I have a function component for a modal that uses JS commands to handle opening and closing the modal. When the modal is closed, I want to return focus to the trigger that was used to open the modal initially. I have this working except when a user presses the Escape key to close the modal when there are multiple modals on the same page.
Here’s a simplified version of my function component and the JS commands:
def modal(assigns) do
~H"""
<.focus_wrap id={@id} class="modal">
<div role="dialog" aria-modal="true" phx-window-keydown={close_modal(@id)} phx-key="escape">
<%= render_slot(@inner_block) %>
</div>
</.focus_wrap>
"""
end
def close_modal(id) do
%JS{}
|> JS.remove_class("overflow-hidden", to: "body")
|> JS.transition("is-closing", to: "##{id}")
|> JS.remove_class("is-opened", to: "##{id}")
|> JS.focus_first(to: "[data-role=#{id}-trigger]")
end
Because there are multiple modals on the same page and they all have phx-window-keydown
, they all get run when a user hits the Escape key. It seems like the last modal on the page is the one that gets the focus moves to its trigger, even if it wasn’t the modal that was opened.
Is there a way to conditionally trigger the phx-window-keydown
only if that modal is open? I haven’t had any luck so far. I’m using phx-window-keydown
since I want it to fire from any element inside the modal, but maybe that’s not the right way of going about it? Open to any ideas!
I know I could dispatch a custom JS event to handle this on the JavaScript side, but was hoping to leverage the same close_modal
function I’m using on the close button (not shown in the code above) so it’s consistent.