fix(ui-core): four product screens stop widening the page at narrow widths - #772
Merged
Conversation
…ning the page Both rows put Nova buttons in a row that could not give. The schema's note field is 224px and its two controls another 220 with the gaps, which comes to 460 and stops fitting somewhere around 500px; the gallery's batch actions did the same a little later. Measured against the running stack, the schema overflowed the document by 204px at 320, 149 at 375 and 44 at 480, and the gallery by 118 and 63 - the residual width both surfaces were carrying into this phase. A button that shrinks is a button whose label truncates, so `shrink-0` on the primitive is right and the row is the thing that had to change. Both now wrap, and the schema's note takes the full width while it is wrapped and its own 224 once the row fits again. The gallery's state filter needed the other answer. It is one joined pill of five segments, 324px wide, so it is wider than the narrowest viewport on its own and wrapping inside the pill would break the control rather than fit it. It scrolls within its own row, which is what the project navigation does with the same shape at the same width.
…g the page Two more of the same defect, found by sweeping every product route rather than the two that were already known. Home's resume row put a thumbnail, a column of counts and a 178px control on one line and overflowed by 35px at 320. The dataset tabs overflowed by 33: each trigger carries a label and a count, so `flex-1` cannot shrink it past its own content. Home's row wraps. The tab strip scrolls inside its row instead, for the reason the project navigation's does - a tab that truncates its label to fit is a tab nobody can read, and the strip is the product's one tab shape rather than a composition this screen is free to restyle.
… overflow Five scenarios, one per route, at 320, 375 and 480. All four fixes in this branch were found by measuring rather than by looking, and without a guard the next fixed-width row puts the scrollbar back. The assertion is on the document, not on elements: a local scroller that does not widen the page is not a defect, and this file's own navigation strip is deliberately one. An element-level check would have to special-case it, and would have called the dataset tab strip broken after this branch fixed it. One test per route rather than one sweep over fifteen navigations, which runs past the suite's 20s budget and reports a timeout where it means the test did too much. Verified by breaking it: with the wrap fixes reverted, schema and the batch detail fail with the width that broke them, and both pass again restored.
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.
Four product screens widened the page at narrow widths. Two of them were known
and had been carried through three phases; the other two were found by measuring
every route instead of the two anybody remembered. A guard now holds the floor.
This is the responsive slice of the cross-product quality pass, landed on its own
rather than held back for the rest of it: it closes both outstanding debts, it
stands up without the batches that follow, and a diff that also carried
accessibility, theme and motion work would be a great deal harder to read.
What was measured
Ten routes at 320, 375, 480, 768, 1024, 1280 and 1536, driven in chromium against
a running stack. The test is the document's own overflow -
documentElement.scrollWidth - clientWidth- because that is the thing a persondrags sideways. A local scroller that does not widen the page is not a defect,
and the project navigation strip is deliberately one.
Seven defects, on four surfaces:
The schema figure is the one worth reading twice: the row measured
right=524,which is the residual width recorded when this was first deferred - "~524px
content at a 500px viewport". It is the same defect, unchanged, not a new one
wearing its clothes.
What changed, and at which layer
A button that shrinks is a button whose label truncates, so
shrink-0on theprimitive is correct and nothing here touches it. Every fix is a composition:
full width while the row is wrapped and its own 224 once the row fits again.
line rather than pushing the page.
row. Both are atomic - a trigger carries a label and a count, a filter is one
joined pill of five segments - so neither can shrink without truncating, and a
tab nobody can read costs more than a scroll does. The project navigation
answered the same shape the same way, so this follows that rather than
inventing a second answer.
Two things the sweep taught, recorded because they will come up again
A culprit search has to skip local scrollers. The first pass blamed the
project navigation on three different screens. Its strip is
overflow-x-autobydesign and already has a test proving it does not widen the page at 320: its
children sit past the viewport without widening anything. Counting them hid the
real causes - the dataset tab strip only appeared once they were filtered out.
Fixing the widest defect uncovers the next. With the gallery's header wrapped
the screen still overflowed, now by way of the state filter, which had been
sitting behind the larger number the whole time. The sweep was re-run after each
fix rather than trusted once.
The guard
Five scenarios in
project-nav.spec.ts, one per project route, at all three floorwidths. It asserts the document rather than elements, precisely so a legitimate
local scroller is not a false positive - an element-level check would have to
special-case the navigation strip, and would call the dataset tabs broken after
this branch fixed them.
One test per route rather than one sweep: fifteen navigations in a single test
runs past the suite's 20s budget, and the timeout reads as "the floor is broken"
when it means the test did too much.
It was verified by breaking it. With the wrap fixes reverted, schema and the batch
detail fail, each naming the width that broke it; restored, all five pass.
Test plan
Every command ran inside Docker/Linux; no repository validation ran natively on
the host.
Node gates, full tree and frozen install in
node:24-bookworm:Browser, in
mcr.microsoft.com/playwright:v1.62.1-noblewithCI=1:The 261 matters more than the five: these are layout changes on four screens that
the suite already asserts behaviour for, so the existing scenarios staying green
is what says the wrapping did not move anything a person relies on.
Scope
Still open
The rest of the quality pass is untouched and unclaimed by this branch: content
stress, accessibility, keyboard operation, focus restoration and layering,
light/dark, motion and reduced motion, scroll ownership, dialog and popover
safety at small viewports, browser zoom, a visual-regression baseline, spacing
consistency, and the async/empty/error states.
Two notes for whoever picks those up. Gallery's state filter and the dataset tab
strip now scroll horizontally at 320 rather than stacking, which is a tradeoff
worth a second opinion. And the sweep only covered a project that exists with the
data it happens to hold; hostile content - a very long class name, a long model
reference, a large annotation count - is the next thing to point it at.