Accessibility
Accessibility is not optional in the Mukoko ecosystem. Every component in this registry is built to meet strict accessibility standards, ensuring usability for all people across Africa’s diverse digital landscape.
Contrast requirements
The Mukoko design system uses APCA 3.0 AAA (Advanced Perceptual Contrast Algorithm) rather than the older WCAG 2.x contrast ratio. APCA is more perceptually accurate, particularly for the warm cream and deep night backgrounds used in our palette.
Minimum contrast values
| Text type | Minimum APCA Lc | Example |
|---|---|---|
| Body text (16px) | Lc 75 | --foreground on --background |
| Large text (24px+) | Lc 60 | Headings on cards |
| UI controls | Lc 60 | Button labels, form inputs |
| Placeholder text | Lc 45 | Input placeholders |
Testing contrast
Every pairing of foreground and background tokens has been validated. When adding new tokens:
- Test in both light and dark themes
- Use the APCA contrast calculator (not the WCAG 2.x ratio checker)
- Verify with
--muted-foregroundon--muted,--foregroundon--card, etc.
Touch targets
All interactive elements must meet a 48px minimum touch target size. This is critical for mobile users, who make up the majority of Mukoko’s audience.
// Correct — 48px touch target via padding
<Button size="default" className="h-10 px-4">
Submit
</Button>
// Also correct — icon button with sufficient size
<Button size="icon" className="size-10">
<Menu className="size-5" />
</Button>For smaller visual elements (like checkbox indicators), ensure the clickable area extends to 48px via padding:
<label className="flex min-h-[48px] items-center gap-3 px-3">
<Checkbox />
<span>Accept terms</span>
</label>Keyboard navigation
All Mukoko components use Radix UI primitives for accessible keyboard interaction. Radix handles:
- Focus management — focus trapping in modals, focus restoration on close
- Arrow key navigation — within menus, tabs, radio groups, comboboxes
- Escape to close — dialogs, dropdowns, popovers, sheets
- Enter/Space to activate — buttons, checkboxes, toggles
- Home/End — jump to first/last item in lists
Focus indicators
All focusable elements display a visible focus ring using the Tailwind focus-visible variant:
focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ringNever remove focus indicators. They are essential for keyboard users.
Screen reader support
Semantic HTML
Use the correct HTML element for its purpose:
<button>for actions, not<div onClick><a>for navigation<nav>for navigation landmarks<main>for primary content<h1>through<h6>in order, no skipped levels
ARIA attributes
Radix UI components include ARIA attributes automatically. For custom components:
// Describe the purpose of icon-only buttons
<Button aria-label="Close dialog" size="icon">
<X className="size-4" />
</Button>
// Link related elements
<Label htmlFor="email-input">Email</Label>
<Input id="email-input" type="email" />
// Announce dynamic content
<div aria-live="polite" aria-atomic="true">
{statusMessage}
</div>Testing screen readers
Test with at least one screen reader:
- macOS: VoiceOver (built in, Cmd+F5)
- Windows: NVDA (free)
- Mobile: TalkBack (Android), VoiceOver (iOS)
Color independence
Never use color as the sole indicator of meaning. Always pair color with:
- Text labels — “Error: Invalid email” not just a red border
- Icons — checkmark for success, X for error
- Patterns — striped or dotted backgrounds for emphasis
The Five African Minerals palette is designed to be distinguishable to people with common color vision deficiencies. The mineral accents were chosen with this constraint in mind.
Checklist
When building or reviewing components, verify:
- Contrast meets APCA 3.0 AAA in both light and dark themes
- Touch targets are at least 48px
- Keyboard navigation works for all interactions
- Focus indicators are visible
- Screen reader announces the component’s purpose and state
- Color is not the sole indicator of meaning
- Heading levels are sequential (no skipping)