Accessibility
Contrast is a gate, never advice. A theme that fails any of these standards fails the build. This page runs the design system's own accessibility engine over the default theme at build time — so what you read here is exactly what `flexa validate`, the Design Studio and CI see.
The standards the engine gates on
Each standard answers a question the others cannot. Adding one never loosens another (PR-4): more gates, not weaker ones. The minimums below are read from the package constants, so they cannot drift from the code.
| Standard | Spec | Minimum | What it catches |
|---|---|---|---|
| WCAG 2 — text contrast | §1.4.3 | — | The classic 1–21 luminance ratio for readable glyphs. Every guaranteed text pair clears its floor in both schemes (see the contrast matrix on the Tokens page). |
| WCAG 2 — non-text contrast | §1.4.11 | — | The focus ring and every solid UI fill must stand out from the page even though they carry no text. A hairline border is exempt (it reads like subtle text, not a component). |
| APCA — perceptual lightness contrast | WCAG 3 candidate | 75 / 60 Lc | A signed Lc (≈ −108…+106) that weighs bright fills more harshly than WCAG 2. Added alongside the ratio, never in place of it. Body text needs Lc ≥ its floor; UI-label text on a fill needs a lower one. |
| Colour-vision deficiency | Machado 2009 | 15 ΔE | A contrast ratio cannot see two hues collapsing into one colour for a red-green or blue-yellow viewer. The brand primary and secondary are simulated for each deficiency and must stay clearly apart by CIE76 ΔE. |
Live diagnostics — the default theme
The engine normalises all four gates into one actionable list: what failed, in which scheme, by how much (in that standard's own unit), and the direction of the fix. These are the honest findings for the shipped default theme — surfaced here rather than hidden, and tracked as a design decision.
| Standard | Scheme | Tokens | Measured | Required | Remedy |
|---|---|---|---|---|---|
| APCA | dark | color.on-primary color.primary | 54.3 Lc | 60 Lc | APCA weighs bright fills more harshly than WCAG 2. Deepen the perceptual contrast of color.on-primary against color.primary — usually a darker fill or a heavier color.on-primary — to reach 60 Lc. |
| APCA | dark | color.on-secondary color.secondary | 53.7 Lc | 60 Lc | APCA weighs bright fills more harshly than WCAG 2. Deepen the perceptual contrast of color.on-secondary against color.secondary — usually a darker fill or a heavier color.on-secondary — to reach 60 Lc. |
| APCA | dark | color.on-success color.success | 44.2 Lc | 60 Lc | APCA weighs bright fills more harshly than WCAG 2. Deepen the perceptual contrast of color.on-success against color.success — usually a darker fill or a heavier color.on-success — to reach 60 Lc. |
| APCA | dark | color.on-warning color.warning | 45.4 Lc | 60 Lc | APCA weighs bright fills more harshly than WCAG 2. Deepen the perceptual contrast of color.on-warning against color.warning — usually a darker fill or a heavier color.on-warning — to reach 60 Lc. |
| APCA | dark | color.on-info color.info | 40.1 Lc | 60 Lc | APCA weighs bright fills more harshly than WCAG 2. Deepen the perceptual contrast of color.on-info against color.info — usually a darker fill or a heavier color.on-info — to reach 60 Lc. |
Colour-vision-deficiency simulation
The brand primary and secondary as they appear to viewers with each deficiency (Machado severity-1.0 matrices, the same Chrome DevTools uses). The two roles must read as clearly different colours — separated by lightness, not hue, because a hue rotation alone is invisible to a dichromat.
| Deficiency | Primary | Secondary | ΔE | Min 15 |
|---|---|---|---|---|
| Normal vision | #2563eb | #475569 | — | — |
| deuteranopia | #0064e8 | #4a5369 | 65.3 | distinct |
| protanopia | #0076f0 | #4e566a | 60.5 | distinct |
| tritanopia | #00869d | #3d595c | 25.4 | distinct |
High-contrast mode
When a viewer asks for more contrast, the theme answers. `emitTheme` auto-applies a high-contrast override under `@media (prefers-contrast: more)` — scoped to the light scheme so a dark viewer keeps dark — re-pointing the neutral and brand roles up to WCAG AAA (7:1). It is also available explicitly as the `hc` scheme.
13 roles re-pointed to WCAG AAA (7:1) under prefers-contrast: more.