Files
adolf/ui/docs/design-system/accessibility.md
alvis bedb527145
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Vendor OpenClaw source as Adolf fork baseline
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11),
free to diverge. Tree copied sans upstream .git; upstream remote added for
future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19.
Preserves docs/ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
2026-07-05 09:36:54 +00:00

141 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Accessibility
OpenClaw targets **WCAG 2.1 AA**. This checklist applies to every UI component — use it when building new components and during PR review.
---
## Contrast Minimums
| Context | Minimum Ratio | Notes |
| ----------------------------------------- | ---------------- | -------------------------------------------------- |
| Normal body text (< 18px / < 14px bold) | **4.5:1** | Use `--text` (#d4d4d8) or stronger on `--bg` |
| Large text (≥ 18px regular / ≥ 14px bold) | **3:1** | Headings in chat thread |
| UI component boundaries (inputs, buttons) | **3:1** | Border colours against adjacent background |
| Focus indicators | **3:1** (AA) | `--focus-ring` / `--focus-glow` already compliant |
| Placeholder text | Best-effort ≥3:1 | `--muted` (#838387) is ~5:1 on `--bg` — acceptable |
> Verify with [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) or browser DevTools accessibility panel.
---
## Checklist
### 1. Focus Visible
- [ ] All interactive elements have a visible `:focus-visible` style
- [ ] Use `--focus-ring` box-shadow pattern from `base.css` — do not remove the outline without replacing it
- [ ] Never use `outline: none` alone; replace with `box-shadow: var(--focus-ring)` and `outline: none`
```css
/* Correct pattern */
.my-button:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
```
### 2. Minimum Tap / Click Target Size
- [ ] All interactive controls are ≥ **44×44px** on mobile / touch targets
- [ ] Icon-only buttons add invisible padding to reach 44px (`min-width: 44px; min-height: 44px`)
- [ ] Verify on the mobile breakpoint (`@media (max-width: 768px)`)
### 3. Skip Link
- [ ] A visually-hidden skip link (`#skip-to-main`) is present in the document root
- [ ] The link becomes visible on focus
- [ ] Target element has `tabindex="-1"` to accept programmatic focus
```html
<a id="skip-to-main" href="#main-content" class="skip-link">Skip to main content</a>
```
```css
.skip-link {
position: absolute;
left: -9999px;
top: 0;
z-index: 9999;
}
.skip-link:focus {
left: 1rem;
top: 1rem;
/* ... visible styles */
}
```
### 4. Focus Trap
- [ ] Modal dialogs trap focus inside while open (Tab/Shift+Tab cycle within the modal)
- [ ] Closing the modal returns focus to the trigger element
- [ ] Escape key closes the modal
### 5. ARIA Labels
- [ ] Icon-only buttons have `aria-label` describing the action (not the icon name)
- [ ] Progress bars use `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`
- [ ] Live regions updating async content use `aria-live="polite"` (or `"assertive"` for critical alerts)
- [ ] Decorative SVG icons have `aria-hidden="true"`
```html
<!-- Correct: icon button -->
<button aria-label="Send message">
<svg aria-hidden="true"><!-- ... --></svg>
</button>
<!-- Correct: progress bar -->
<div
role="progressbar"
aria-valuenow="42"
aria-valuemin="0"
aria-valuemax="100"
aria-label="Context window usage"
>
<div style="width: 42%"></div>
</div>
```
### 6. Tab Role Pattern
When building a tab interface:
- [ ] Tab container: `role="tablist"`
- [ ] Each tab: `role="tab"`, `aria-selected="true|false"`, `aria-controls="panel-id"`
- [ ] Each panel: `role="tabpanel"`, `id` matching `aria-controls`, `aria-labelledby` pointing to its tab
- [ ] Keyboard: Arrow keys move between tabs; Tab moves into the panel; Shift+Tab exits
```html
<div role="tablist" aria-label="Main navigation">
<button role="tab" aria-selected="true" aria-controls="chat-panel" id="chat-tab">Chat</button>
<button role="tab" aria-selected="false" aria-controls="settings-panel" id="settings-tab">
Settings
</button>
</div>
<div role="tabpanel" id="chat-panel" aria-labelledby="chat-tab"><!-- ... --></div>
<div role="tabpanel" id="settings-panel" aria-labelledby="settings-tab" hidden><!-- ... --></div>
```
### 7. Reduced Motion
- [ ] No animation plays without being suppressible via `prefers-reduced-motion`
- [ ] The global reset in `base.css` covers transitions — test with "Reduce motion" enabled in OS settings
- [ ] Infinite loaders (`shimmer`, spinners) have explicit `animation: none` in reduced-motion context
### 8. Semantic HTML
- [ ] Use native elements (`<button>`, `<a>`, `<input>`) before adding ARIA to `<div>` / `<span>`
- [ ] Headings (`<h1>``<h6>`) reflect document hierarchy — do not skip levels
- [ ] Lists of items use `<ul>` / `<ol>` + `<li>`, not chains of `<div>`
---
## Testing Tools
| Tool | Purpose |
| ------------------------------------------------------- | ----------------------------------- |
| Chrome DevTools → Accessibility tab | Inspect ARIA tree, contrast |
| axe DevTools (browser extension) | Automated WCAG audit |
| macOS VoiceOver (`Cmd+F5`) | Screen reader smoke test |
| `prefers-reduced-motion: reduce` (DevTools → Rendering) | Verify animation suppression |
| Keyboard-only navigation | Tab through entire UI without mouse |