fix: dual-view dropdown columns overflowed the panel (#258 regression) - #263
Merged
Conversation
Reported as the dropdown items not fitting in dual view. They did not, and the cause turned out to be two separate mistakes in #258 -- one layout, one worse than layout. **The overflow.** Adding a key chip to each input row meant giving the name `white-space: nowrap` so it would ellipsise rather than wrap. `.column-layout` uses `grid-template-columns: 1fr 1fr`, and `1fr` is `minmax(auto, 1fr)` whose auto minimum is the item's MIN-CONTENT size. With wrapping text that is the longest word; with nowrap it is the entire label. So the tracks computed to 339.758px each inside a 358px panel and the columns spilled roughly 320px out of the dropdown. That is the same trap as flex `min-width: auto`, one level up -- and the flex one was already fixed in this very file, on the name span, which is how the grid one got missed. Fixed with `minmax(0, 1fr)`. **The chip should not have been there at all.** `1`-`4` call selectInput() with the default side='both' and set BOTH feeds. Clicking a row in the Left column calls selectInputForSide(id, 'left') and sets one. So a chip on a per-side row documented a key that does something different from the control it sat next to. Chips now render on the single-view list only, where one feed is shown and setting both is the same thing to the operator as setting that one. That also resolves the fit on its own terms: a dual column is ~173px against the single list's ~358px, and a name plus a chip left about 98px for the name -- enough to turn "Blackmagic UltraStudio Recorder 3G" into "Blackmagic Ul...", which is useless for telling two capture cards apart. Name truncation is scoped to the single list with the chip. Dual-column names wrap again, exactly as they did before #258. Measured after the fix, dual view at a 400px panel: tracks 173px + 173px + 12px gap against a 358px container, no chips in the columns, every name fully visible with nothing truncated, panel inside the viewport. Single view keeps its 1-4 chips at 322px rows, where the long Blackmagic label is not even truncated. Two new tests, 557 -> 559, both pinning halves of the fix that would each have hidden the other: that the grid uses minmax(0, 1fr) and not a bare 1fr, and that nowrap is scoped to the list that has a chip. Verified by reverting each in turn, plus putting the chip back on the dual columns.
5 tasks
BernardJen
added a commit
that referenced
this pull request
Aug 20, 2026
The mirror of the input dropdown, anchored to the bottom edge instead of the top: same hover-to-reveal, same 0.3s slide, same touch-open class, same cursor handling, corners rounded on the side away from the edge it hangs off. Rows come from shortcuts.js, which makes this the third consumer of that list after the keydown handler and the Settings table (#258). It shows the SAME rows as the table rather than a shortened "important ones" set -- that would have been a fourth hand-maintained list, which is the thing that list exists to remove. A test asserts the two carry identical chips. Wider than the dropdown on purpose. The dropdown is a picker capped at 400px; this is a reference table and the wall is 5:1, so an auto-fit grid turns twelve rows into three rows of four columns instead of one column twelve deep. Measured at a 1500px viewport: 1100x183, four 244px tracks, sitting on the bottom edge, no scrolling. Two things measuring caught that reasoning would not have: **A fixed-position element is shrink-to-fit, so `max-width` caps it but never expands it** -- and `repeat(auto-fit, minmax(...))` needs a DEFINITE width to work out its column count. With only a max the panel sized to its content minimum: 467px wide and one column at 1500px, which is precisely the long-list-off-the-bottom the grid was there to prevent. Fixed with an explicit `width: min(1100px, 92vw)`. **Three of twelve labels were ellipsising at 1100px**, including both "(if the remote keyboard is enabled)" caveats -- the part that makes those two rows mean anything. Labels now wrap. Uneven row heights are the cheaper cost; a legend that hides what a key does defeats itself. Same trade as the dual-column names in #263. Escape closes it, alongside the other panels. 13 new tests, 582 -> 595. Verified by breaking each: dropping the explicit width fails 1, truncating labels 1, removing the Escape close 1, and rendering a shortened set 4 -- including the test that pins the legend and the Settings table to identical chips. One note on verification method. The Browser pane reports document.hidden: true and never goes visible, so the transition clock is frozen and getComputedStyle returns the pre-transition value indefinitely. Reading the panel's transform after a toggle showed translateY(0) in both states, which looked like a broken rule and was not -- it was the same trap as #262. Disabling the transition makes the change land in one style recalculation, which is readable regardless: closed translateY(183) fully off-screen, open translateY(0) on the bottom edge, trigger 0 -> 0.7 with the cursor.
BernardJen
added a commit
that referenced
this pull request
Aug 20, 2026
The mirror of the input dropdown, anchored to the bottom edge instead of the top: same hover-to-reveal, same 0.3s slide, same touch-open class, same cursor handling, corners rounded on the side away from the edge it hangs off. Rows come from shortcuts.js, which makes this the third consumer of that list after the keydown handler and the Settings table (#258). It shows the SAME rows as the table rather than a shortened "important ones" set -- that would have been a fourth hand-maintained list, which is the thing that list exists to remove. A test asserts the two carry identical chips. Wider than the dropdown on purpose. The dropdown is a picker capped at 400px; this is a reference table and the wall is 5:1, so an auto-fit grid turns twelve rows into three rows of four columns instead of one column twelve deep. Measured at a 1500px viewport: 1100x183, four 244px tracks, sitting on the bottom edge, no scrolling. Two things measuring caught that reasoning would not have: **A fixed-position element is shrink-to-fit, so `max-width` caps it but never expands it** -- and `repeat(auto-fit, minmax(...))` needs a DEFINITE width to work out its column count. With only a max the panel sized to its content minimum: 467px wide and one column at 1500px, which is precisely the long-list-off-the-bottom the grid was there to prevent. Fixed with an explicit `width: min(1100px, 92vw)`. **Three of twelve labels were ellipsising at 1100px**, including both "(if the remote keyboard is enabled)" caveats -- the part that makes those two rows mean anything. Labels now wrap. Uneven row heights are the cheaper cost; a legend that hides what a key does defeats itself. Same trade as the dual-column names in #263. Escape closes it, alongside the other panels. 13 new tests, 582 -> 595. Verified by breaking each: dropping the explicit width fails 1, truncating labels 1, removing the Escape close 1, and rendering a shortened set 4 -- including the test that pins the legend and the Settings table to identical chips. One note on verification method. The Browser pane reports document.hidden: true and never goes visible, so the transition clock is frozen and getComputedStyle returns the pre-transition value indefinitely. Reading the panel's transform after a toggle showed translateY(0) in both states, which looked like a broken rule and was not -- it was the same trap as #262. Disabling the transition makes the change land in one style recalculation, which is readable regardless: closed translateY(183) fully off-screen, open translateY(0) on the bottom edge, trigger 0 -> 0.7 with the cursor.
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.
Reported: the dropdown items do not fit in dual view. They did not — and the cause
was two separate mistakes in #258, one of them worse than a layout problem.
The overflow
Giving each input row a key chip meant giving the name
white-space: nowrapso itwould ellipsise rather than wrap.
.column-layoutusesgrid-template-columns: 1fr 1fr, and1frisminmax(auto, 1fr)whose autominimum is the item's min-content size. With wrapping text that is the longest
word; with
nowrapit is the entire label.Measured before the fix:
339.758px 339.758px358pxFixed with
minmax(0, 1fr). This is the same trap as flexmin-width: auto, onelevel up — and the flex one was already fixed in this very file, on the name
span, which is exactly how the grid one got missed.
The chip should not have been in the dual columns at all
Checking why the columns were cramped turned up something worse:
1–4callselectInput()with the defaultside='both'→ sets both feedsselectInputForSide(id, 'left')→ sets oneSo the chip documented a key that does something different from the control beside
it. Chips now render on the single-view list only, where one feed is shown and
setting both is the same thing to the operator as setting that one.
That resolves the fit on its own terms too. A dual column is ~173px against the
single list's ~358px; a name plus a chip left about 98px for the name, which turns
Blackmagic UltraStudio Recorder 3GintoBlackmagic Ul…— useless for tellingtwo capture cards apart. Name truncation is now scoped to the list that has a chip,
so dual-column names wrap again exactly as they did before #258.
Measured after
Dual view, 400px panel:
173px + 173px + 12pxgap against a358pxcontainer — fitsSingle view:
1–4chips present, 322px rows, uniform row heights, and the longBlackmagic label is not even truncated at that width.
Tests
Two new, 557 → 559. They pin both halves of the fix, because either alone would
have hidden the other:
1fr 1frnowrapre-applied to the dual columnsjsdom does no layout, so the CSS assertions check the declaration rather than
measuring — the measurements above came from a real browser.
On how this got shipped
My verification of #258 screenshotted the dropdown in Single mode only. The
two-column layout is the one that breaks, and I never looked at it. The mode was
one click away and I had the browser open.