theam / theam/facility

Web UI accessibility: timeline has no live regions, no skip link, no sr-only primitive, no a11y guard in CI

Open
#331 2 comments 0 reactions 0 assignees View on GitHub

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:

  1. No skip link anywhere. The sidebar navigation is tabbed through on every page (WCAG 2.4.1 bypass blocks).
  2. No sr-only primitive in packages/ui. Icon-only controls have no idiomatic way to get an accessible name; aria-label coverage across the app is sparse.
  3. 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 — StatusDot is aria-hidden by 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.
  4. 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.
  5. The login page has no heading and no <main> landmark, and the document title is bare "facility".
  6. Review surfaces rely on 9–12.5px muted text (LegendChip is 9px, story metadata 10.5px with --dim). Contrast at those sizes and 200% zoom behavior are unverified.
What I propose
  1. 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/ui primitives and key stateless apps/web components. The guard set only grows.
  2. Add a skip link to the app shell and an sr-only primitive to packages/ui.
  3. 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.
  4. Login page: one main landmark, one heading, a descriptive title.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.