fix: listbox and dropdown with enter transitions - #28
Open
RobertJoonas wants to merge 1 commit into
Open
RobertJoonas wants to merge 1 commit into
RobertJoonas wants to merge 1 commit into
Conversation
When using transitions for dropdown/listbox options becoming visible, the opening click is already considered an "outside" click from the options wrapper's perspective, which ends up closing the options before it even renders. The fix is to not consider trigger button clicks as outside clicks. Since `phx-click-away` needs to be attached to a single element, and attaching it to a wrapper element would mean introducing a dead-zone (due to possibly unequal widths between the trigger and options) the option that we're left with is to do it with a document click handler in the hook. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a bug where the "opening" click on a dropdown/listbox trigger button is already considered an "outside" click from the options wrapper's perspective, which ends up closing the options before it even renders.
The fix is to not consider trigger button clicks as outside clicks.
Since
phx-click-awayneeds to be attached to a single element, and attaching it to a wrapper element would mean introducing a dead-zone (due to possibly unequal widths between the trigger and options) the option that we're left with is to do it with a document click handler in the hook.The bug doesn't surface until an animation is used, which makes the LiveView JS internals behave differently:
Scenario A — transition configured:
handleToggle()handler runs first, since its listener is on the button element.showListboxAndFocus(), which tells LiveView "show the panel" via execJS(...).el.dispatchEvent(new Event("phx:show-start"))— synchronously, right there, still inside step 2's call stack.handleShowStart(), which marks the panel as now open.handleToggle()finishes. The click event keeps bubbling upward.document. LiveView's click-away check now runs — still part of the same original click, just later in the bubble. It looks at the panel: is it open? Yes (step 4 already flipped that, moments ago). Was the click "outside" it? Also yes (button is a sibling of the panel, not inside it). Verdict: close it.Scenario B — no transition:
1–2. Same as above.
3. LiveView doesn't call dispatchEvent yet — it schedules it via
requestAnimationFramefor the next frame.4.
handleToggle()finishes. Nothing has told our hook the panel is "open" yet.5. Click keeps bubbling, reaches document, LiveView's click-away check runs. It looks at the panel: still marked closed (step 3 hasn't fired yet). Verdict: nothing to close. No-op, like it's always been.
6. The click event is now fully done and out of the picture. Only after that — on the next animation frame — does LiveView finally call
dispatchEvent(phx:show-start), and the panel opens for real, safely, with no click-away check left to race against.So the difference emerges from step 3, where behaviour is determined by existence of transition in/out classes (source code ref)