Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Overlays

Tour

Overlays

Tour React component for Tailwind CSS v4

TooltipAlert
Live props
State
defaultOpen
defaultStep0
Behavior
persistKey
autoStart
shortcut
closeOnOverlayClick
scrollBehavior
Appearance
spotlight
overlayOpacity0.55
spotlightPadding8px
spotlightRadius14px
showProgress
size
radius
tone
color
Content
showSkip
showClose
keyHints
Layout
mobileLayout
docked
Code
import { Tour } from "@/components/ui/tour"

<Tour />
  1. Home
  2. Components
  3. Overlays
  4. Tour
Pro

Tour React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React product tour that dims the page around the real UI, explains each step in a card, docks at the bottom on phones and adds hotspots.

Start the tour with its button or the shortcut and the page dims around the first target: a rounded spotlight hugs the element and a card beside it explains the step. Next, Back and Skip sit in the card; the progress dots can be clicked to jump. Each step scrolls its target into view first, then the spotlight glides there on a spring and the card fades in beside it; steps without a target show a centered card. Keys: Right arrow or Enter goes next, Left goes back, Escape skips (announced), Tab stays inside the card, and focus returns to where it was when the tour ends. Interactive steps let clicks and typing reach the highlighted element, and advanceOn click moves on when you press the real button. On a phone the card docks at the bottom above the safe area and the keyboard, its target is scrolled into the top half, and a swipe left or right pages the steps. With persistKey a finished or skipped tour is remembered and autoStart leaves it alone. TourHotspot is a pulsing dot on a new feature: tap or click it for a hint (a bottom card on phones); once seen it stays away. Reduced motion makes the spotlight jump and the cards fade.

Tour is a Pro React component in the React overlay components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add tour, together with Button, Kbd, Progress, useControllableState, useKeyboardInset and 7 more and the npm packages @radix-ui/react-popover, motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add tour

Tour is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import Tour from @/components/ui/tour.

import { useRef } from "react"
import { Button } from "@/components/ui/button"
import { Tour, type TourStep } from "@/components/ui/tour"

export function ClientsTour() {
  const search = useRef<HTMLInputElement>(null)
  const invoice = useRef<HTMLButtonElement>(null)
  const steps: TourStep[] = [
    { id: "welcome", title: "Welcome to Northwind CRM", content: "We show you where everything is in 30 seconds." },
    { id: "search", target: search, title: "Find any client", content: "A name, an EIN or a city." },
    { id: "invoice", target: invoice, title: "Issue an invoice", content: "Press New invoice.", advanceOn: "click" },
  ]
  return (
    <Tour
      steps={steps}
      persistKey="northwind-crm:tour"
      autoStart
      shortcut="shift+h"
      labels={{ next: "Continue" }}
    >
      <input ref={search} placeholder="Search clients" />
      <Button ref={invoice}>New invoice</Button>
    </Tour>
  )
}

Props

  • steps*
    TourStep[]

    The steps: { id, target? (selector, function or ref), title, content?, media?, side? (top / right / bottom / left / auto), align?, spotlightPadding?, spotlightRadius?, interactive?, advanceOn?: "click", beforeEnter?, nextLabel? }. A step without a target, or whose target is not found within 1s, shows a centered card.

  • defaultOpendefault false
    boolean

    Starts open. Use open / onOpenChange to control it, or start() from useTour / setApi.

  • open
    boolean

    Controlled open state. Only one tour shows at a time; a second one waits for the first to close.

  • onOpenChange
    (open: boolean) => void

    Called when the tour opens or closes.

  • defaultStepdefault 0
    number

    The step index it starts at.

  • step
    number

    Controlled step index.

  • onStepChange
    (step: number) => void

    Called with the new index on Next, Back, a dot, a swipe or goTo.

  • onComplete
    () => void

    Called when the last step's Done is pressed (or finish()).

  • onSkip
    () => void

    Called on Skip, the close button, Escape, an overlay click with closeOnOverlayClick, or skip().

  • persistKeydefault ""
    string

    Local storage key that remembers the tour was completed or skipped. autoStart does not start a finished tour; start() still does, and reset() forgets it.

  • autoStartdefault false
    boolean

    Opens once after hydration and a 600ms settle, unless persistKey says it was already finished.

  • shortcutdefault ""
    string

    A global key that starts the tour, in mod+k notation. Empty binds nothing; the demo passes "shift+h" (the showcase owns ?).

  • spotlightdefault true
    boolean

    Dims the page with a rounded cutout around the target and blocks clicks elsewhere. false shows only the cards, with an arrow (a ring alone marks the target when the card is docked), and leaves the page usable (coachmarks).

  • overlayOpacitydefault 0.55
    number

    Strength of the dim. Dark mode adds 0.1 so the page still recedes behind the card.

  • spotlightPaddingdefault 8
    number

    Room in px between the target and the edge of the cutout. Steps can override it.

  • spotlightRadiusdefault 14
    number

    Corner radius of the cutout in px, capped at half the smaller side. Steps can override it.

  • showProgressdefault "dots"
    "dots" | "fraction" | "bar" | "none"

    How the card shows where you are: dots (clickable), 2 / 5, a thin bar, or nothing (screen readers still hear it).

  • sizedefault "md"
    "sm" | "md"

    Card width 288 / 340px (never wider than the screen minus 24px), with matching padding and type.

  • radiusdefault "lg"
    "none" | "sm" | "md" | "lg" | "full"

    Card corners: 0, 12, 16 or 24px; full falls back to lg. The docked phone card keeps its 28px sheet top.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Color of the Next button and the progress.

  • colordefault ""
    string

    Any CSS color for the Next button and the progress; replaces the tone.

  • showSkipdefault true
    boolean

    A Skip button in the card on every step but the last.

  • showClosedefault true
    boolean

    The × in the card's corner (on phones it shows only when Skip is hidden). It skips the tour.

  • keyHintsdefault true
    boolean

    Shows the → key on the Next button on desktops. Hidden on touch screens.

  • closeOnOverlayClickdefault false
    boolean

    A click on the dimmed area skips the tour. Off by default so a stray tap does not end it.

  • scrollBehaviordefault "smooth"
    "smooth" | "instant"

    How targets scroll into view (instant under reduced motion). Nested scrollers scroll too.

  • mobileLayoutdefault "docked"
    "docked" | "popover"

    Below 768px the card docks at the bottom where the thumb is, with a 44px Next and swipe paging, and targets scroll into the top half. popover keeps the desktop card.

  • dockeddefault false
    boolean

    Docks the card at every width, e.g. inside a phone mockup.

  • container
    Element | null

    Where the overlay renders (default document.body). A transformed element becomes the frame: the dim, the spotlight and the docked card stay inside it.

  • setApi
    (api: TourApi) => void

    Receives { start(stepId?), next(), previous(), goTo(index | id), skip(), finish(), reset() } once mounted.

  • labels
    Partial<TourLabels>

    Every string: next "Next", back "Back", skip "Skip tour", done "Done", close "Close tour", progress(i, n) "Step i of n", stepAnnounce(i, n, title), skipped "Tour closed", completed "Tour completed". DEFAULT_TOUR_LABELS has the English set.

  • classNames
    Partial<Record<"overlay" | "spotlight" | "card" | "media" | "title" | "content" | "progress" | "actions" | "close" | "handle", string>>

    Extra classes for the inner parts.

  • children
    ReactNode

    Rendered in place; anything inside can read the tour with useTour().

