fix(overlay): open overlays above later rows and at their real position - #296
Merged
Merged
Conversation
added 2 commits
September 25, 2026 08:29
ui-overlay-host isolates every Select and Dropdown so a pointer can reach an overlay that hangs outside its root. The isolation also confines the overlay's z-index to its host, which paints at z-index auto in tree order, so a later positioned sibling of an ancestor covered the open list. A Select in a table row is where it shipped: the next .table__row paints over the options and they cannot be pressed. While anything inside the host is open, the host takes the overlay's layer.
The width limits reached the element through the style signal only after the first update had measured it, so the overlay was measured at its unconstrained width. For Select, whose CSS floor is max(100%, 14rem) on a fixed box, that is the whole viewport, and the left clamp pinned the list to the screen edge. A desktop browser moved it into place a frame later through the ResizeObserver, which read as a blink on the left; chuzz, whose observer does not fire, left it there. The same limits are now written onto the element before it is measured, so the first position is the final one. Measured on a Select in a table row: chuzz-headless placed the list at left 88 under a trigger at 696 and now at 696; the desktop browser's first write was left 8 under a trigger at 765 and is now 765.38.
added 3 commits
September 25, 2026 13:37
The host action was pinned to a chuzz revision from before headless releases existed, so every run compiled that source against the current registry. Its unlocked dependencies moved on (tokio features, blitz-control-protocol 0.5.3) and it stopped compiling, turning every PR red in the host step. The pin now names chuzz master, whose action downloads the verified chuzz-headless 0.1.39 release.
One named a session scratchpad file under /private/tmp by its full path, the other ran git -C against /Users/revenge/code/UI. Neither path exists anywhere but the machine the review ran on. The scratch file is described instead, and the git command runs in the checkout it is read from.
0.1.40 reports the live viewport size and fires ResizeObserver, and pulls ps-blitz 0.4.12 with MutationObserver, so the QA host behaves like the browser it stands in for on overlays and observers.
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.
Two overlay bugs, found on crates.vip's admin page (a role Select in each table row).
1. The open list painted under the next row
ui-overlay-hostgives Select and Dropdownisolation: isolate, so a pointer can reach an overlay that hangs outside its root. The same stacking context confines the overlay'sz-index: 80to its host, and the host paints atz-index: autoin tree order, so the next positioned.table__rowcovered the open options.Fix (
overlayHost.css):.ui-overlay-host:has([data-open="true"]) { z-index: 80; }. The host takes the overlay's layer only while something inside it is open. Isolation stays.2. The list opened at the screen's edge for a frame (and stayed there in chuzz)
createOverlayPositionmeasured the overlay before its width limits landed (they arrive through the style signal after the first update). Select's CSS floor ismin-width: max(100%, 14rem)on a fixed box, so the first measurement was viewport-wide and the left clamp pinned the list to the edge. A desktop browser fixed it a frame later through the ResizeObserver, which read as a blink on the left. chuzz's ResizeObserver never fires, so the list stayed at the edge.Fix (
overlayPosition.ts): write the samemax-width/min-widthonto the element before measuring, so the first position is the final one. The write is skipped for an overlay stand-in without astyle(the tests measure with one); an unguarded throw there halted reactivity for the whole test run.Measured
A Select in a table row, the popover's first written position:
With both fixes, the topmost element over the next row at the bottom of the open list is an option.
Checks run locally
bun test --conditions=browser: 321 pass, 0 fail (master: the same 321).bunx tsc --noEmit,bun run build,bun run check:api,bun run smoke,bun run check:package: pass.bun run lint: fails on master with the same 134 pre-existing errors; nothing new in the two changed files.Separate chuzz bugs, not fixed here
ResizeObserveris defined but its callback never fires.window.innerWidthreports 1440 while the page lays out at 1344.Hard-coded local paths
docs/reviews/2026-07-27-ai-smell-deadcode-tests-docs.mdnamed a scratchpad file by its full/private/tmp/...path, anddocs/reviews/2026-07-27-theming-css-build-perf.mdrangit -C /Users/revenge/code/UI. The first is described instead; the second runs in the current checkout.