Skip to content

feat(web): baseline accessibility semantics for the shells and login - #337

Open
anabelle wants to merge 1 commit into
theam:mainfrom
anabelle:feat/web-baseline-semantics
Open

feat(web): baseline accessibility semantics for the shells and login#337
anabelle wants to merge 1 commit into
theam:mainfrom
anabelle:feat/web-baseline-semantics

Conversation

@anabelle

@anabelle anabelle commented Sep 7, 2026

Copy link
Copy Markdown

Refs #331. The baseline-semantics slice agreed in the issue: no live-region decisions here, no new dependencies.

What changes

  • VisuallyHidden primitive in @facility/ui: the blessed way to give icon-only controls an accessible name. Tailwind's sr-only technique, never display: none, so content stays in the accessibility tree.
  • SkipLink in both authenticated shells (org and project): first focusable element in the DOM, sr-only until focused, fixed top-left when visible, targets an explicit #main-content with tabIndex={-1} so focus actually moves and the next Tab lands inside the work area instead of back in the sidebar.
  • Login page: <main> landmark, the brand mark becomes the <h1>, and title: "Sign in" rides the root template to render "Sign in · facility".

Tests

apps/web/test/a11y-baseline.test.tsx, deterministic and dependency-free: server-renders both real layouts with the API, topbar, and router-link modules mocked, then asserts the DOM contract (skip link precedes the sidebar nav, main carries id and tabindex, login has landmark, heading, and title; VisuallyHidden keeps text in the tree). Runs in the default node environment, no browser, no network, no credentials.

Verification

  • pnpm --filter @facility/web test - 6 files, 37 tests passed (5 new)
  • pnpm --filter @facility/web typecheck - clean
  • pnpm --filter @facility/ui typecheck - clean
  • pnpm exec biome check on changed files - clean after import-order fixes
  • pnpm --filter @facility/web build - clean
  • node guards/run.mjs - 2 guards ran, 0 failed

Not run: full pnpm verify (needs Docker-backed PostgreSQL; no API, database, or workspace boundary is touched) and the manual keyboard pass (recommended on merge: tab from the address bar on an org page, a project page, and the login page).

Effects

First slice of theam#331: a VisuallyHidden primitive in @facility/ui, a
keyboard-visible skip link with an explicit main-content target in both
authenticated shells (first focusable element, main becomes focusable),
and login page semantics (main landmark, h1, descriptive title via the
root template). Dependency-free: contracts are tested with
server-rendered markup assertions in the default node environment.

Refs theam#331
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