Skip to content

make the Catalog page usable on a phone - #3201

Merged
atomantic merged 1 commit into
mainfrom
cos/task-ms5db58f/agent-0cc415bb
Jul 29, 2026
Merged

make the Catalog page usable on a phone#3201
atomantic merged 1 commit into
mainfrom
cos/task-ms5db58f/agent-0cc415bb

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

The Catalog page didn't fit a phone. The header toolbar's four controls need ~350px and a 320px viewport gives 288px, so they ran off the side; the three filter dropdowns each claimed a fixed min-w-[160px] they had no room for; and the selection bar's dropdown menus, anchored to a ~90px button, opened past the viewport edge.

Layout

  • Toolbar wraps to its own rows under sm — a full-width segmented Grid/Albums toggle, then Sync/Ingest/New splitting the row evenly.
  • Search moved above the filters so the primary way to find an ingredient is reachable without scrolling.
  • Type chips stay on one swipeable row (overflow-x-auto scrollbar-hide touch-pan-x, bleeding to the screen edge) instead of stacking 3–4 rows deep and pushing the cards below the fold. They wrap as before from sm up.
  • Filter dropdowns lay out two-up; the fixed min-width applies only from sm.
  • Selection bar stacks its count above three equal-width actions. Its menus anchor to the button row under sm (the per-button wrappers only become relative at sm) so they span the bar rather than hanging off one button, and cap at 60vh so an upward-opening menu can't run off the top in landscape.
  • Album subtitle drops below the title instead of competing with it for a ~200px slot.
  • Tap targets raised to min-h-[40px] across the toolbar, filters, and action bar.

Accessibility
Labels too long for a narrow button hide their tail (hidden sm:inline / hidden lg:inline) and keep the full wording in aria-label, so the accessible name never depends on viewport width. The visible text stays a prefix of it, per WCAG 2.5.3 label-in-name.

Card delete confirm
Moved from a corner overlay to the shared InlineConfirmRow band, which names the ingredient (Delete "Echo Saint"?). The overlay had to be paid for with reserved padding on the link, and a single-column phone card has no width to spare: reserving it crushed the name, and stretching the overlay instead covered the name outright — hiding the record being deleted. The band also drops a magic padding constant that was coupled to the confirm row's own height.

Performance
The sticky selection bar drops backdrop-blur under sm. Its fill is already 95% opaque, so on a phone the blur bought nothing visible while making the compositor re-sample the area behind the bar on every scroll frame over a 60-card grid.

Apart from the delete-confirm band, desktop layout is unchanged.

Test plan

  • cd client && npm test — 477 files / 5330 tests pass, including a new case asserting that the three buttons whose labels shorten keep their full aria-label. That assertion is load-bearing: jsdom applies no CSS, so the existing name-based queries would still pass with the aria-label deleted.
  • npx eslint clean on all changed files.
  • Built the client and verified against the compiled CSS that every new utility actually compiles (no silently-absent class) and that each sm: override lands after its base rule in the cascade — including pl-11 over px-4 on the confirm band.

The toolbar's four controls needed ~350px and ran off the side of a 320px
viewport; the three filter dropdowns each claimed a fixed min-width they
didn't have room for; and the selection bar's menus opened off-screen when
anchored to a ~90px button.

- Toolbar wraps to its own rows under `sm`: full-width segmented Grid/Albums
  toggle, then Sync/Ingest/New splitting the row evenly.
- Search moved above the filters so it's reachable without scrolling.
- Type chips stay on one swipeable row instead of stacking 3+ rows deep.
- Filter dropdowns lay out 2-up; the fixed min-width applies from `sm` up.
- Selection bar stacks its count above three equal-width actions. Its menus
  anchor to the button ROW under `sm` (the per-button wrappers only become
  `relative` at `sm`) so they span the bar, and cap at 60vh so an upward-
  opening menu can't run off the top in landscape.
- Labels too long for a narrow button hide their tail and keep the full
  wording in aria-label, so the accessible name never depends on viewport
  width (WCAG 2.5.3 label-in-name, asserted in the suite).
- Card delete confirm moves from a corner overlay to the shared
  InlineConfirmRow band, which names the ingredient. The overlay had to be
  paid for with reserved padding on the link, and a single-column phone card
  has no width to spare — reserving it crushed the name, and stretching the
  overlay instead covered the name outright, hiding the record being
  deleted. The band also drops a magic padding constant that was coupled to
  the confirm row's own height.
- Bigger delete/select tap targets; album subtitle drops below the title
  instead of squeezing it.
- Sticky bar drops `backdrop-blur` under `sm`: the fill is already 95%
  opaque, so the blur only cost a per-frame compositor re-sample.

Apart from the delete-confirm band, desktop layout is unchanged.
@atomantic
atomantic merged commit 4bdec5e into main Jul 29, 2026
6 checks passed
@atomantic
atomantic deleted the cos/task-ms5db58f/agent-0cc415bb branch July 29, 2026 01:13
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.

1 participant