feat: responsive + a11y sweep across the remaining web routes #558
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
#557 feat: unify Specs and Planner into one page
charles/claude-hooks
Reference
charles/claude-hooks#558
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
As an operator, I want every web route to match the responsive + a11y baseline that the agents page just established so that the dashboard is usable on mobile and clears WCAG 2.1 AA across the board.
The agents page (
/agents) is the reference. PR #555 nailed: lucide-react icons (no Unicode glyphs),<Button>for every clickable, mobile breakpoints (sm:),<Drawer>primitive with focus trap + focus return + role=dialog, autosave +role="status"live region, form inputs linked to errors viaaria-describedby+aria-invalid,<label>wrapping,prefers-reduced-motionhonored, contrast bumped ontext-text-dim. Other routes are not yet there.This is a sweep, route by route. Each ticket box below is a self-contained PR-sized chunk.
Acceptance criteria
Foundation — pre-work (do these first, blocks the others)
apps/web/src/components/for any drawer / panel still using<aside>directly. Migrate to<Drawer>.<Tabs>primitive does not exist, add one with arrow-key navigation +role="tablist"/role="tab"/aria-selected. Likely needed by the planner / specs unification (#557) and by Settings.apps/web/CLAUDE.md: every clickable goes through<Button>, every overlay through<Drawer>, every icon from lucide./flows(apps/web/src/routes/flows.index.tsx— 385 LOC + features ~11.5K LOC across 37 files)<button>instances with<Button>(size + variant per existing usage).▶ ▼ ⚠ ✓ ✗ ⏸…) with lucide icons.<select>(lines ~303, 332, 346) + search<input>(line ~320) getaria-label+aria-describedbyif errors exist.InstancesTablepattern inagents.tsx).RunsDrawermigrates to the<Drawer>primitive (drops the manual scaffold).sm:) applied to header, filters, table./monitor(apps/web/src/routes/monitor.index.tsx— 503 LOC + components)<Drawer>if they use the manual aside pattern.aria-labelon chart wrappers.<Button>withtone="error"for destructive ones.sm:./plannerand/specs— covered by #557 (unification ticket). This sweep does not double-do that work./settings(apps/web/src/routes/settings.index.tsx— 522 LOC)✓glyph (line ~325) → lucideCheck.<input>/<select>get associated<label>(oraria-label).role="status" aria-live="polite"./login(apps/web/src/routes/login.tsx)<label>+aria-describedbyfor the inline error.loading={mutation.isPending}from the<Button>primitive.Cross-route
app-shell.tsx) collapses to a hamburger drawer belowsm:.components/toasts.tsx) — toasts dismissable via Esc + tab order respects focus.<aside>drawer instances repo-wide migrated to<Drawer>. Grepapps/web/srcfor<asideand verify each.<button type="button">outside of<Drawer>'s internals migrated to<Button>.git grep -E "[▶▼⏸✓✗⚠①②③↺×↑↓⛽]"acrossapps/web/srcand confirm only intentional non-icon Unicode (e.g. tier numerals in semantic contexts) remains.Verification
just qapasses; no Biomelint/a11y/*errors.Out of scope
/statsand/usageroutes — being deleted in #556./agentsroute — already done.text-text-dimalready bumped; the rest of the palette stays.Suggested implementation order
/flows— biggest surface; locks the table / drawer migration patterns./monitor— drawers + charts./settingsand/login— smaller, can land in parallel.References
26e72f6(lucide + Button extension),da25428(Drawer primitive),9fab22d(header disclosure + tier sr-only + reduced-motion + save live region),b72eebb(form labels),9b61e4a(text-dim contrast bump).apps/web/src/components/{button,drawer,chip-input}.tsx.apps/web/src/lib/use-media-query.tsfor runtime branching by viewport.apps/web/CLAUDE.md(radius / shadow / drawer patterns).Dispatch coordination
Parallel with #556. Soft-blocks #557 — see ordering note below.
Routing: boss (Tabs primitive needs design judgment; without it, #557 will reinvent it).
Hard ordering constraint — Foundation commit MUST land first:
The "Foundation — pre-work" block at the top of the acceptance criteria is the gating piece for #557. Land it as the first commit on this branch and push immediately so #557 can rebase off it. Specifically:
<Tabs>primitive atapps/web/src/components/tabs.tsxwith arrow-key navigation +role="tablist"+aria-selected.apps/web/src/components/for any leftover<aside>drawers and migrate to<Drawer>.apps/web/CLAUDE.mdwith the conventions (Button / Drawer / Tabs / lucide / tokens — only).Commit, push, then proceed with the per-route sweep (
/flows→/monitor→/settings→/login→ cross-route). Do not gate the sweep on #557; #557 will rebase itself.Conflict points to watch:
apps/web/src/components/app-shell.tsx— #556 drops the/statsnav entry; #557 collapses Specs+Planner. Coordinate via rebase.apps/web/CLAUDE.md— #557 will also append a section. Land your update first; #557 rebases.Independent of: #557 specs/planner unification (different feature folders, but consumes our Tabs).