Accessibility
WCAG 2.2 AA, checked in a real browser: axe, target size, the focus ring and contrast.
Contrast
Contrast is measured from the real token values in every mode, as part of the build. Anything within 0.15 of a threshold counts as failing.
Target size
Every interactive element is at least 24 by 24 CSS pixels, and grows to 44 on touch and other coarse pointers.
import { TOUCH_TARGET } from 'topclassui/classes'
export function SaveButton() {
return <button type="button" className={TOUCH_TARGET}>Save</button>
}The shared class every control carries, and your own controls can carry it too. Its value: min-h-[var(--tc-target-min,24px)] min-w-[var(--tc-target-min,24px)] pointer-coarse:min-h-[var(--tc-target-coarse,44px)] pointer-coarse:min-w-[var(--tc-target-coarse,44px)]
Every drag has a keyboard path
WCAG 2.5.7. A Slider takes arrow keys. A Drawer and a Toast always render a close button.
Focus is always visible
One focus ring on every control: a CSS outline with an offset, so the gap shows the real background on any surface. --tc-ring reaches 3:1 on every surface.
import { FOCUS_RING } from 'topclassui/classes'
export function HomeLink() {
return <a href="/en" className={FOCUS_RING}>Home</a>
}Its value: outline-none focus-visible:outline-solid focus-visible:outline-(length:--tc-ring-width) focus-visible:outline-offset-(length:--tc-ring-offset) focus-visible:outline-ring
Labels are enforced by the types
An Input outside a Field needs an id, an aria-label or an aria-labelledby, and TypeScript rejects one without.
<Input placeholder="Email" />
// Type error: id, aria-label or aria-labelledby is requiredimport { Field } from 'topclassui/field'
import { Input } from 'topclassui/input'
export function Email() {
return (
<Field name="email" label="Email">
{(control) => <Input {...control} type="email" />}
</Field>
)
}Automatic and manual
Known gaps
Contrast is measured on every build. Axe, target size, the focus ring and long text inside its control are checked in a real browser on every demo, in 3 modes and 2 directions, and the interactive components have keyboard tests. Screen readers (NVDA, VoiceOver) and forced colors are checked by hand, and that has not been done yet.