Web UI accessibility: timeline has no live regions, no skip link, no sr-only primitive, no a11y guard in CI
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 71
- Forks
- 64
- Avg merge
- 15h 38m
- Merged PRs (30d)
- 66
Description
The problem
Facility's operating model makes the web UI the surface where humans supervise agents: read the story timeline, review turns, decide. Parts of that surface are currently hard or impossible to use with a keyboard or screen reader. Findings below come from a static pass over apps/web and packages/ui plus a runtime check of the login page, at commit c14bc6d.
Worth saying first, because the audit found it: the fundamentals are better than most applications I audit. apps/web/components/shell/nav.tsx:52 has <nav aria-label="Primary"> with a proper aside landmark, packages/ui/src/tokens.css:87 applies a global prefers-reduced-motion kill-switch, status is always text plus color (apps/web/components/ci-status.tsx renders "checks · failed · …", story rows render story.status as text), the forms have correct live regions (apps/web/components/settings/keys-manager.tsx:80 uses polite/assertive correctly), the command palette is a labelled dialog with Escape support (apps/web/components/shell/cmdk.tsx:128), and there are no clickable-div antipatterns.
The gaps:
- No skip link anywhere. The sidebar navigation is tabbed through on every page (WCAG 2.4.1 bypass blocks).
- No
sr-onlyprimitive inpackages/ui. Icon-only controls have no idiomatic way to get an accessible name;aria-labelcoverage across the app is sparse. - The story timeline, the core review surface, has no live-region semantics. Live regions exist only in settings and forms components. Turn state changes and completions are visual only —
StatusDotisaria-hiddenby design and the adjacent status text is never announced. A screen-reader reviewer cannot tell when an agent turn finishes, which is the exact moment the product asks them to pay attention. - No automated accessibility checking. No axe-core anywhere in the test suites, and biome runs the default preset only. Nothing fails if any of the above regresses further.
- The login page has no heading and no
<main>landmark, and the document title is bare "facility". - Review surfaces rely on 9–12.5px muted text (
LegendChipis 9px, story metadata 10.5px with--dim). Contrast at those sizes and 200% zoom behavior are unverified.
What I propose
- Treat accessibility as a guard, matching the repository's own invariants approach: axe-core in the web app's vitest suite, deterministic (jsdom, server-rendered components, no network, no credentials), covering the
packages/uiprimitives and key statelessapps/webcomponents. The guard set only grows. - Add a skip link to the app shell and an
sr-onlyprimitive topackages/ui. - Define the announcement strategy for the story timeline, e.g.
role="log"or a polite live region for turn completion, so supervising agents works without sight. - Login page: one
mainlandmark, one heading, a descriptive title.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the app shell, packages/ui primitives, and the stateless components under apps/web identified in the audit; review nav.tsx, ci-status.tsx, keys-manager.tsx, cmdk.tsx, and the login page. Run the web app's existing Vitest suite and inspect the current CI and Biome configuration. Done means the proposed accessibility guard, skip link, sr-only primitive, timeline announcement strategy, login landmarks and title, and documented contrast or zoom findings are addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- accessibility, frontend, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100