Tour Spotlight

Setlist
Search songs and venues
Hounds of Love3:02
Running Up That Hill4:58
Cloudbusting5:10
Wuthering Heights4:28
Kate Bush, Hammersmith Odeon, 12 songs
About this component

Tour Spotlight

Onboarding coach marks: the page dims around a rounded cutout that frames each step's target, the cutout glides to the next target on a spring and the target scrolls into view, while a step card sits beside it and flips to whichever side has room. Back, next, skip and finish buttons, progress dots you can jump with, arrow keys and Escape, focus held in the card and handed back afterwards. Targets are CSS selectors or refs and are tracked through scrolling and resizing; the tour can dim the whole viewport or only its own box, let clicks through to the target, and be controlled or left to itself.

Usage

The import and the props worth knowing about, in one place.

import { TourSpotlight } from "@/components/beste/component/tour-spotlight";

const steps = [
  { target: "#search", title: "Find anything", body: "Search songs, venues and setlists.", side: "bottom" },
  { target: "#new-setlist", title: "Start a new one", body: "Copied from your last show.", side: "left" },
];

// Over the whole viewport, opened from your own state
<TourSpotlight steps={steps} open={open} onOpenChange={setOpen} onFinish={() => console.log("Tour finished")} />

// Inside a panel: selectors are searched in the children and only this box is dimmed
<TourSpotlight steps={steps} contained defaultOpen launcherLabel="Replay the tour">
  <Dashboard />
</TourSpotlight>

<TourSpotlight
  steps={steps}
  allowTargetClick          // clicks pass through the cutout
  closeOnOverlayClick       // clicking the dimmed area skips
  dim={0.4}
  labels={{ next: "Continue", finish: "Got it" }}
/>

Keyboard and gestures

Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.

Arrow right / Arrow leftNext or previous step.
EscapeSkip the tour.
TabMove between the card's buttons. Focus stays in the card until the tour closes.
Click a dotJump straight to that step.

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
steps*TourStep[]—
openboolean—Whether the tour is showing. Pair with `onOpenChange` to control it.
defaultOpenboolean—
onOpenChange(open: boolean) => void—
openDelaynumber—Milliseconds to wait before a tour that is open on load first shows, so the page can settle. @defaultValue 3000
stepnumber—The current step, zero based. Pair with `onStepChange` to control it.
defaultStepnumber—
onStepChange(step: number) => void—
onFinish() => void—Fired when the reader presses the last step's finish button.
onSkip() => void—Fired when the reader skips, presses Escape or clicks the dimmed area (with `closeOnOverlayClick`).
containedboolean—Dim only this component's own box instead of the whole viewport, for tours inside a panel or preview.
allowTargetClickboolean—Let clicks through the cutout to the highlighted element.
closeOnOverlayClickboolean—Clicking the dimmed area skips the tour.
ringboolean—A soft ring pulses around the cutout.
dimnumber—How dark the dimmed area is, 0 to 1.
launcherLabelstring—When set, a button with this label starts the tour again while it is closed.
labelsTourSpotlightLabels—
tone"muted" | "outline" | "ghost"—
size"sm" | "default" | "lg"—
classNamestring—
childrenReact.ReactNode—The interface being toured. Selectors in `steps` are searched here when `contained`.