diff --git a/ACCESSIBILITY_CHECKLIST.md b/ACCESSIBILITY_CHECKLIST.md new file mode 100644 index 0000000000..6ba0dad22a --- /dev/null +++ b/ACCESSIBILITY_CHECKLIST.md @@ -0,0 +1,248 @@ +# Accessibility Checklist + +This checklist should be used when developing or reviewing components in the Ultraviolet design system. + +## ✅ Critical Checks (Must Pass) + +### Keyboard Navigation +- [ ] All interactive elements are keyboard accessible (Tab, Enter, Space, Arrow keys where appropriate) +- [ ] Focus order is logical and follows visual order +- [ ] Focus is visible and clear (minimum 3:1 contrast ratio) +- [ ] No keyboard traps (users can navigate away from all components) +- [ ] Custom components handle keyboard interactions appropriately: + - Enter/Space activates buttons + - Arrow keys navigate within composite widgets (menus, tabs, etc.) + - Escape closes popups, menus, and dialogs + +### Screen Reader Support +- [ ] All interactive elements have accessible names (via text content, `aria-label`, or `aria-labelledby`) +- [ ] Icons without visible text have `aria-label` or `aria-hidden="true"` if decorative +- [ ] Form inputs have associated labels (via `htmlFor`/`id` or `aria-labelledby`) +- [ ] Error messages are associated with inputs (via `aria-describedby` or `aria-errormessage`) +- [ ] Dynamic content changes are announced (using `aria-live` regions where appropriate) +- [ ] Images have meaningful `alt` text (or `alt=""` if decorative) + +### ARIA Attributes +- [ ] ARIA roles are used correctly and only when necessary (prefer native HTML elements) +- [ ] Required ARIA attributes are present for custom widgets: + - Combobox: `aria-expanded`, `aria-controls`, `aria-haspopup` + - Menu: `role="menu"`, `aria-haspopup="menu"` + - Tab: `role="tab"`, `aria-selected`, `aria-controls`, `id` + - TabList: `role="tablist"`, `aria-orientation` + - Slider: `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, `aria-valuetext` + - Progressbar: `aria-valuenow`, `aria-valuemin`, `aria-valuemax` + - Dialog/Modal: `aria-modal`, `aria-labelledby`, `aria-describedby` +- [ ] State attributes reflect current state (`aria-expanded`, `aria-selected`, `aria-pressed`, `aria-checked`) +- [ ] `aria-current="page"` is used for current page in navigation/breadcrumbs/pagination + +### Focus Management +- [ ] Focus is moved appropriately when opening modals/dialogs +- [ ] Focus is trapped within modals/dialogs when open +- [ ] Focus returns to trigger element when closing popups/dialogs +- [ ] Focus is managed correctly in multi-step processes +- [ ] `tabIndex` is used appropriately: + - `tabIndex="0"` to make non-interactive elements focusable + - `tabIndex="-1"` to remove elements from tab order + - Roving tabIndex for composite widgets (menus, toolbars, etc.) + +### Semantic HTML +- [ ] Proper heading hierarchy (h1 → h2 → h3, no skipped levels) +- [ ] Lists use proper list markup (`