Accessibility overview
Yugen UI is built to be accessible by default: ARIA semantics from Radix, full keyboard navigation, visible focus and contrast that meets WCAG 2.1 AA.
Principles
Components handle the mechanics (roles, keys, focus); you handle the content (labels, headings, alt text, page order). An interface is accessible only when both are in place.
Semantics first
The right native element (button, a, input, table) and ARIA roles from Radix. No buttons built from a div.
Keyboard as capable as the mouse
Everything you can do with a mouse also works from the keyboard, following the WAI-ARIA APG interaction patterns.
Visible state
A 2px high-contrast focus ring; text at ≥ 4.5:1, control borders at ≥ 3:1; color is never the only signal.
Announced changes
Errors, notifications and async results are read out through live regions at the right level.
User preferences respected
prefers-reduced-motion turns off looping animations; the light / dark theme follows the OS; layouts reflow when zoomed.
Keyboard
Tab stops once in each group (roving tabindex); arrow keys move inside the group. In RTL, ← / → follow the reading direction.
| Component | Keys | Behavior |
|---|---|---|
| All controls | TabShift+Tab | Move to the next / previous control in DOM order. |
| Button, ToggleButton, Link | EnterSpace | Activate (Link: Enter only). ToggleButton toggles aria-pressed. |
| Checkbox, Switch | Space | Toggle the state. |
| RadioGroup, ToggleGroup, Toolbar | ←→↑↓HomeEnd | Move within the group (RadioGroup also selects the new item). |
| Tabs | ←→HomeEnd | Switch tabs and show the matching panel; ↑ / ↓ for vertical tabs. |
| Menu, ContextMenu, Menubar | Enter↓↑→Esc | Open, move between items, → opens a submenu, Esc closes and returns focus; type to jump to an item. |
| Dropdown | EnterSpace↑↓Esc | Open the listbox, select an option, type to jump (typeahead). |
| Combobox, TagPicker, Command | ↑↓EnterEscBackspace | Type to filter, ↑ / ↓ to highlight, Enter to select; Backspace in an empty input removes the last tag (TagPicker). |
| Slider | ←→PageUpPageDownHomeEnd | Decrease / increase by one step, by a large step, go to min / max. |
| Dialog, Drawer | EscTab | Focus stays inside the surface; Esc closes it (except modalType="alert"); focus returns to the trigger after closing. |
| Popover, HoverCard, Tooltip | Esc | Close. Tooltip opens when its trigger gets keyboard focus. |
| Accordion | EnterSpace↑↓HomeEnd | Open / close a panel, move between headers. |
| Tree | ↑↓→←HomeEnd | → expands a branch / moves to the first child, ← collapses a branch / moves to the parent. |
| List (navigationMode) | ↑↓→← | Move between items; in composite mode, → / ← move into / out of the interactive content of an item. |
| Toast | F8 | Jump to the notification region; Tab to the action / close buttons. |
Semantics for screen readers
Most of it comes from Radix; Yugen adds default labels in Vietnamese for close buttons, pagination and breadcrumbs.
| Component | Role / attributes |
|---|---|
| Dialog / DialogSurface | role="dialog" or alertdialog, aria-modal, name from DialogTitle, description from DialogDescription. |
| Menu | menu, menuitem, menuitemcheckbox, menuitemradio, aria-expanded on the trigger. |
| Tabs | tablist, tab (aria-selected, aria-controls), tabpanel. |
| Checkbox, Switch, Radio | checkbox (aria-checked="mixed" when indeterminate), switch, radiogroup / radio. |
| Slider | slider with aria-valuenow / min / max; name from label or aria-label. |
| Dropdown, Combobox | combobox + listbox / option, aria-expanded, aria-activedescendant. In a Field, the Combobox / TagPicker listbox is named by the label (aria-labelledby). |
| Breadcrumb, Pagination | nav with aria-label, current page aria-current="page". |
| Table | th scope="col", sortable columns have aria-sort; TableSelectionCell is labelled “Chọn hàng” (Select row). |
| MessageBar | role="alert" for error / warning, role="status" for info / success. |
| Toast | Radix notification region: error / warning toasts are read immediately (assertive), the rest politely (polite). |
| Spinner, ProgressBar | role="progressbar"; Spinner defaults to aria-label="Đang tải" (Loading). |
| Avatar, Persona | role="img" with the person's name; the status dot has a label. |
| Field, Input | label for, aria-describedby pointing to the hint / validation message, aria-invalid on error. |
Checklist before you ship
Tick items as you check them. The list is only kept while you are on this page.
0 of 10 done
Tools & related pages
- Automated checks: axe DevTools, Accessibility Insights for Web, Lighthouse (they find about 30–40% of issues; the rest needs manual testing).
- Screen readers: NVDA (Windows, free), Narrator, VoiceOver (macOS / iOS), TalkBack (Android).
- Chrome DevTools › Rendering: emulate
prefers-reduced-motion,prefers-color-scheme,forced-colorsand color vision deficiencies.
Further reading: