# Accessibility
Every site aardvark generates targets **WCAG 2.1 Level AA** out of the box. The chrome
ships with semantic landmarks, a skip link, visible keyboard focus, screen-reader
announcements, and reduced-motion support — and the build flags color-contrast problems
in your theme before they reach readers.
## Standards we follow
- **WCAG 2.1 Level AA** — the contrast, keyboard, and name/role/value success criteria.
- **Keyboard-first** — every interactive control is reachable and operable without a mouse.
- **Screen-reader friendly** — landmarks, current-state cues, and a live region for dynamic updates.
- **Respects user preferences** — `prefers-reduced-motion` and `prefers-color-scheme`.
## Built-in accessibility features
- **Skip to content** — the first Tab stop on every page jumps past the header
and navigation straight to the main content.
- **Landmark regions** — the banner, the section tabs, the documentation sidebar, the
breadcrumb trail, the main content, and the "On this page" list are each exposed as a
labelled region, so screen-reader users can jump between them.
- **Visible focus** — every link, button, and control shows a clear focus ring when you
navigate with the keyboard.
- **State cues** — the current page (sidebar), the current section (on-this-page), expanded/
collapsed sections, and sorted table columns are announced, not just shown with color.
- **Live announcements** — filtering a table announces its result ("No matching rows") to
assistive technology.
- **Links beyond color** — body links are underlined, so they're distinguishable without
relying on color.
- **Reduced motion** — scroll-spy, tab, and reveal animations are disabled when your system
asks to reduce motion.
## Keyboard shortcuts
The chrome and the interactive components are fully keyboard-operable:
| Where | Keys | Action |
|-------|------|--------|
| Anywhere (on load) | Tab | Focus **Skip to main content**; Enter jumps to the article |
| Sidebar navigation | → / ← | Expand / collapse the focused section |
| Sidebar section toggle | Enter / Space | Open or close the section |
| Section tab menu (header) | Esc | Close the dropdown and return focus to its button |
| Table column header | Enter / Space | Sort by that column |
| Table filter box | type to filter | Show only matching rows (live) |
| Tabbed content | ← → Home End | Move between / jump to first or last tab |
| Accordion / API sections | Enter / Space | Expand or collapse |
| File tree | ↑ ↓ → ← Home End | Move focus; expand/collapse a folder or step in/out; jump to first/last row |
| File tree — activate row | Enter / Space · Esc | Toggle a folder, open a file's code in a modal, or follow a linked file · close the modal |
| Copy-code button | Enter / Space | Copy the snippet |
| Zoomable image | Enter / Space · Esc | Open the lightbox · close it |
| "Was this page helpful?" stars | ← / → | Change the rating |
| Language selector · theme toggle | the control's native keys | Switch language · light/dark |
> **Search shortcuts:** the default theme doesn't add a global search hotkey. If you enable
> [Algolia DocSearch](/search/), it brings its own — Cmd/Ctrl + K
> and / — to open search from anywhere.
## Build-time contrast check
When you customize `theme.colors`, the build checks your palette against WCAG AA and prints
a non-fatal warning for any text/background pair that falls short — in both light and dark:
```text
aardvark: warning — color contrast below WCAG AA:
light — links: #8a7fff on #ffffff = 3.41:1 (needs 4.5:1)
Adjust theme.colors so each pair meets the ratio (a darker/lighter shade per scheme),
or set a11y.contrast: false to silence this check.
```
It checks body text, secondary text, links, the active navigation item, and text on the
code/table surface. Because each color scheme has its own background, pick a `primary` (and
other slots) that reads well on **both** — that's why this site sets a lighter `primary` for
dark mode than for light. Tune the check in `aardvark.config.yaml`:
```yaml
a11y:
contrast: true # run the audit (default: true; non-fatal warnings only)
contrastLevel: AA # AA (default) or AAA
strict: false # also audit the built-in default palette, not just your colors
# a11y: false # shorthand to turn the audit off entirely
```
Sites that don't customize `theme.colors` use the built-in palette, which already meets AA —
so the audit stays quiet unless you opt into `strict`.
## Writing accessible content
The theme handles the chrome; a few habits keep your pages accessible too:
- **Describe images** — always give Markdown images alt text: ``. Use empty alt (`![]`) only for purely decorative images.
- **Keep headings in order** — one `#` per page, then `##`, then `###`; don't skip levels for size. The on-this-page list and screen-reader outline are built from them.
- **Write meaningful link text** — "[read the deployment guide](/deployment/)", not "click here".
- **Don't rely on color alone** — pair it with text or an icon when it carries meaning.
- **Label custom widgets** — any interactive snippet you add should be keyboard-operable and
carry an accessible name (an `aria-label` or visible text) and a visible focus style.
> **Note:** Mantine components used in content (buttons, tabs, accordions, the rating widget)
> bring their own keyboard support and ARIA roles. Default filled buttons use Mantine's brand
> color; if you rely on a custom `primary`, the contrast check above covers its use as link
> and active-state text.
## Roadmap
- Live assistive-technology smoke tests (NVDA / VoiceOver) as part of releases.
- An automated `axe`/`pa11y` pass over the built sample site.