20 — Accessibility
Accessibility is a first-class concern, not a later-pass polish. Every Locara primitive — from components to capability prompts to the registry — is designed to work for users of assistive technology.
Principles
- Accessible by default. Components and primitives ship with full a11y support; app authors get it without effort.
- macOS native conventions. Locara apps respect VoiceOver, Dynamic Type, Reduce Motion, Reduce Transparency, Increase Contrast, and Color Filter settings.
- Keyboard-first navigation. Every action reachable via keyboard. No mouse-only flows.
- Discoverable to assistive tech. Capability declarations + app metadata are surfaced to screen readers as structured information, not as visual-only chrome.
- Reviewed at submission. A11y is part of the registry review pipeline, not an honor system.
Component-level requirements
Every component in @locara/components (see 11-components.md) must:
- Semantic HTML / ARIA roles. No
<div>-only buttons. Use<button>,<a>,<input>,<dialog>, etc., with appropriate roles and labels. - Keyboard support. Tab/Shift-Tab navigation, Enter/Space activation, Escape to dismiss, arrow keys where they make sense.
- Focus management. Visible focus rings (respecting
:focus-visibleand the OS focus-ring setting). Trap focus in modals; restore on dismiss. - Screen reader labels. Every interactive element has an accessible name. Icons paired with labels (
aria-labelor visually-hidden text). - Live regions for streaming content.
aria-live="polite"for streaming chat tokens, transcription updates, etc. So VoiceOver announces incrementally instead of going silent. - Color contrast. Meets WCAG AA (4.5:1 for normal text, 3:1 for large text). Tooling: components include a
npm run a11y-auditthat checks all colors. - Dynamic Type support. Respects macOS text-size preferences. No
font-size: 12pxhard-codes; use rem with system base size. - Reduce Motion. Animations check
prefers-reduced-motion: reduceand disable / shorten where possible. - Reduce Transparency. Frosted-glass / vibrancy effects degrade gracefully when transparency is reduced.
- Increase Contrast. Color tokens include high-contrast variants; the system setting toggles them.
The shadcn/Radix substrate gets us most of this for free; Locara components extend with explicit a11y testing.
App-author guidelines
Locara apps inherit a11y from @locara/components, but app code must:
- Don’t override default focus styles without restoring an alternative.
- Don’t trap users in modals without an Escape path.
- Respect dynamic content updates — when streaming output, announce via live regions.
- Provide alternative input methods for any voice/audio interaction (a Locara voice assistant must also accept typed input).
- Caption audio output where possible — TTS responses should also display as text.
- Support VoiceOver navigation of long content (transcripts, document text) — use proper heading hierarchy, landmark regions.
The CLI’s locara test will include a11y assertions in tests/accessibility.test.ts. Templates ship with starter tests.
Runtime-level requirements
The Locara runtime + client itself must:
- Capability prompts are screen-reader accessible. The first-run consent UI shows a structured table of capabilities (already designed in 13-security-privacy.md); each row is a properly-labeled list item.
- Update prompts and cool-down notifications are accessible.
- Dev panel (
locara dev’s right pane) is accessible — useful for blind developers building Locara apps. - The website (locara.app) and the optional Locara Manager utility meet all accessibility requirements.
Registry-level surfacing
The catalog frontend (locara.app) surfaces accessibility metadata for each app:
- An A11y badge is shown when an app has been a11y-tested (review pipeline + author self-attestation).
- Filters: “VoiceOver-supported,” “high-contrast support,” “keyboard-only navigable.”
- Each app page lists known a11y limitations declared by the publisher.
Apps cannot self-claim “VoiceOver-supported” without passing automated checks at submission.
Review pipeline a11y checks
Automated, run as part of locara verify --strict and at registry submission:
- axe-core run on the Tauri webview’s DOM in headless mode. Catches missing labels, contrast issues, ARIA misuse.
- Keyboard navigation test — exercises every focusable element via tab order; flags unreachable interactives.
- Heading hierarchy check —
<h1>exists, no level skips. prefers-reduced-motionhonored — script tests with the media query forced; flags animations that don’t respect it.- Manifest a11y declarations — apps declare known limitations honestly. Review staff (initially you) spot-checks claims.
Automated checks block submission for hard violations (missing labels, contrast failures); warn for softer issues. App authors get a clear report with line numbers and suggested fixes.
Specific macOS settings to honor
Each Locara app + the runtime + the client must respond to these system settings:
| Setting | Behavior |
|---|---|
| VoiceOver enabled | All interactive elements have accessible names; live regions for dynamic content. |
| Increase Contrast | High-contrast palette is selected via prefers-contrast: more. |
| Reduce Motion | Disable non-essential animations; replace with static states. |
| Reduce Transparency | Solid backgrounds replace blur/vibrancy. |
| Differentiate Without Color | Status indicators include shape/text, not color alone (e.g., capability “denied” shows ✗ + “denied” text, not just red). |
| Color Filters | App tested under macOS Color Filter settings (Greyscale, Protanopia, etc.) — components remain usable. |
| Larger Text / Dynamic Type | All text scales with system size preference. |
| Bold Text | System bold preference respected; use system font weights. |
| Mouse keys | Avoid hover-only interactions (hover-to-reveal menus need a non-hover path). |
A11y in voice / multimodal apps
Locara apps using voice-to-voice, text-to-speech, etc. modalities have specific obligations:
- Voice apps must accept text input as alternative. Don’t lock deaf users out.
- TTS apps must show text alongside audio. Don’t lock blind-and-deaf users out.
- Live transcription apps must support visual indicators of who’s speaking, not just audio.
- Image-to-text / VLM apps are themselves accessibility tools for blind users — they should optimize for that use case (high-quality alt text, OCR over uploaded images).
These are guidelines + recommendations in v1; tightened to requirements as the catalog matures.
Testing infrastructure
The @locara/test package includes:
import { test, expect, runApp, a11y } from '@locara/test'
test('chat is accessible', async () => {
const app = await runApp()
const issues = await a11y.audit(app.webview)
expect(issues.violations).toHaveLength(0)
})
test('keyboard-only flow works', async () => {
const app = await runApp()
await a11y.keyboard.tabTo('chat-input')
await a11y.keyboard.type('Hello')
await a11y.keyboard.press('Enter')
expect(app.lastSentMessage).toBe('Hello')
})
Templates from locara init ship with starter a11y tests; new components can’t be added to @locara/components without a11y tests.
Out of scope (for v1)
- Voice control / dictation beyond what macOS provides (apps inherit system-level dictation in any text input).
- Sign language interpretation of audio output.
- Custom AT (assistive technology) integrations beyond VoiceOver / standard macOS APIs.
- Multi-language a11y review — English-only for v1.
Phasing
- Phase 1: All
@locara/componentsship with a11y baseline (semantic HTML, ARIA, keyboard nav, contrast).Transcribeis fully a11y-tested as the reference. - Phase 2: axe-core integration in
locara test. Automated review checks at submission.DocVaultis fully a11y-tested. - Phase 3: A11y badges in the registry. Filters in the client. Public a11y guidelines for app authors.
- Phase 4: Community a11y reviewer program; a11y-themed app collections; public audit of the Locara website + (if shipped) the optional Locara Manager utility.
Open questions
- (open) Should an a11y violation block app submission, or just warn? Leaning: hard violations (missing labels, contrast failures < AA) block; soft ones warn.
- (open) Self-attestation for a11y on app cards — how do we prevent false claims? Probably: claims are surfaced as “publisher claims VoiceOver support” until automated checks verify.
- (open) Right-to-left language support is not a11y per se but related; punted to localization.
Cross-references
- Components a11y baseline: 11-components.md
- Capability prompts UI (must be accessible): 13-security-privacy.md, 14-trust-safety.md
- App store discovery filters: 12-registry.md
- Apple’s accessibility programming guide: https://developer.apple.com/accessibility/
- WCAG 2.2: https://www.w3.org/WAI/standards-guidelines/wcag/
- axe-core: https://github.com/dequelabs/axe-core