2ada69a40f689bfeafba6878fdf94ed1760e4eaf
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
57fbbdf0d2 |
feat(ui): a shell a phone can be held in
Plan 016 B2, phase 1. Below 600px the grid drops its sidebar column, `bottom-nav` becomes the primary navigation, and the shell fits the viewport instead of scrolling sideways out of it. 600 rather than the sidebar's own 900, because 900 is a laptop and the answer there is a narrower sidebar, which is still a sidebar. Under 600 there is no room for one at all: 360px of viewport over a 200px nav is not a layout. **The tab bar is four destinations and a way to everything else.** Three to five is where touch targets stop being thumb-sized -- eleven over 360px is 32px each -- so the four are the ones plan 016's subset says a phone is for, and "More" opens the *existing* `app-sidebar` in a drawer rather than listing the destinations a second time. Two lists is two places to add the next view to. That reuse has a cost this found the hard way: a shared component brings its `data-testid`s with it, so rendering the drawer's sidebar unconditionally put a second `nav-home` (and ten siblings) in the DOM and **failed 30 existing specs** with "resolved to 2 elements" -- on a desktop viewport, where this element is `display: none` and the drawer can never open. It renders only while the drawer is open, and the component test asserts the absence, because the failure is invisible from inside the component and lands in files nobody touched. **What made the shell overflow was minimums, not padding.** Measured at 360px: the body was 652px wide, because a `min-width` in a flex row is a hard floor and a grid item's implicit minimum is its content. So `min-width: 0` on the boxes between the viewport and the content, and each component stands its own non-essential parts down in its *own* stylesheet -- search-bar's 200px floor, job-indicator's label (the visible one; the live region that announces it is untouched), audio-player's seek bar and volume. A media query inside a shadow root is answered by the viewport, so this is the component saying what it drops rather than the shell reaching in. Volume goes because the hardware keys own it on a phone, which is the same reason mediacontrols' Android handler implements no volume callback. Seeking goes because 4px is not a thumb target; it belongs to the full-screen now-playing view, which is the next phase. An existing spec therefore asserts the opposite of what it did: layout-overflow's 320px case used to require that the 464px behind `overflow: hidden` could be *scrolled to*, which was the remedy available while the shell had one layout. It reflows now -- 320px in a 320px viewport, exactly -- and reflow is what WCAG 1.4.10 asked for. |
||
|
|
4efd17d477 |
fix(a11y): let the shell scroll sideways when it does not fit
a11y.21 (WCAG 1.4.10), measured rather than taken as filed. The finding's mechanism is vertical — "the 4em bars grow while the viewport does not, and anything that no longer fits is clipped with no scrollbar" — and that is not what happens. The middle row is `1fr` and absorbs the growth exactly: at 200% text on 800x600 the bars go 64px to 128px and the panel 472px to 344px, with the footer still landing on 600. Nothing is clipped vertically, and Settings stays reachable because the sidebar scrolls (007 phase 5). What is real is the axis the finding does not mention. At 200% text the shell is 1014px wide in an 800px viewport, and at 320px — 400% page zoom of 1280, the width 1.4.10 names — it is 784px, so 464px of the app including the job indicator and the queue button sat behind `overflow: hidden` with no way to reach it. So the horizontal axis scrolls and the vertical one stays fixed, which also keeps the transport where a desktop player's transport belongs. At every size this app promises there is no overflow on either axis and no scrollbar appears, which the three viewport cases assert. The first version of the spec passed on the broken build: `overflow: hidden` still permits programmatic scrolling, so `scrollLeft = 9999` proves nothing. It is a wheel gesture now. |
||
|
|
9d420cda0a |
fix(a11y): add a skip link, demote the subtitle, and size the sort arrow
a11y.30: `<main id="main-content">` existed and nothing linked to it, so a keyboard user walked the library filter, the search box, the job indicator and eleven nav items before reaching content, on every navigation. Two things in it are load-bearing and only checkable against the running document: the link is out of flow in *both* states, because `body` is a grid with named areas and an in-flow extra child is auto-placed into one of them; and `<main>` needs tabindex="-1", or the fragment link moves the scroll, leaves the tab sequence where it was, and looks like it worked. a11y.29: `<h1>` followed by `<h3>` for type size. An `hgroup` takes one heading plus paragraphs, so a `<p>` is also what it was meant to hold. a11y.34: the sort arrow was 10px, below the type scale's own floor, with a comment acknowledging it. Half of that finding was closed by Phase 1 — the direction is announced now, via aria-sort — and the other half is one declaration. And the state that landed in: the hgroup measured 67px inside a 64px bar, so dropping the h3's bottom margin shortened the block, moved the flex-centred pair down, and clipped the subtitle's descenders. The overflow was pre-existing; `margin-block: 0` on the title is the fix, pinned by a new layout-overflow case. |
||
|
|
e9ca16362f |
fix(ui): make the app fit the window it enforces a minimum for
The track list shared out its whole clientWidth across the resizable columns while every row spends 24px on the favourite column and 2x8px on its own padding before the first one starts, so the grid was always exactly 40px wider than the box holding it and the last column was clipped at every size (scrollWidth 1280 vs clientWidth 1240, measured). Both numbers now live in one place and are read by the two call sites that had written them out separately, which is how they came to disagree. The enforced minimum was 512x384, which the layout had never supported: at 700x480 the eleven sidebar items needed 406px of a 352px pane, overflow:hidden cut the last two off with nothing to scroll, and Settings and Jobs could not be reached at all. The pane scrolls now, the sidebar collapses to icons below 900px (its .collapsed mode existed and only a manual drag ever reached it), the subtitle hides at the same breakpoint so the title stops wrapping out of the 4em bar, and the minimum is 800x600 - measured as where the shell still works rather than picked as a round number. |