Accessibility
Lumeo is built with accessibility as a core principle. All components follow WAI-ARIA guidelines, support keyboard navigation, and work with screen readers out of the box.
Our approach
Accessibility is not an afterthought in Lumeo. Every component is designed from the start with proper semantic markup, ARIA attributes, keyboard interactions, and focus management. Our goal is to make it easy to build inclusive applications without requiring accessibility expertise from every developer on your team.
Lumeo components follow the WAI-ARIA Authoring Practices Guide for interaction patterns, and use native HTML semantics wherever possible. When ARIA roles are necessary, they are applied automatically so you do not need to add them manually.
Keyboard navigation
All interactive components in Lumeo are fully operable via keyboard. The library follows standard keyboard conventions so users who rely on keyboard navigation will find familiar interaction patterns.
General patterns
- Tab moves focus between interactive elements. Shift+Tab moves focus backward.
- Enter or Space activates buttons, toggles, checkboxes, and selectable items.
- Escape closes overlays including Dialog, Sheet, Drawer, Alert Dialog, Dropdown Menu, Popover, Context Menu, Combobox, and Color Picker.
- Arrow keys navigate within composite widgets like Select, Combobox, Dropdown Menu, Context Menu, Menubar, Tabs, Rating, Carousel, and OTP Input.
- Home and End jump to the first and last item in lists and menus.
Component-specific keyboard support
| Component | Keys | Behavior |
|---|---|---|
| Select | Up Down Enter Escape | Navigate options, select, close |
| Combobox | Up Down Enter Escape | Navigate filtered results, select, close |
| Dropdown Menu | Up Down Enter Escape | Navigate items, activate, close |
| Context Menu | Up Down Enter Escape | Navigate items, activate, close |
| Tabs | Left Right (or Up Down vertical) | Switch between tabs based on orientation |
| Dialog / Sheet / Drawer | Escape Tab | Close overlay, cycle focus within trap |
| Alert Dialog | Escape Tab | Close (if allowed), cycle focus within trap |
| Accordion | Enter Space | Toggle section open/closed |
| Carousel | Left Right | Navigate between slides |
| Rating | Left Right | Decrease or increase rating value |
| OTP Input | Left Right Backspace | Move between digits, delete and move back |
| Cascader | Up Down Right Escape | Navigate levels, expand children, close |
Focus management
Proper focus management is critical for keyboard and screen reader users. Lumeo handles focus automatically in overlay components so you do not need to manage it manually.
Focus trapping
When a modal overlay opens (Dialog, Sheet, Drawer, Alert Dialog), Lumeo automatically traps focus
inside the overlay content. Pressing Tab cycles through focusable elements within the overlay,
and focus cannot escape to the page behind it. This is implemented via
ComponentInteropService.SetupFocusTrap()
and cleaned up with
RemoveFocusTrap()
when the overlay closes.
Scroll locking
When a modal overlay is open, background scroll is locked via
ComponentInteropService.LockScroll()
to prevent users from accidentally scrolling the page behind the overlay.
Scroll is restored when the overlay closes. This applies to Dialog, Sheet, Drawer, Alert Dialog, Tour, and Image preview.
Click-outside dismissal
Non-modal overlays like Popover, Dropdown Menu, Context Menu, Combobox, and Color Picker register
click-outside handlers via
ComponentInteropService.RegisterClickOutside().
Clicking outside the overlay content dismisses it, which is the expected behavior for these patterns.
Focus-visible rings
All interactive elements display a visible focus ring when navigated to via keyboard. The ring uses the
focus-visible
pseudo-class, so it only appears for keyboard users and does not show on mouse click. The ring color
is set via the --ring
CSS variable, which adapts to light and dark mode.
Cleanup
All overlay components implement IAsyncDisposable
to properly clean up focus traps, scroll locks, and click-outside handlers. Cleanup code handles
JSDisconnectedException
gracefully to avoid errors during Blazor circuit disconnection.
Screen reader support
Lumeo components use semantic HTML elements and ARIA attributes to provide a meaningful experience for screen reader users. Roles, states, and properties are applied automatically.
ARIA roles and attributes by component
| Component | ARIA Role | Key Attributes |
|---|---|---|
| Dialog | dialog |
aria-modal, aria-labelledby, aria-describedby |
| Alert Dialog | alertdialog |
aria-modal, aria-labelledby, aria-describedby |
| Sheet / Drawer | dialog |
aria-modal, aria-labelledby, aria-describedby |
| Alert | alert |
Dismiss button has aria-label |
| Toast | alert |
Live region announcements for screen readers |
| Checkbox | checkbox |
aria-checked (supports mixed for indeterminate) |
| Switch | switch |
aria-checked |
| Toggle | button | aria-pressed |
| Toggle Group | group |
Each item has aria-pressed |
| Radio Group | radiogroup |
aria-label, aria-labelledby; items have aria-checked |
| Select | combobox / listbox |
aria-haspopup, aria-expanded, aria-controls, aria-activedescendant |
| Combobox | combobox / listbox |
aria-haspopup, aria-expanded, aria-autocomplete, aria-activedescendant |
| Dropdown Menu | button / menu | aria-haspopup, aria-expanded, aria-controls; items have menuitem |
| Context Menu | menuitem / menuitemcheckbox / menuitemradio |
aria-checked on checkbox and radio items |
| Tabs | tablist / tab / tabpanel |
aria-selected, aria-controls, aria-orientation, aria-labelledby |
| Accordion | button | aria-expanded on trigger buttons |
| Rating | radiogroup |
aria-label ("Rate X out of Y") on each star |
| Progress | progressbar |
aria-valuenow, aria-valuemin, aria-valuemax |
| Breadcrumb | navigation |
aria-label="breadcrumb"; current page has aria-current="page" |
| Pagination | navigation |
aria-label="pagination" |
| Carousel | region |
aria-roledescription="carousel"; slides have aria-roledescription="slide" |
| Tooltip | tooltip |
Content announced on focus/hover |
| Tree View / Tree Select | tree / treeitem |
aria-expanded, aria-selected |
| Menubar | menubar |
Items use menuitem role |
| Steps | list / listitem |
Semantic step progression |
Color and contrast
Lumeo uses CSS custom properties for all colors, which means color contrast can be controlled at the theme level rather than per component.
-
No hardcoded colors. Every color in Lumeo is a CSS variable (
--foreground,--primary,--muted, etc.). Swapping the theme swaps all colors at once. -
Dark mode via variable swaps. Dark mode is handled entirely through CSS variable overrides. There are no
dark:Tailwind prefixes anywhere in the library, ensuring a consistent and clean approach. -
Foreground / background pairing. Every background color variable has a matching foreground variable (e.g.
--primarypaired with--primary-foreground) to maintain readable contrast ratios. - Built-in themes tested for contrast. The 7 built-in color themes (Zinc, Blue, Green, Rose, Violet, Amber, Teal) are designed with sufficient contrast between foreground and background in both light and dark modes.
-
Muted text uses proper contrast. The
--muted-foregroundvariable is calibrated to provide readable secondary text without disappearing against the background.
Best practices for your app
While Lumeo handles component-level accessibility, there are application-level practices you should follow to ensure a fully accessible experience.
-
Use Label with form inputs. Always pair Input, Select, Checkbox, Radio Group, Switch, and other form controls with a
<Label>component. This creates an accessible name for screen readers. -
Provide meaningful text. Avoid icon-only buttons without an
aria-label. If a button only has an icon, passaria-label="Description"via AdditionalAttributes. -
Use semantic headings. Use the
<Heading>component with appropriateLevelvalues (1 through 6) to create a logical heading hierarchy. Screen readers use headings to navigate page structure. - Test with keyboard only. Try navigating your application using only the keyboard. Every action should be reachable without a mouse.
- Test with a screen reader. Run through key flows with NVDA (Windows), VoiceOver (macOS), or Narrator (Windows) to verify the experience.
-
Respect user preferences. Lumeo supports
prefers-color-schemefor automatic dark mode. Avoid overriding user system preferences without offering a toggle.