Accessibility Statement
Every component ships against automated keyboard, contrast and screen-reader checks — the static gates fail CI on a regression and the rendered checks gate every release — not a one-time audit we did once and stopped measuring.
Last reviewed October 2026
Conformance status
Styloviz's free and Pro component libraries, the showcase site, and all 21 bundled templates are built to conform to the Web Content Accessibility Guidelines (WCAG) 2.1, Level AA . We describe this as substantially conformant rather than fully certified: automated tooling and a manual keyboard/focus sweep cover a large, well-defined surface (below), but no automated scan can prove every WCAG success criterion for every combination of assistive technology and browser. Where we know of a gap, we say so in Known limitations below, rather than leaving it undocumented.
What's built in
Full keyboard operation
Every interactive component is reachable and operable without a pointer — arrow-key roving where a widget owns a group, Escape to dismiss anything that opened over the page, and Enter/Space activation on custom controls.
Visible focus, never suppressed
Focus rings use `focus-visible` so they appear for keyboard users without following a mouse click, and they are checked for contrast against the surface behind them in both light and dark themes.
Semantic structure and ARIA
Native elements first, ARIA only where no native element exists. Roles, names and states are asserted in unit tests, and a static invariant check rejects an `aria-label` on an element with no role to carry it.
Contrast in both themes
Every text/background pair in the kit is checked against its WCAG AA threshold in light and dark mode, so a theme switch can never quietly drop a label below the ratio it passed at.
Respects reduced motion
Chart entrance animations, transitions and auto-advancing surfaces read `prefers-reduced-motion` and stand still when the user has asked the system for less movement.
A semantic equivalent for every visual surface
Where a fact reaches the page only as geometry — a bar’s height, a card’s column, a calendar cell’s colour step, a tile’s position in a grid — the component publishes a table saying it in words, from one shared implementation. It mirrors what is drawn rather than the data behind it, so collapsed rows, hidden widgets and a zoomed chart's window are reflected in the summary too: an alternative that contradicts the picture is worse than none.
Announced loading and error states
Data components render a shared set of loading, error, retry and empty shells that carry the right live-region semantics, so a screen-reader user learns that a fetch failed rather than meeting an empty region.
How we enforce it
Every mechanism below runs against the live codebase, not a snapshot. The static gates fail CI on a regression, the same as any other bug; the rendered axe sweep and the unit tests are part of the full gate every release must pass.
| Mechanism | What it checks | Runs |
|---|---|---|
| ESLint a11y rule set | Angular template rules for missing labels, non-interactive elements carrying handlers, positive tabindex, redundant roles and inaccessible custom controls. | Every lint run and every build. |
| Static UI-invariant check | Repo-specific rules the linters do not have: prohibited ARIA attributes, decorative SVGs missing `aria-hidden` (walking the inherited tag stack), a described-by that drops a description, an aria-label outranked by a nested one, and unreachable retry actions. | Every build; a violation fails CI. |
| axe-core against the live showcase | Automated WCAG rule evaluation over rendered pages, so a violation is measured against real DOM and real computed styles rather than source. | Every end-to-end sweep. |
| Contrast gate | Every same-element foreground/background pair in the kit, resolved to actual theme colours and compared against its WCAG AA threshold — in light and dark mode. | Every build. |
| Component unit tests | Roles, accessible names, keyboard interaction and focus movement asserted per component, including the loading/error/empty states. | Every test run. |
| Visual-alternatives ledger | Every geometry-driven surface is listed with how it publishes a semantic equivalent, and each entry must prove its claim: one that says “shared summary table” has to render it, one that says “already semantic” has to contain the element it leans on — a table, an ordered list, a list role. It also rejects a hand-rolled visually-hidden table, because `sr-only` cannot clip a `display: table` box and four chart families learned that separately. | Every build; a violation fails CI. |
| Reduced-motion and non-colour ledger | Across the data-display components, every looping ping, pulse or bounce must be motion-safe or stilled under `prefers-reduced-motion`. A ledger of the motion surfaces — carousel autoplay, the pulsing badge dot, the like burst, the gift-card sheen, the line clamp and the card flip — and of the status shown as colour — avatar presence, badge tone, heatmap bins, timeline variants, product availability — must each prove its claim in source. | Every build; a violation fails CI. |
| Keyboard-at-scale ledger | List View, Tree, Data Table, Transfer and Kanban each keep ONE tab stop per collection however many rows it holds, with arrows, Home/End, PageUp/PageDown that clamp rather than wrap, and typeahead — all from one shared contract in the core package. Each family must prove it in source and name the spec that renders a large dataset and counts the tab stops, and it rejects a static `tabindex="0"` repeated per row. It also records each family’s documented ceiling: 2,000 rendered rows, the page size for a paginated table, or virtualization. | Every build; a violation fails CI. |
| Focus-restoration ledger | One rule for where focus goes when the thing holding it disappears — the item now at the same position, then the one before it, then the container, never the top of the page. A comment posting, a file removed, a card moved, a tree node deleted, a lightbox closing and a table row filtered away are each recorded with the shared helper they use and the spec that checks where focus actually landed. | Every build; a violation fails CI. |
| Manual keyboard and focus sweep | A human pass over every interactive component and template page: tab order, focus trapping in overlays, focus restoration on close, and escape routes. | Before each release and whenever a new interactive component ships. |
Known limitations
Stated plainly rather than left implicit — a component library cannot make every promise a fully custom-audited application can.
Not verified against every screen reader
Testing focuses on current versions of NVDA and VoiceOver with Chrome, Firefox and Safari. Older combinations, and JAWS-specific behaviours, are not part of the automated matrix — differences there are possible.
Composition is the integrator’s responsibility
A component can guarantee its own semantics, not the page you place it in. Heading order, landmark structure, page titles and the reading order of a screen you assemble from these parts remain yours to verify.
Your content decides some criteria outright
Alt text, link purpose, language of parts, and the readability of your copy cannot be supplied by a component. Chart colours are configurable, so a palette you override can fall below the contrast the defaults pass at.
Dense data surfaces have practical ceilings
Very large virtualised tables and charts with hundreds of marks expose fewer individual elements to assistive technology than a small one does — the summary and the keyboard path are accessible, but not every rendered mark is a separate stop. A collection that renders every row (not virtualized, not paginated) has a documented ceiling of 2,000 rows, past which it warns in development.
Found an accessibility issue?
Automated tooling catches a lot, but not everything — tell us what you found and we'll investigate. Every confirmed issue gets fixed and, where possible, turned into a permanent automated check so the same defect class can't return.
This statement describes the Styloviz component libraries, showcase site and bundled templates as they exist today. It is reviewed and re-verified against the checks above whenever the accessibility tooling or component set changes materially.