Accessibility
Hypermedia Components keeps state in HTML attributes (aria-*, data-*,
native :checked / disabled), so assistive technology gets the semantics
for free. Beyond that, the kit adapts to the user’s context in CSS:
Forced Colors, reduced motion, and right-to-left layout.
Forced Colors (Windows High Contrast)
Section titled “Forced Colors (Windows High Contrast)”When a user turns on a high-contrast / forced-colors theme, the browser
replaces author colors with the user’s system palette and drops
box-shadow. Two HC patterns would otherwise break:
- Focus rings drawn with
box-shadow(the inputs, selects, custom toggles, slider) — the ring disappears. - State conveyed only by a background tint (
color-mix) — a selected option, the current pagination page, a checked control — becomes indistinguishable.
A single forced-colors stylesheet (hc.a11y.css, shipped inside the main
hc.css bundle) re-expresses both using CSS system colors, which
forced-colors mode preserves:
- Focus is restored as a real
outline(Highlight) wherever a component usedoutline: noneplus a box-shadow ring. - Selection / active state (combobox & command options, tabs, toggle
group, pagination, calendar days, datagrid selected rows / current cell)
is marked with an inset
outline—outlinesurvives forced-colors, so the mark is always visible. - Custom toggles (
hc-checkbox,hc-radio,hc-switch, thehc-sliderthumb) opt out withforced-color-adjust: noneand paint withHighlight/HighlightText/Canvas/CanvasText, so the checked fill and thumb stay visible.
You get this automatically with the bundled hc.css. With the granular
entry, import the stylesheet after your component CSS:
@import "@hypermedia-components/core/css/core";@import "@hypermedia-components/core/css/button";/* …other components… */@import "@hypermedia-components/core/a11y.css"; /* last */hc.a11y.css is concatenated into the hc.components layer as the last
source file, so it overrides each component’s own focus / state rules by
source order — no extra cascade layer, no specificity hacks.
Testing it
Section titled “Testing it”Emulate forced-colors in Chromium DevTools (Rendering → Emulate CSS media
feature forced-colors), or in Playwright:
await page.emulateMedia({ forcedColors: 'active' });Focus an input, tab through a combobox, toggle a checkbox — the indicators stay visible in the system palette.
Reduced motion
Section titled “Reduced motion”When the user sets prefers-reduced-motion, every animated component
neutralises its transition duration so state changes are instant rather
than animated. This is handled in CSS — no JavaScript, no configuration.
Components that animate in their own stylesheet (accordion, drawer, progress,
skeleton, spinner, switch, the OTP caret, the shell overlay, datagrid) gate
themselves; the remaining controls whose only motion is a transition
(button, checkbox, radio, input, select, datepicker, tabs, pagination, toggle
group) are covered centrally in hc.a11y.css, and the htmx indicator fade in
hc.htmx.css. The net effect: nothing in the kit animates under
reduced-motion.
// Verify in Playwright:await page.emulateMedia({ reducedMotion: 'reduce' });// getComputedStyle(button).transitionDuration === '0s'Motion that conveys meaning (a spinner indicating progress) keeps its role
via aria-*; reduced-motion only removes the decorative animation.
Right-to-left (RTL)
Section titled “Right-to-left (RTL)”Set dir="rtl" on <html> (or any subtree) and the kit follows. Layout is
built on CSS logical properties (margin-inline, inset-inline-start,
text-align: start, border-inline-end…), so spacing, alignment, borders,
and the components’ internal geometry mirror automatically — there are no
physical left / right rules to flip.
A few spots need genuine direction-awareness, and are handled for you:
- Datagrid frozen columns stick to the inline-start edge (right, in RTL), and the freeze-line shadow falls on the correct side.
- Calendar previous / next chevrons mirror so “previous” still points the natural way.
- Keyboard navigation. Horizontal ← / → are mirrored in RTL for the tabs, toggle group, datagrid cell grid, calendar, and splitter — ← moves to the inline-end (next) item. Vertical ↑ / ↓ are unchanged.
You can flip the whole documentation site to RTL with the Dir picker in the top bar to preview every component.