VayuUI

Tour

A step-by-step guided tour component that highlights elements with a spotlight overlay and positions a popover with navigation controls.

Installation

npx vayu-ui-cli@latest add tour

Usage

Tour Demo

Feature A

Feature B

Anatomy

<Tour
  steps={steps}
  isOpen={open}
  onClose={() => setOpen(false)}
  onComplete={() => setOpen(false)}
  onSkip={() => setOpen(false)}
  showProgress={true}
  showStepNumbers={true}
  maskClickable={false}
  closeOnEscape={true}
  closeOnMaskClick={false}
  scrollBehavior="smooth"
  highlightedAreaClassName="custom-spotlight"
  maskClassName="custom-mask"
>
  {/* Your application content — target elements identified by CSS selectors */}
</Tour>

Accessibility

  • Keyboard navigation: ArrowRight advances to the next step, ArrowLeft goes to the previous step, Escape closes the tour (when closeOnEscape is true)
  • ARIA attributes: role="dialog" with aria-modal="true" on the popover, aria-labelledby referencing the dialog title, role="progressbar" with aria-valuenow, aria-valuemin, aria-valuemax, and aria-label on the progress bar
  • Focus management: Body scroll is locked during the tour; the target element is scrolled into view with block: 'center' and inline: 'center'
  • Screen reader live region: A visually hidden div with aria-live="polite" and aria-atomic="true" announces step changes

Screen reader behavior

When a tour step changes, the live region announces: "Step N of M: [step title]". The popover is identified as a dialog via role="dialog" and aria-modal="true", informing screen readers that content outside the tour is temporarily inert. The progress bar conveys completion percentage through role="progressbar" with current, minimum, and maximum values. All navigation buttons include descriptive aria-label attributes for context.

Component Folder Structure

Tour/
├── Tour.tsx              # Root component with TourContext, state management, keyboard handling
├── TourOverlay.tsx       # SVG mask overlay with spotlight cutout
├── TourPopover.tsx       # Dialog popover with arrow, header, body, progress, footer
├── use-position.ts       # Popover position calculation with viewport clamping
├── use-target.ts         # Target element finding, MutationObserver, scroll/resize handling
├── hooks.ts              # useTour context consumer hook
├── types.ts              # TypeScript interfaces (TourStep, TourContextValue, TourProps)
├── index.ts              # Public exports
└── README.md             # Internal documentation

Props

Tour

PropTypeDefaultDescription
stepsTourStep[]—Array of tour step definitions
isOpenbooleanfalseControlled open state
onClose() => void—Callback fired when the tour closes
onComplete() => void—Callback fired when the last step completes
onSkip() => void—Callback fired when the user skips
showProgressbooleantrueShow progress bar
showStepNumbersbooleantrueShow step counter badge
maskClickablebooleanfalseAllow pointer events through overlay
closeOnEscapebooleantrueClose on Escape key
closeOnMaskClickbooleanfalseClose when clicking the overlay
scrollBehaviorScrollBehavior"smooth"Scroll-into-view behavior
highlightedAreaClassNamestring—Class name for the spotlight border
maskClassNamestring—Class name for the overlay mask

TourStep

PropTypeDefaultDescription
targetstring—CSS selector for the target element
titlestring—Step heading
contentstring | ReactNode—Step body
placement'top' | 'bottom' | 'left' | 'right' | 'center'"bottom"Popover placement
spotlightPaddingnumber8Spotlight cutout padding
disableInteractionbooleanfalseBlock pointer events on target
showSkipbooleantrueShow skip button for this step
nextButtonTextstring"Next"Override next button label
prevButtonTextstring"Previous"Override previous button label
onNext() => void | Promise<void>—Async hook before advancing
onPrev() => void | Promise<void>—Async hook before going back
customButtonsReactNode—Replace the default button row

useTour Hook

const { isOpen, currentStep, steps, goToStep, nextStep, prevStep, close, skip } = useTour();

Access tour state and controls from any component rendered inside <Tour>. Throws an error if used outside the Tour provider.

On this page