Ok, I’ve tried to do this with hooks, but I have some very weird behaviour:
Hooks.Highlight = {
updated() {
if (this.handler) {
clearTimeout(this.handler);
}
if (this.el.dataset.highlight === "on") {
const handler = setTimeout(() => {
this.el.setAttribute("data-highlight", "off");
}, 1000);
this.handler = handler;
}
}
}
attr(:id, :any, required: true)
attr(:trigger, :any)
attr(:duration, :integer)
slot(:inner_block)
attr(:rest, :global)
def highlight(assigns) do
assigns =
assign_new(assigns, :highlight, fn ->
if changed?(assigns, :trigger) do
"on"
else
"off"
end
end)
~H"""
<div id={@id} data-id={@id} phx-hook="Highlight" {@rest} data-highlight={@highlight}>
<%= render_slot(@inner_block) %>
</div>
"""
end
defmodule Storybook.CoreComponents.Highlight do
use PhoenixStorybook.Story, :example
import Elixir.DomainModellingWeb.CoreComponents
@impl true
def mount(_params, _session, socket) do
{:ok, assign(socket, value: 10, value2: 20, value3: 30)}
end
@impl true
def render(assigns) do
~H"""
<.highlight
id="1"
trigger={@value}
duration={500}
class="data-[highlight=on]:bg-primary-500 bg-neutral-900 text-white"
>
<div class="p-4">
<button phx-click="click">Value 1: <%= @value %></button>
</div>
</.highlight>
<.highlight
id="2"
trigger={@value2}
duration={500}
class="data-[highlight=on]:bg-primary-500 bg-neutral-900 text-white"
>
<div class="p-4">
<button phx-click="click2">Value 2: <%= @value2 %></button>
</div>
</.highlight>
<.highlight
id="3"
trigger={@value3}
duration={500}
class="data-[highlight=on]:bg-primary-500 bg-neutral-900 text-white"
>
<div class="p-4">
<button phx-click="click3">Value 3: <%= @value3 %></button>
</div>
</.highlight>
"""
end
@impl true
def handle_event("click", _, socket) do
{:noreply,
socket
|> update(:value, fn value ->
value + 1
end)}
end
@impl true
def handle_event("click2", _, socket) do
{:noreply,
socket
|> update(:value2, fn value ->
value + 1
end)}
end
@impl true
def handle_event("click3", _, socket) do
{:noreply,
socket
|> update(:value3, fn value ->
value + 1
end)}
|> dbg
end
end
The strange behaviour I get: every time I click, all previous highlight components that have been clicked also run the updated
hook.
The items that haven’t been previously updated, don’t get in the updated
hook.
What’s even stranger is that for these items that get in the update hook, the data-highlight
changes to “on”.
On the elixir side, nothing happens in the def highlight
though.
Here you can see the behaviour: Screen Recording 2023-09-13 at 17.25.39.mov - Google Drive
That seems like a bug, but I guess there’s a bigger change that I’m doing something wrong.