Conversation
…I, vaul) Closes #113. Picker chrome could become unclickable inside Radix Dialog portals, and clicking it dismissed the host dialog. Three orthogonal issues surfaced during manual verification: 1. Modal-aware chrome - Add `defangOutsideHandlers` and apply it to bar, picker, params panel, annotation overlay, global bar, and design panel host. - Sets `pointer-events: auto !important` on interactive chrome so Radix's `body { pointer-events: none }` modal scroll-lock can't silence our UI. - Stops `pointerdown` / `mousedown` / `focusin` propagation at the chrome boundary so DismissableLayer / FocusScope outside-handlers never fire for clicks that land on us. 2. detectPageTheme: misread transparent body as black - `getComputedStyle(body).backgroundColor` returns `rgba(0,0,0,0)` when no bg is set; the prior regex captured (0,0,0) and ignored alpha, calling every default-bg page "dark." - Honor alpha, walk body → html, fall back to `prefers-color-scheme` only when both are transparent. 3. Exit X invisible on host pages with `button { padding: ... }` - Every other chrome button sets padding inline; exitBtn didn't. Host resets like `button { padding: 0.5rem 1rem }` (in the new fixture, common in the wild) inflated the 24x24 button into 56x40 and pushed the SVG into a non-rendering region — DevTools showed the right styles, the X just didn't paint. - Pin `padding: 0` + `box-sizing: border-box`, match the toggle icon spec (14 / stroke 1.5 / textDim → text on hover). 4. Toast no longer obscures the global bar - Position the toast above globalBarEl's actual rect instead of a fixed bottom: 16px that overlapped the bar's bottom: 14px. Test coverage: new `vite8-react-radix-dialog` fixture exercises the full pick → Go → cycle → Accept loop with `@radix-ui/react-dialog` + `Portal` + `Overlay` + `Content`. Without the fix, clicking Go dismisses the dialog and unmounts the picked element. All 20 live e2e fixtures pass; all 180 unit tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deploying impeccable with
|
| Latest commit: |
630e586
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c59e501c.impeccable-2rv.pages.dev |
| Branch Preview URL: | https://feat-live-modal-host-friendl.impeccable-2rv.pages.dev |
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.
Summary
Closes #113. The live picker became unclickable inside Radix Dialog portals, and clicking it dismissed the host dialog. Fixes that, plus three adjacent issues that surfaced during manual verification on the new fixture.
What's in here
defangOutsideHandlershelper applied to bar, action picker, params panel, annotation overlay, global bar, and design panel host. Setspointer-events: auto !importantso Radix's modal scroll-lock can't silence our UI, and stopspointerdown/mousedown/focusinpropagation at the chrome boundary so DismissableLayer / FocusScope outside-handlers never fire for our clicks. Click events still bubble normally.detectPageThemecorrectness — the prior regex readrgba(0,0,0,0)as black, mislabelling every default-background page as dark. Now honors alpha, walksbody → html, and falls back toprefers-color-schemeonly when both are transparent.button { padding: 0.5rem 1rem }inflated the 24×24 button into 56×40 and pushed the SVG out of view. Pinnedpadding: 0+box-sizing: border-box, dropped to a 14 / stroke 1.5 spec that matches the other toggle icons in perceived weight.bottom: 16px, overlapping the bar'sbottom: 14px. Now reads the bar's actual rect and parks itself ~12 px above its top edge.Test plan
bun run test— 180/180 unit + static fixture checks passbun run test:live-e2e— 20/20 fixtures pass (19 prior + newvite8-react-radix-dialog)vite8-react-radix-dialog: pick element inside a real@radix-ui/react-dialogportal → bar appears above the lightbox, every chip / Go / cycle / Accept click works, dialog stays open through the full session.button { padding: 0.5rem 1rem }.🤖 Generated with Claude Code
Note
Medium Risk
Changes global event propagation and
pointer-eventsbehavior for multiple floating UI roots, which could subtly affect interactions/focus behavior on some host pages. Scope is limited to live-picker chrome and fixture/docs updates with no data/security impact.Overview
Improves live-picker robustness when used inside modal dialogs/portals (e.g., Radix, Headless UI, vaul). Adds
defangOutsideHandlersand applies it to the bar, action picker, params panel, annotation overlay, global bar, and design panel host to forcepointer-events: auto(where appropriate) and stop early pointer/focus event propagation so host “outside click/focus” dismiss logic doesn’t interfere.Also fixes a few adjacent UI issues: toast positioning now avoids overlapping the global bar,
detectPageThemenow ignores transparentrgba(...)backgrounds and falls back more safely, and the exit “X” button is styled to resist host CSS resets. Adds a newvite8-react-radix-dialogframework fixture for e2e coverage and updates the craft reference name (Neon→NeoMirai).Reviewed by Cursor Bugbot for commit 630e586. Bugbot is set up for automated code reviews on this repo. Configure here.