Parts

  • TourHotspot

    component

    A pulsing dot on a corner of its children (or of target) that opens a hint: title, content, placement ("top-end" | "top-start" | "bottom-end" | "bottom-start"), offset, side, align, persistKey (gone once seen), tone, color, pulse, open / defaultOpen / onOpenChange, onDismiss, responsive (a bottom card below 768px), labels { open, dismiss "Got it" }, classNames. Props: TourHotspotProps.

  • useTour

    hook

    The nearest tour's API plus { open, step, count, status }; null outside a Tour. Signature: () => TourState | null.

  • DEFAULT_TOUR_LABELS

    constant

    The English card strings: next, back, skip "Skip tour", done, close, progress and the screen reader announcements. Override keys through labels.

  • DEFAULT_TOUR_HOTSPOT_LABELS

    constant

    The hotspot strings: open "Show tip" (the dot's accessible name) and dismiss "Got it". Override them through TourHotspot labels.

  • TourStep

    type

    One step: id, target (selector, function or ref), title, content, media, side, align, interactive, advanceOn, beforeEnter and nextLabel.

  • TourApi

    type

    The controls setApi hands you: start(stepId?), next, previous, goTo(index or id), skip, finish and reset.

  • TourHotspotProps

    type

    The props of TourHotspot, for wrappers that render hints from your own data.

Examples

Progress bar, small card

showProgress="bar" with size="sm": 288px cards for short, three-step tours.

Coachmarks without dimming

spotlight={false}: no overlay, the page stays usable and each card points at its target with an arrow.

Hotspot

TourHotspot pulses on a new feature; opened once, persistKey keeps it away. Tap it on a phone for a bottom card.

Interactive step

interactive: the search takes the caret and typing reaches the page while the tour waits.

Phone frame, docked and swipeable

docked inside a phone mockup (container): the card sits at the bottom, swipe it left or right to page.

beforeEnter opens a menu

The second step opens the Actions menu before it highlights Export to Excel; the third closes it again.

Dependencies

@radix-ui/react-popovermotionlucide-reactbuttonkbdprogressuse-controllable-stateuse-keyboard-insetuse-media-queryuse-persisted-stateuse-shortcuthapticsmotiontonesui-config

Files

  • components/ui/tour.tsx

FAQ

Is the React Tour component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Tour?

Run npx wingo-ui@latest add tour. It also adds the Wingo UI items it builds on (Button, Kbd, Progress, useControllableState, useKeyboardInset and 7 more) and the npm packages @radix-ui/react-popover, motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/tour.

How does Tour behave on phones?

On a phone the card docks at the bottom above the safe area and the keyboard, its target is scrolled into the top half, and a swipe left or right pages the steps. TourHotspot is a pulsing dot on a new feature: tap or click it for a hint (a bottom card on phones); once seen it stays away.

See also

PopoverOnboarding CarouselShortcuts Dialog

More React overlay components

TooltipDropdown MenuAlert DialogContext MenuDialogDrawer
All 13 React overlay components

Articles using this component

  • Onboarding Checklist UI: The Get Started Card in React

    Build it: screens and apps · Nov 6, 2026 · 9 min read

  • React Product Tour: Spotlight, Phone Dock, Hotspots

    Component guides · Oct 19, 2026 · 9 min read

PreviousTooltipNext Alert

Welcome tour

Not started

NNorthwind CRM
DashboardClientsInvoicesReportsNew

Emma Carter

Administrator

Clients

Northwind Labs · today, 4:40 PM

TI

Tech Solutions Inc.

12-3456740 · New York

$12,480Active
KB

Keystone Builders

56-7812330 · Denver

$103,400Active
GP

Greenleaf Pharmacy

45-6781280 · Portland

$7,315.20Overdue
DC

Dental Art Clinic

78-1234500 · Miami

$5,600Active

dim 0.55 · pad 8 · r 14 · progress dots · md / lg · neutral · phones docked · scroll smooth