with one click
hex-core-accessibility
// Accessibility patterns for hex-core components. Load when the user asks about a11y, aria-label, screen reader, keyboard navigation, focus management, or WCAG compliance with hex-core.
// Accessibility patterns for hex-core components. Load when the user asks about a11y, aria-label, screen reader, keyboard navigation, focus management, or WCAG compliance with hex-core.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | hex-core-accessibility |
| description | Accessibility patterns for hex-core components. Load when the user asks about a11y, aria-label, screen reader, keyboard navigation, focus management, or WCAG compliance with hex-core. |
Hex Core components wrap Radix UI primitives, so most accessibility behavior (roles, keyboard nav, focus traps) is Radix's. The hex-core layer adds styling and a few conventions.
role="dialog", aria-expanded, aria-selected, aria-checked, aria-describedby on form controls.Select and Command support typeahead out of the box.aria-label// ❌ WRONG
<Button variant="outline" size="icon"><SettingsIcon /></Button>
// ✅ RIGHT
<Button variant="outline" size="icon" aria-label="Settings"><SettingsIcon /></Button>
The component won't warn — the CSS doesn't care — but a screen reader announces "button" with no label.
Label<Label htmlFor="email">Email</Label>
<Input id="email" type="email" />
Or via Form composition (FormLabel auto-wires htmlFor):
<FormField name="email" render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl><Input {...field} /></FormControl>
</FormItem>
)} />
Dialog and AlertDialog differ in semantics. AlertDialog sets role="alertdialog" and forces focus to Cancel by default. Use it for delete/destroy. Use plain Dialog for informational modals.
<AlertDialogCancel>Cancel</AlertDialogCancel> // focused by default — good default
<AlertDialogAction onClick={deleteAccount}>Delete</AlertDialogAction>
<SheetContent>
<SheetHeader>
<SheetTitle>Edit profile</SheetTitle>
</SheetHeader>
{/* Close button is auto-inserted with "Close" aria-label */}
</SheetContent>
Radix supplies the close button; don't add a second one.
Using the wrong one gives the wrong ARIA role and confuses screen readers.
aria-live="polite" by default. For critical alerts that interrupt, use Alert or AlertDialog instead.
| Component | Keys |
|---|---|
| Button | Enter, Space |
| Select | Arrow Up/Down, Home, End, typeahead, Esc |
| Dialog / Sheet | Esc to close, Tab cycles within |
| DropdownMenu | Arrow Up/Down, Enter, Esc, typeahead |
| Command | Arrow Up/Down, Enter, Esc |
| RadioGroup | Arrow keys cycle, Space/Enter selects |
| Tabs | Arrow Left/Right, Home, End |
| Accordion | Arrow Up/Down, Home, End, Enter/Space toggle |
The three shipped themes (default, midnight, ember) pass WCAG AA for background / foreground and primary / primary-foreground pairs. If you fork a theme, re-check your pairs — the CLI doesn't enforce it. Tool: https://webaim.org/resources/contrastchecker/
Every .schema.ts file has an ai.accessibilityNotes field with component-specific guidance. Call get_component_schema({name}) and read that field before shipping.