Locara

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

  1. Accessible by default. Components and primitives ship with full a11y support; app authors get it without effort.
  2. macOS native conventions. Locara apps respect VoiceOver, Dynamic Type, Reduce Motion, Reduce Transparency, Increase Contrast, and Color Filter settings.
  3. Keyboard-first navigation. Every action reachable via keyboard. No mouse-only flows.
  4. Discoverable to assistive tech. Capability declarations + app metadata are surfaced to screen readers as structured information, not as visual-only chrome.
  5. 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-visible and 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-label or 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-audit that checks all colors.
  • Dynamic Type support. Respects macOS text-size preferences. No font-size: 12px hard-codes; use rem with system base size.
  • Reduce Motion. Animations check prefers-reduced-motion: reduce and 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:

  1. axe-core run on the Tauri webview’s DOM in headless mode. Catches missing labels, contrast issues, ARIA misuse.
  2. Keyboard navigation test — exercises every focusable element via tab order; flags unreachable interactives.
  3. Heading hierarchy check<h1> exists, no level skips.
  4. prefers-reduced-motion honored — script tests with the media query forced; flags animations that don’t respect it.
  5. 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:

SettingBehavior
VoiceOver enabledAll interactive elements have accessible names; live regions for dynamic content.
Increase ContrastHigh-contrast palette is selected via prefers-contrast: more.
Reduce MotionDisable non-essential animations; replace with static states.
Reduce TransparencySolid backgrounds replace blur/vibrancy.
Differentiate Without ColorStatus indicators include shape/text, not color alone (e.g., capability “denied” shows ✗ + “denied” text, not just red).
Color FiltersApp tested under macOS Color Filter settings (Greyscale, Protanopia, etc.) — components remain usable.
Larger Text / Dynamic TypeAll text scales with system size preference.
Bold TextSystem bold preference respected; use system font weights.
Mouse keysAvoid 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/components ship with a11y baseline (semantic HTML, ARIA, keyboard nav, contrast). Transcribe is fully a11y-tested as the reference.
  • Phase 2: axe-core integration in locara test. Automated review checks at submission. DocVault is 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