react-tourlight

Accessibility

Focus management, keyboard behavior, ARIA semantics, reduced motion, and what to verify in your integration.

react-tourlight includes focus management, keyboard navigation, ARIA semantics, and reduced-motion behavior. These are building blocks for an accessible guide, not a certification of your application. Test your content, theme contrast, custom tooltips, and interactive targets with the input methods and assistive technologies your users rely on.

Focus management

When the tooltip is displayed, focus moves to its primary action. Non-interactive steps keep focus within the tooltip; interactive steps also need access to the highlighted target. On dismissal, focus should return to the control that launched the guide. Include this behavior in your browser checks, especially when routes or dialogs replace that control.

Focus trap

On non-interactive steps, Tab cycles through the tooltip's controls. On interactive steps, the highlighted target remains available to keyboard users. Verify that custom tooltips and application dialogs preserve a usable focus order.

Keyboard navigation

All tours and highlights support full keyboard navigation:

KeyAction
EscapeDismiss the tour or highlight
Right ArrowGo to the next step
Left ArrowGo to the previous step
TabNavigate available controls; non-interactive steps trap focus in the tooltip
Shift + TabReverse cycle through tooltip buttons
Enter / SpaceActivate the focused button

Escape can be disabled per-provider with escToDismiss={false}, though this is not recommended for accessibility.

ARIA attributes

The tooltip is rendered as a dialog with proper ARIA semantics:

  • role="dialog" -- Identifies the tooltip as a dialog to assistive technology
  • aria-labelledby -- Points to the step title element, giving the dialog an accessible name
  • aria-describedby -- Points to the step content element, giving the dialog an accessible description
  • aria-live="polite" -- Announces step changes to screen readers without interrupting the current announcement queue

Example rendered markup

<div
  role="dialog"
  aria-labelledby="spotlight-title-0"
  aria-describedby="spotlight-content-0"
>
  <h2 id="spotlight-title-0">Search</h2>
  <p id="spotlight-content-0">Find anything instantly with our search.</p>
  <button>Next</button>
  <button>Skip</button>
</div>

Screen reader support

Step changes use an aria-live region. Announcement behavior can vary with the screen reader, browser, content, and custom rendering. Test the combinations your application supports; automated ARIA checks alone do not establish that the whole journey is understandable.

prefers-reduced-motion

react-tourlight respects the prefers-reduced-motion media query. When this preference is enabled:

  • Spotlight transitions between steps are instant (no animation)
  • Tooltip enter/exit animations are disabled
  • The overlay fades in without the smooth clip-path transition

No configuration is needed. This behavior is automatic and CSS-based.

Inert background content

While the spotlight UI is active, off-path background content is marked with inert. For interactive steps, the target's subtree remains available. Inert content:

  • Cannot receive focus via Tab
  • Is excluded from the accessibility tree
  • Does not receive user click interactions

This ensures that users navigating with a screen reader or keyboard stay within the tour context.

Semantic button elements

All interactive elements in the tooltip (Next, Previous, Skip, Done, Close) are rendered as semantic <button> elements with descriptive text labels. This ensures they are:

  • Discoverable by screen readers
  • Activatable via Enter or Space
  • Properly included in the tab order
  • Visually identifiable as interactive controls

Checklist

Here's a summary of the accessibility features built into react-tourlight:

  • Focus trap inside tooltip
  • Focus restored on tour end
  • Escape key dismisses tour
  • Arrow key navigation between steps
  • role="dialog" on tooltip
  • aria-labelledby and aria-describedby set
  • aria-live="polite" for step announcements
  • inert on background content
  • prefers-reduced-motion respected
  • Semantic <button> elements throughout
  • Keyboard behavior to verify with your application and custom components