Accessibility
VelinStyle targets WCAG 2.2 Level AAA token defaults and component contracts — certification of your application remains your responsibility. See the AAA conformance matrix. For lighter AA contrast, set data-velin-contrast="aa" on <html>. Run npm run test:a11y:coverage for framework coverage.
Built-in features
Focus Visible
All interactive elements have a clear :focus-visible ring. Try pressing Tab to navigate this page.
:focus-visible {
outline: 3px solid var(--velin-color-focus);
outline-offset: 2px;
}
Screen Reader Only
Use .velin-sr-only to hide text visually while keeping it accessible.
<button class="velin-btn"> <svg aria-hidden="true">...</svg> <span class="velin-sr-only">Close</span> </button>
Skip Link
Every page should have a .velin-skip-link as the first focusable element.
<a href="#main" class="velin-skip-link"> Skip to main content </a>
Reduced Motion
All animations are disabled when prefers-reduced-motion: reduce is set.
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; }
}
Touch Targets
All buttons, links, and form controls have a minimum touch target of 44x44px.
.velin-btn {
min-block-size: 2.75rem;
min-inline-size: 2.75rem;
}
Forced Colors
All components adapt to Windows High Contrast mode via forced-colors: active.
Skeleton Loading (CLS Protection)
Skeleton placeholders reserve space for content, preventing layout shifts.
WCAG 2.2 checklist
| Criterion | Status | How VelinStyle Helps |
|---|---|---|
| 1.4.3 Contrast (Minimum) | Built-in | AAA defaults exceed 7:1; data-velin-contrast="aa" for 4.5:1 palette |
| 2.1.1 Keyboard | Built-in | Focus-visible ring, focus trapping, roving tabindex |
| 2.4.1 Bypass Blocks | Built-in | .velin-skip-link component |
| 2.4.7 Focus Visible | Built-in | Global :focus-visible with 3px outline |
| 2.4.11 Focus Not Obscured | Built-in | scroll-padding-block-start via .velin-scroll-pt-nav |
| 2.5.5 / 2.5.8 Target Size | Built-in | .velin-target-touch — 44px on primary controls |
| 2.3.3 Animation | Built-in | prefers-reduced-motion respected globally |
| 3.2.6 Consistent Help | Patterns | Documented in A11y patterns |
| 1.4.6 Contrast (Enhanced) | Default | Token pairs validated via npm run test:contrast |
CSS brings accessibility
VelinStyle loads an @layer a11y bundle with skip links, screen-reader utilities, focus appearance, reduced motion, forced colors, target size on controls, and default scroll-padding for focus-not-obscured (2.4.11). Color tokens in src/tokens/color.css are tuned for AAA; optional AA via data-velin-contrast="aa".
import { initA11y } from '@birdapi/velinstyle/a11y';
initA11y({ announcer: true, scrollPadding: true });
Measure framework coverage: npm run test:a11y:coverage · per-page axe: npm run test:a11y · token contrast: npm run test:contrast.