Accessibility
ARC UI targets WCAG 2.1 Level AA. Components ship with semantic HTML, keyboard support, and ARIA attributes built in — and this site is the test bed.
Automated Audit
Claims are cheap, so we audit. Every component documentation page — live demos included — is checked with axe-core against the fully rendered DOM, shadow roots included, in both themes. CI fails on any serious or critical violation, color contrast included. No exclusions.
ARIA Attributes
Roles are set automatically: arc-modal is a role="dialog"
managing aria-modal; arc-tabs wires up
tablist/tab/tabpanel. Anything extra passes
through from the host element:
Keyboard Navigation
Every interactive component is fully keyboard-driven. Don't take our word for it — this one is live. Tab to it and drive it from the keyboard:
| Component | Keys | Action |
|---|---|---|
| Button | Enter / Space | Activate |
| Modal | Escape | Close |
| Tabs | Arrow Left/Right, Home / End | Switch tab |
| Accordion | Enter / Space | Toggle panel |
| Select | Arrow Up/Down | Navigate options |
| Select | Enter | Select option |
| Select | Escape | Close dropdown |
| Toggle | Space | Toggle on/off |
| Checkbox | Space | Toggle checked |
| Drawer | Escape | Close |
| Tooltip | Escape | Dismiss |
Focus Management
ARC UI ships two focus indicator styles as design tokens. Tab through these to compare them:
Focus shows only on keyboard navigation (:focus-visible), never on mouse
clicks — click the cards above and nothing appears. Overlays like arc-modal
and arc-drawer trap focus while open.
Screen Readers
Shadow DOM can complicate screen reader access; ARC UI's patterns avoid the traps:
- Slotted content stays in the light DOM, where screen readers reach it directly.
- ARIA attributes set on the host element are reflected into the shadow root where needed.
- Form elements take a
labelattribute, so they are always announced.
Color & Contrast
The audit above measures actual rendered ratios in both themes — these are results, not targets:
--text-primaryon--bg-deepexceeds 15:1.-
--text-mutedand--text-ghostmeet the 4.5:1 ratio for normal text in both themes. -
The feedback colors —
--color-success,--color-warning,--color-error,--color-info— pass in both dark and light modes.
Reduced Motion
With prefers-reduced-motion set, every transition and animation collapses —
functionality is unchanged, only the motion goes:
Without JavaScript
Web Components need JavaScript to upgrade. Until that happens — a failed script, a slow network, JS disabled — a custom element is an unknown tag rendering only its light DOM. What you put inside the element is what everyone sees first.
This matters most for links. An href on the custom element itself
cannot produce a working link without JavaScript: the attribute sits
on the element, and the real <a> only exists in a shadow root that
is never created. Slot a real anchor instead and the link is ordinary HTML from the
first byte:
On upgrade the component adopts that anchor as its control rather than rendering a
second one, so there is only ever one link in the accessibility tree. The
href form stays fully supported — prefer it inside app shells where
JavaScript is guaranteed, and the slotted form on anything public, indexed, or
first-load critical. This applies to arc-button,
arc-icon-button, arc-link, arc-card,
arc-nav-item, arc-breadcrumb-item, and
arc-sidebar-link.
The stylesheet hides components only until they upgrade, and that hide is gated on scripting being available — so with JS disabled your content stays visible rather than being hidden forever waiting for an upgrade that never comes:
Components whose content comes from properties rather than slots — such as
arc-feature-card, which renders from heading and
description — have no light DOM to fall back to and stay blank without
JavaScript. Author their content as slotted markup, treat them as enhancement-only,
or server-render them.
See Also
- Server Rendering — content in the payload before JS runs
- Getting Started — installation and setup