Skip to content

Reflow the footer control strip instead of scrolling it off screen - #608

Merged
thcp merged 3 commits into
mainfrom
fix/footer-fit
Sep 9, 2026
Merged

thcp merged 3 commits into
mainfrom
fix/footer-fit

Conversation

@thcp

@thcp thcp commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Closes #586

The problem

The footer control row is flex-wrap: nowrap with flex: none children inside an overflow-x: auto box, so it never reflows. Past a certain width it just scrolls, silently, and controls sit off the right-hand edge with nothing to say they are there.

Measured against a real six-stem track, the strip wants 1443px. It is not a high-DPI bug: it already overflows by 88px on a maximized 1080p window at 100% scaling. Scaling only makes it dramatic.

The fix

The click-track options are 706px of that 1443px, about half the row. When the strip runs out of room they stop being one long line and become a wrapped block. Nothing is hidden, nothing moves behind a disclosure, and .daw-footer is min-height precisely so a taller row is accommodated rather than clipped.

That last part is deliberate. #269 decided these options stay visible, with "no popover, no click to reveal them". A popover was the obvious fix and I built it first. Besides reversing that decision, an absolutely positioned panel anchored inside the strip is clipped by it, because a box with one axis scrollable computes the other to auto as well: it rendered and could not be clicked. Wrapping needs none of that machinery, so the popover was thrown away.

Overflow on the e2e fixture, before to after:

viewport before after
2200 fits fits, layout untouched
1920 (maximized 1080p) +88 fits
1680 +328 fits
1536 (4K at 250%, the report) +472 fits
1440 +568 +86
1280 +728 +246

Below about 1440 it still scrolls. Closing that gap needs something to be hidden, which is a product decision rather than a layout one, so it is not made here.

Why JS and not a media query

The space available is not a function of the viewport. Collapsing the library sidebar moves it by 324px (390 to 66), which flips the answer on its own: at 1920 the strip overflows with the sidebar open and fits comfortably with it shut. A breakpoint keyed on window width would collapse a footer with room to spare, and miss one without.

A correction worth recording

The strip is not wider in other languages. The original analysis argued for measurement on the basis of a 63px spread between locales; measured across en/fr/de/pl it is 1443px in all four, because the group labels are 10px uppercase and narrower than the controls beneath them. The refit on language change is kept because select and button text can vary, not because the labels do. The sidebar is the real reason, and it is a stronger one.

Tests

tests/e2e/footer-fit.spec.mjs covers the wide case being untouched, the reported geometry fitting, every click control staying visible and clickable once wrapped, the strip reopening when room returns, and the page never scrolling sideways.

Nothing in the suite asserted on layout width before, which is why this shipped. Note that Playwright's viewport is 1280x720, so every existing spec was already running in an overflowing footer; click-track.spec.mjs passes unchanged against this.

Found in passing

#607: the desktop window's minWidth: 1024 is in logical pixels, so at 250% scaling it demands 2560 physical and can exceed the screen. Not fixed here, since this change is layout-only and does not touch the desktop shell.

Thales added 3 commits September 9, 2026 11:06
The footer control row is `flex-wrap: nowrap` with `flex: none` children inside
an `overflow-x: auto` box, so it never reflows. Past a certain width it just
scrolls, silently, and controls sit off the right-hand edge with nothing to say
they are there.

Measured against a real six-stem track, the strip wants 1443px. That means it
already overflowed by 88px on a maximized 1080p window at 100% scaling, and by
472px at the 1536px logical viewport a 4K panel gets at 250% Windows scaling,
which is the geometry from the report. It is not a high-DPI bug; scaling only
makes it dramatic.

The click-track options are 706px of that 1443px, about half the row. When the
strip runs out of room they now stop being one long line and become a wrapped
block, which is what the row has space for. Nothing is hidden, nothing moves
behind a disclosure, and `.daw-footer` is min-height precisely so a taller row
is accommodated rather than clipped.

That last part is deliberate. #269 decided these options stay visible with "no
popover, no click to reveal them". A popover was the obvious fix and was tried
first; besides reversing that decision, an absolutely positioned panel anchored
inside the strip is clipped by it, because a box with one axis scrollable
computes the other to `auto` as well. It rendered and could not be clicked.
Wrapping needs none of that machinery.

Measured on the e2e fixture, overflow before -> after:

  2200   fits  ->  fits, layout untouched
  1920    +88  ->  fits
  1680   +328  ->  fits
  1536   +472  ->  fits     (the reported window)
  1440   +568  ->  +86
  1280   +728  ->  +246

Below about 1440 it still scrolls. Closing that needs something to be hidden,
which is a product decision rather than a layout one.

Why this is measured in JS rather than written as a media query: the space
available is not a function of the viewport. Collapsing the library sidebar
moves it by 324px (390 -> 66), which flips the answer on its own -- at 1920 the
strip overflows with the sidebar open and fits comfortably with it shut. A
breakpoint keyed on window width would collapse a footer with room to spare and
miss one without.

Worth recording, since it is the argument the fix was originally designed
around and it does not hold: the strip is *not* wider in other languages.
Measured across en/fr/de/pl it is 1443px in all four, because the group labels
are 10px uppercase and narrower than the controls beneath them. The refit on
language change is kept because select and button text can vary, not because
the labels do.

tests/e2e/footer-fit.spec.mjs covers the wide case being untouched, the
reported geometry fitting, every click control staying visible and clickable
once wrapped, the strip opening back up when the room returns, and the page
never scrolling sideways. Nothing in the suite asserted on layout width before,
which is why this shipped.

Closes #586
…hat could not fail

Four review findings.

Picking a 7/8 meter, or "Custom...", un-hides the grouping input, its label,
or the custom-beats box, which is 120-160px appearing inside the strip with no
refit. The ResizeObserver cannot see it either: the strip's own box is
flex-sized so its width does not move, and its height does not move because
everything on the row is one line of 34px controls. So the strip went straight
back to the silent sideways scroll this branch exists to remove. Hooked into
_renderMetroGrouping, which every path that shows or hides those controls
already funnels through.

collapse-tight was making the widest cluster wider. `.footer-clusters
.collapse-tight .footer-group-body` at (0,3,0) outranked
`.footer-group-position .footer-group-body { gap: 4px }` at (0,2,0), so the
Position cluster's internal gaps went 4px to 6px at the exact moment the code
was trying to reclaim width. Dropped: the eight cluster gaps going 16px to 8px
are the real win, and re-measured on a real six-stem track the removal changed
nothing (1440 went from +86 to +84, and 1536 still fits exactly).

The LEVELS comment still described the popover from the first attempt, which
was thrown away. It now describes the wrapping that is actually there.

"the page itself never scrolls sideways" is deleted rather than fixed. It
could not fail: `html, body { overflow: hidden }` means the document has no
horizontal scroll to report whatever the footer does, and .footer-clusters is
its own overflow-x box so its overflow never reaches an ancestor either.
Verified by disabling the fix completely, at which point it still passed, and
it was paying for four full openStudio loads to do it. "the reporter's
geometry no longer overflows" is the test that does fail without the fix, and
it measures the same property where it can actually be observed.
@thcp
thcp marked this pull request as ready for review September 9, 2026 12:35
@thcp
thcp merged commit 23eaf4d into main Sep 9, 2026
10 checks passed
@thcp
thcp deleted the fix/footer-fit branch September 9, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: StemDeck UI Scaling in Windows

1 participant