Spotlight Tour

A guided tour that dims the page and cuts a hole around one element at a time. The hole glides to each next element and takes its shape, with the explanation card riding along beside it.

  • Onboarding
  • Overlay
  • Motion

Uses motion, clsx, tailwind-merge

Open in ChatGPTOpen in Claude

Acme /Projects

Projects

  • StorefrontUpdated 2h agoLive
  • DocsUpdated yesterdayLive
  • Admin dashboardUpdated 3 days agoBuilding
  • BlogUpdated last weekLive

New here? Take a 20-second tour.

Installation

Add the component on its own with the CLI, or copy the file in by hand.

The CLI writes components/ui/spotlight-tour.tsx and installs motion, clsx and tailwind-merge. It needs the @keyframeui registry in components.json; add it once per project.

npx shadcn@latest add @keyframeui/spotlight-tour

Examples

Finished sections built with Spotlight Tour. Each one installs whole, with the component included.

What's New

Three new features spread down a page. Each one scrolls into view while the spotlight travels to it. The Live switch stays usable while it's highlighted.

Pulse

Overview

acme.com · Last 30 days

Visitors

184k

Bounce

38%

Avg. visit

2m 41s

Visitors right now

3,552

Weekly signups

Week 7 was launch week.

Launch day

Front page of Hacker News for 9 hours.

Top referrer

news.ycombinator.com

31% of visits

Top country

United States

42% of visits

Top device

Desktop

68% of visits

Top browser

Chrome

57% of visits

Top pages

/48,210+12%
/pricing18,904+31%
/docs/getting-started12,377+8%
/blog/launch-week9,120+164%
/changelog6,483-3%
/careers2,941+5%

Form Help

A sign-up form that explains each field in turn. You can type into each field while it's highlighted.

Create your workspace

Free for teams of up to 5.

pulse.app/

Props

stepsRequired

TypeSpotlightTourStep[]

The stops on the tour. Each has a title, and optionally a body, a target (a CSS selector, an element or a ref; leave it out for a centered card with no highlight), a side for the card, its own padding and radius, interactive to let people click and type inside the hole, and advanceOnClick to move on when the element is clicked.

openRequired

Typeboolean

Whether the tour is showing.

onOpenChange

Type(open: boolean) => void

Called with false when the tour is skipped, closed with Esc or finished.

step

Typenumber

The current step, to control it yourself. Otherwise the tour starts at the first step each time it opens.

onStepChange

Type(step: number) => void

Called when the step changes. Use it to get the page ready, such as opening a menu before highlighting something inside it. The tour waits for the element to appear.

onComplete

Type() => void

Called when Done is pressed on the last step, not when the tour is skipped.

padding

TypenumberDefault8

Room between each element and the edge of its hole, in pixels. A step's own padding wins.

className

Typestring

Extra classes for the card.

overlayClassName

Typestring

Extra classes for the dimmed layer, such as its color. Defaults to bg-black/50 dark:bg-black/65.