Skip to main content
Create interactive product tours and onboarding experiences with smart positioning, progress tracking, and completion persistence. Perfect for helping users discover features in your application.

Installation

npx shadcn@latest add https://rigidui.com/r/guided-tour.json

Usage

import { TourProvider, TourStep, TourTrigger } from '@/components/guided-tour'
import { Button } from '@/components/ui/button'

export default function App() {
  return (
    <TourProvider
      autoStart={false}
      onTourComplete={() => console.log('Tour completed!')}
      onTourSkip={() => console.log('Tour skipped!')}
    >
      <div className="p-4">
        <TourTrigger>
          <Button>Start Tour</Button>
        </TourTrigger>

        <TourStep
          id="step-1"
          title="Welcome"
          content="Welcome to our application!"
          order={1}
          position="bottom"
        >
          <div className="p-4 border rounded">Main Content</div>
        </TourStep>

        <TourStep
          id="step-2"
          title="Features"
          content="Here are the main features."
          order={2}
          position="right"
        >
          <aside className="p-4 border rounded">Sidebar</aside>
        </TourStep>
      </div>
    </TourProvider>
  )
}

Features

Interactive Guidance

Highlight specific elements on your interface and provide contextual explanations to guide users.

Smart Positioning

Automatically calculates optimal popover positioning based on viewport space and element location.

Completion Tracking

Tracks tour completion status to prevent showing the tour repeatedly to users who have already completed it.

Progress Tracking

Built-in progress indicator shows users how many steps remain with smooth transitions.

Keyboard Navigation

Supports keyboard navigation for accessibility and power users.

Auto-Start

Optionally auto-start the tour for new users with configurable conditions.

API Reference

TourProvider

children
ReactNode
required
The content to be wrapped by the tour provider
autoStart
boolean
default:"false"
Whether to automatically start the tour when the component mounts
ranOnce
boolean
default:"true"
Whether the tour should only run once per user/device
storageKey
string
default:"'rigidui-tour-completed'"
Key used to store tour completion status in localStorage
shouldStart
boolean
default:"true"
Whether the tour should start based on external conditions (e.g., user preferences)
onTourComplete
() => void
Callback function called when the tour is completed
onTourSkip
() => void
Callback function called when the tour is skipped

TourStep

id
string
required
Unique identifier for the tour step
title
string
required
Title displayed in the tour step popover
content
string
required
Content/description text for the tour step
order
number
required
The order in which this step should appear in the tour sequence
position
'top' | 'bottom' | 'left' | 'right'
default:"'bottom'"
Preferred position for the popover relative to the target element
children
ReactNode
required
The element(s) to be highlighted and explained in this tour step

TourTrigger

children
ReactNode
required
The content to be rendered as the tour trigger button
className
string
Additional CSS classes for styling the trigger
hideAfterComplete
boolean
default:"false"
Whether to hide the trigger button after the tour is completed
storageKey
string
default:"'rigidui-tour-completed'"
Key to check for tour completion status (should match TourProvider’s storageKey)

useTour Hook

A hook that provides access to tour state and controls.
const {
  registerStep,
  unregisterStep,
  startTour,
  stopTour,
  nextStep,
  prevStep,
  resetTourCompletion,
  isActive,
  currentStepId,
  currentStepIndex,
  totalSteps
} = useTour()
isActive
boolean
Whether the tour is currently active
currentStepId
string | null
ID of the currently active step
currentStepIndex
number
Index of the current step (0-based)
totalSteps
number
Total number of steps in the tour
startTour
() => void
Function to start the tour
stopTour
() => void
Function to stop the tour
nextStep
() => void
Function to move to the next step
prevStep
() => void
Function to move to the previous step
resetTourCompletion
() => void
Function to reset tour completion status

Examples

Feature Discovery Tour

import { TourProvider, TourStep, TourTrigger } from '@/components/guided-tour'
import { Sparkles } from 'lucide-react'

function FeatureTour() {
  return (
    <TourProvider autoStart={false}>
      <div className="app">
        <header>
          <TourTrigger>
            <button className="flex items-center gap-2">
              <Sparkles className="w-4 h-4" />
              Discover Features
            </button>
          </TourTrigger>
        </header>

        <TourStep
          id="create-button"
          title="Create New Content"
          content="Click here to create new posts, articles, or projects."
          order={1}
          position="bottom"
        >
          <button className="create-btn">Create New</button>
        </TourStep>

        <TourStep
          id="search-bar"
          title="Smart Search"
          content="Use our powerful search to find anything instantly."
          order={2}
          position="bottom"
        >
          <input placeholder="Search..." className="search-input" />
        </TourStep>
      </div>
    </TourProvider>
  )
}

Multi-Step Onboarding

import { TourProvider, TourStep } from '@/components/guided-tour'

function Onboarding() {
  const handleComplete = () => {
    // Track onboarding completion
    analytics.track('onboarding_completed')
  }

  return (
    <TourProvider
      autoStart={true}
      ranOnce={true}
      onTourComplete={handleComplete}
      storageKey="app-onboarding-v2"
    >
      <div className="dashboard">
        <TourStep
          id="welcome"
          title="Welcome to Dashboard"
          content="This is your personal dashboard where you can track everything."
          order={1}
          position="bottom"
        >
          <div className="dashboard-header">Dashboard</div>
        </TourStep>

        <TourStep
          id="metrics"
          title="Key Metrics"
          content="Monitor your important metrics in real-time."
          order={2}
          position="right"
        >
          <div className="metrics-panel">Metrics</div>
        </TourStep>

        <TourStep
          id="settings"
          title="Customize Settings"
          content="Personalize your experience in settings."
          order={3}
          position="left"
        >
          <button className="settings-btn">Settings</button>
        </TourStep>
      </div>
    </TourProvider>
  )
}
Use the storageKey prop to version your tours. When you update your tour, change the storage key to show it again to users who completed the old version.
The tour automatically scrolls elements into view and positions the popover optimally based on available viewport space.

Build docs developers (and LLMs) love