What Makes a React Component Accessible (and Why Radix Matters)
Keyboard navigation, focus management, and ARIA are where accessibility quietly breaks. Here's what 'accessible' actually means for interactive components — and how Ninna UI handles it.
By Ninna UI Team
"Accessible" gets thrown around a lot, but for interactive components it has a concrete meaning. A button is easy. A combobox, a modal, or a menu is where things quietly fall apart — and where most hand-rolled components fail real users.
The three pillars
- Keyboard navigation: every interaction possible with a mouse must work with a keyboard — arrow keys in menus, Escape to close, Enter/Space to activate.
- Focus management: focus must move predictably. Open a modal and focus moves in and is trapped; close it and focus returns to the trigger.
- ARIA semantics: screen readers need correct roles, states, and relationships (aria-expanded, aria-controls, role="dialog", and so on).
If you've ever opened a custom dropdown and found that Tab moved focus to the page behind it, you've felt the cost of getting focus management wrong.
Why this is so hard to do by hand
The WAI-ARIA authoring practices for a single widget like a combobox run for pages. Edge cases — typeahead, focus restoration after deletion, RTL support — are easy to miss and tedious to test. This is why so many in-house component libraries have subtle accessibility bugs.
Standing on Radix's shoulders
Radix UI Primitives implement these behaviours correctly and are battle-tested across thousands of apps. The trade-off with using Radix directly is that you style everything yourself and manage each @radix-ui package as a dependency.
Ninna UI wraps Radix internally for complex widgets, so you get its accessibility guarantees with styling and theming already done — and Radix never appears in your dependency tree or your code.
import { DropdownMenu } from "@ninna-ui/overlays";
<DropdownMenu>
<DropdownMenu.Trigger>Options</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item>Edit</DropdownMenu.Item>
<DropdownMenu.Item>Delete</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>Arrow-key navigation, typeahead, focus trapping, and ARIA wiring all work out of the box. Accessibility shouldn't be a feature you bolt on later — it should be the default. That's the bar we hold Ninna UI to, audited with automated vitest-axe checks.