Sebb

Sebb

When LV change-detection results in new elements rendered, what is the recommended way to do that?

Is this OK? (works, but not sure if right way to do it)

defmodule TestlvtransitionsWeb.MyLive do
  use TestlvtransitionsWeb, :live_view

  def render(assigns) do
    ~H"""
    <style>
      @keyframes fadein {
        from { opacity: 0.2; }
        to { opacity: 1; }
      }
      .new-box { animation: fadein 1000ms linear; }
    </style>
    <div phx-click="show1">SHOW 1</div>
    <div phx-click="show2">SHOW 2</div>
    <div :if={@show1} class="bg-red-500 fadein">HELLO</div>
    <div :if={@show2} class="bg-red-500 fadein">HELLO</div>
    """
  end

  def mount(_, _, socket), do: {:ok, assign(socket, show1: false, show2: false)}

  def handle_event("show1", _, socket), do: {:noreply, assign(socket, :show1, true)}
  def handle_event("show2", _, socket), do: {:noreply, assign(socket, :show2, true)}
end

Showing Posts 1 to 10

trisolaran

trisolaran

I would give phx-mounted a try :slight_smile:

Sebb

Sebb OP

I’m having some trouble with that.
I think I have to match the transition-duration property value to the time option. (the docs don’t do that, but I do not see how else this should work). OK I did that. Also in class I set the same opacity as in the start-slot of the 3-tuple, otherwise the element appears-vanishes-appears. But still I do not get a smooth transition, it just pops up.

<div
  :if={@show1}
  phx-mounted={
    JS.transition({"ease-out duration-1000", "opacity-20", "opacity-100"}, time: 1000)
  }
  class="bg-red-500 opacity-20"
>

There is a solution with JS.show here: Achieving tailwind enter/leave transitions with LiveView.JS - #7 by paulstatezny

<div
  :if={@show1}
  style="display: none"
  phx-mounted={
    JS.show(
      transition: {"ease-linear duration-1000", "opacity-20", "opacity-100"},
      time: 1000
    )
  }
  class="opacity-20 bg-red-500"
>

:face_with_monocle:

derpycoder

derpycoder

How about Live Motion?

Sebb

Sebb OP

I’d rather not pull in another dependency for this trivial task. The CSS-animation works fine, but I still hope there is a way with LV (expect the hacky solution with JS.show).

LostKobrakai

LostKobrakai

Take a look at animation-iteration-count. You don’t need JS or LV to limit an css animation to play only once.

kwando

kwando

I cant wrap my head around how to reliable use JS hooks to animate. There are some unintuitive things happening when animating stuffs and mixing JS hooks with server rendering :neutral_face: problem is probably on my end, but still

Sebb

Sebb OP

You are answering the questions I did not ask yet, thats next level :grin:
Actually trying to figure out one edge case now.

The version in the OP (animate) works fine (and also once as animation-iteration-count is set to 1 (implicitly as its the default). But consider this:

 <style>
      @keyframes fadein { from { opacity: 0.2; } to { opacity: 1; } }
      .new-box { animation: fadein 1000ms linear; }
 </style>
 <div phx-click="show1">SHOW red</div>
 <div phx-click="show2">SHOW blue</div>
 <div :if={@show1} class="bg-red-500 fadein">HELLO</div>
 <div :if={@show2} class="bg-blue-500 fadein">HELLO</div>

When one clicks “SHOW blue” first and then “SHOW red” the animation is blue both times. I have an idea whats happening and maybe one would have to set update-ignore or sth, but its not nice.

I think its just not really fully working right now.

trisolaran

trisolaran

Yep. I came to the same conclusion

I see that your element doesn’t have a an id. I think it needs a unique id assigned to work, otherwise LV can’t distinguish newly mounted elements from those already existing. phx-mounted works for me, but not if I remove the id. Maybe give it a try

Sebb

Sebb OP

Indeed, that solves the messed up animations. But it does not heal the JS.transition solution.
Here are all three approaches I tried: animation, JS.show (@paulstatezny solution) and JS.transition.
The first two look the same, the third does not work.

<div phx-click="show1">SHOW red</div>
<div phx-click="show2">SHOW blue</div>

<div class="flex flex-col gap-2">
  <div>
    <style>
      @keyframes fadein {
        from { opacity: 0.2; }
        to { opacity: 1.0; }
      }
      .fadein { animation: fadein 1 1000ms linear; }
    </style>
    <div :if={@show1} id="11" class="bg-red-500 fadein">HELLO ANIM 1</div>
    <div :if={@show2} id="21" class="bg-blue-500 fadein">HELLO ANIM 2</div>
  </div>

  <div>
    <div :if={@show1} id="21" style="display: none" class="opacity-20 bg-red-500"
      phx-mounted={JS.show(
          transition: {"ease-linear duration-1000", "opacity-20", "opacity-100"},
          time: 1000)}>HELLO LV.JS/A 1</div>
    <div :if={@show2} id="22" style="display: none" class="opacity-20 bg-blue-500"
      phx-mounted={JS.show(
          transition: {"ease-linear duration-1000", "opacity-20", "opacity-100"},
          time: 1000)}>HELLO LV.JS/A 2</div>
  </div>

  <div>
    <div :if={@show1} id="31" class="bg-red-500 opacity-20"
      phx-mounted={
        JS.transition({"ease-linear duration-1000", "opacity-20", "opacity-100"}, time: 1000)
      }>HELLO LV.JS/B 1</div>
    <div :if={@show2} id="32" class="bg-blue-500 opacity-20"
      phx-mounted={
        JS.transition({"ease-linear duration-1000", "opacity-20", "opacity-100"}, time: 1000)
      }>HELLO LV.JS/B 2</div>
  </div>
</div>
trisolaran

trisolaran

yep forget what I said, I just looked and I’m actually using phx-mounted + JS.show as well.. I’m having a strong déjà vu feeling of having gone through all this already :laughing:

Here’s what works for me:

 <div
            id={elem.id}
            class="hidden"
            phx-mounted={
              JS.show(transition: {"ease-in duration-500", "opacity-0", "opacity-100"}, time: 500)
            }
          >
Hello
</div>

Basically, exactly like your solution. I guess thre’s something broken with phx-mounted={JS.transistion(...)} after all. :broken_heart:

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews