Lumeo

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. --primary paired 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-foreground variable 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, pass aria-label="Description" via AdditionalAttributes.
  • Use semantic headings. Use the <Heading> component with appropriate Level values (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-scheme for automatic dark mode. Avoid overriding user system preferences without offering a toggle.