# Accessibility

Source: https://lumeo.nativ.sh/docs/accessibility

# 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](https://www.w3.org/WAI/ARIA/apg/) 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.
