Skip to content

Waypoints page: a toolbar where a card of prose used to be - #702

Merged
pokle merged 2 commits into
masterfrom
claude/waypoints-page-text-reduction-d6a1mn
Sep 19, 2026
Merged

pokle merged 2 commits into
masterfrom
claude/waypoints-page-text-reduction-d6a1mn

Conversation

@pokle

@pokle pokle commented Sep 19, 2026

Copy link
Copy Markdown
Owner

Preview: https://claude-waypoints-page-text-r.glidecomp.pages.dev/comp

The page's job is to show a competition's waypoints, and on a phone it showed almost none of them: a sentence describing the page, then a titled card with a heading and two more sentences explaining two buttons — and the first waypoint began below the fold.

What changed

  • The intro paragraph is deleted outright — "The shared waypoints for this competition. Tasks pick their turnpoints from this set." plus the admin half that listed six file formats.
  • WaypointDeviceExport is now a toolbar. The same two buttons, in the same place, with no heading, no subtitle and no border. Its title / subtitle props went with them; the only call site used the defaults. Button labels are unchanged — "Open in app" on a coarse pointer, "Download" on a fine one.
  • The swap toggle no longer stands permanently above both outputs. It is offered where each output is chosen: a checkbox item at the head of the download menu, and a checkbox inside the expanded QR section. One piece of state behind both, so a set swapped in the menu opens swapped in the QR.

The menu item

It is a one-item MenuSection with selectionMode="multiple", so it is a real menuitemcheckbox carrying aria-checked rather than an onAction item pretending to be one, and shouldCloseOnSelect={false} keeps the menu open — the format links beneath it carry the swap state in their hrefs and have to re-render. Written up as gotcha #28 in the RAC adoption guide, since it is a new pattern for the kit.

Coverage

The QR-and-swap test now runs in both Playwright projects. It was previously skipped wholesale on mobile because it shared a test with a download menu it never touched — and a phone is the width this toolbar exists for. The download-menu tests stay fine-pointer only, and one of them pins the menu staying open when swap is selected.

32 passed, 2 skipped   comp-waypoints.spec.ts (chromium + mobile)
836 passed             frontend vitest
bun run typecheck:all  clean
bun run build          clean (Vite + SSR bundle + Astro)

Screenshots taken at Pixel 7 and desktop confirm the first waypoint is now on the first screen, and that the QR section carries its checkbox.

One thing worth a look

The swap item sits in a menu, and the kit's MenuItem is ~28 px tall — over WCAG 2.5.8's 24 px, under the ≥44 px this repo's accessibility standard asks for on a coarse pointer. That is pre-existing and applies to every menu row in the app (the eight format items beside it are the same height), so I have not special-cased this one row. Bumping rac/menu.tsx with a pointer-coarse: rule would fix every menu at once and seems worth its own change.

Accessibility (docs/accessibility-standard.md)

  • Keyboard: menu and toggle reachable and operable; the QR toggle returns focus to itself
  • Focus: no focus-visible styles stripped
  • Contrast: unchanged tokens; removing the bg-muted/30 card leaves buttons on the page background, which the kit already covers
  • Not colour-alone: the swap item's state is a tick glyph plus aria-checked
  • Names: the menu item carries the full sentence as textValue, with the visible words inside it (WCAG 2.5.3)
  • Semantics: one h1 — and one fewer h2, since the card's heading is gone
  • Zoom/reflow: comp-waypoints.spec.ts asserts the page never scrolls sideways, in both projects
  • Targets: the QR-section checkbox is a full-width label; see the note above on menu rows

🤖 Generated with Claude Code

https://claude.ai/code/session_01UhNoutDWYNCH8txCmfz88T


Generated by Claude Code

The page's job is to show a competition's waypoints, and on a phone it
showed almost none of them: a sentence describing the page, then a titled
card with a heading and two more sentences explaining two buttons, and the
first waypoint began below the fold. Every word of that is gone.

- The intro paragraph ("The shared waypoints for this competition…", plus
  the admin half listing six file formats) is deleted outright.
- WaypointDeviceExport is now a TOOLBAR — the same two buttons, in the same
  place, with no heading, no subtitle and no border. Its `title`/`subtitle`
  props went with them; the only call site used the defaults.
- The swap toggle no longer stands permanently above both outputs. It is
  offered where each output is chosen: a checkbox item at the head of the
  download menu, and a checkbox inside the expanded QR section. One piece of
  state behind both, so a set swapped in the menu opens swapped in the QR.

The menu item is a one-item MenuSection with selectionMode="multiple", so it
is a real menuitemcheckbox with aria-checked rather than an onAction item
pretending to be one, and shouldCloseOnSelect={false} keeps the menu open —
the format links under it carry the swap state in their hrefs and have to
re-render. Written up as gotcha #28 in the RAC adoption guide.

Coverage: the QR-and-swap test now runs in BOTH Playwright projects (it was
skipped wholesale on mobile for a download menu it never touched), which is
the width this toolbar exists for; the download-menu tests stay fine-pointer
only, and one of them pins the menu staying open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhNoutDWYNCH8txCmfz88T
"Hide map" had a row of its own for one right-aligned button, directly under
the row the device-export buttons were already on. On a phone that is a whole
line of vertical space spent on nothing, on the page whose job is to show the
waypoints.

MasterDetail owned that toggle, so this adds a way to hoist it:

- `useDetailFold(prefsKey)` holds the fold — the remembered answer, read in an
  effect for the same hydration reason MasterDetail's own copy was — and hands
  back the pane's id so a button outside the layout can say what it expands.
- `DetailFoldButton` is that button, identical to the one MasterDetail renders
  in its row, including the `@5xl:` query that hides it side by side. A caller
  must place it inside an `@container`, or a container query with no container
  ancestor never matches and the button leaks into the wide layout.
- Given `fold`, MasterDetail renders no toggle row AT ALL. Leaving it empty
  would spend the height this was meant to give back. Callers that pass
  nothing are untouched — the report card, the ranking, the task diagram and
  the thermal census all keep the row they had.

The button rides `WaypointDeviceExport`'s new `trailing` slot rather than
sitting beside it: an expanded QR makes that block tall AND wide, and as a
sibling the toggle was pushed onto its own line under the QR, floating above
the map as though it belonged to something else.

Two consequences worth knowing. The toggle now scrolls with the page instead
of sticking with the pinned pane, so hiding the map from halfway down the list
means scrolling back up — the trade this makes. And the master's focus
clearances now over-clear by the row that is no longer stuck (~2.25rem), which
is the safe direction for WCAG 2.4.11: a focused row stops slightly lower than
it needs to, never behind the pane.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhNoutDWYNCH8txCmfz88T
@github-actions

Copy link
Copy Markdown

Preview Deployment
https://8c26856e.glidecomp.pages.dev
Commit: 30200d8

@pokle
pokle marked this pull request as ready for review September 19, 2026 11:52
@pokle
pokle merged commit 98acc0d into master Sep 19, 2026
6 checks passed
@pokle
pokle deleted the claude/waypoints-page-text-reduction-d6a1mn branch September 19, 2026 11:53
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.

2 participants