react-product-tour-highlight
v3.0.3
Published
React Product Tour Highlight: spotlight-based React onboarding flows and walkthroughs with tooltips and step navigation.
Maintainers
Readme
React Product Tour Highlight
Add onboarding tours in 2 minutes.
Drop a react product tour into your app — spotlight highlights, tooltips, and step navigation for react onboarding, react guided tour, and react walkthrough flows. No heavy deps. No config rabbit holes.
npm install react-product-tour-highlightDemo

Why this library?
- ⚡ Lightweight — no heavy deps, ships lean
- 🎯 Clean spotlight effect — smooth highlights that draw the eye
- 🧩 Simple API — pass
steps, toggleisOpen, you're done - 🎨 Beautiful by default — light/dark themes, progress bar, polished tooltips
Key Features
- Spotlight highlight with soft glow and smooth step transitions
- Premium tooltip UI with progress bar, dots, or step counter
- Light / dark themes with partial token overrides
- Next / Back / Skip navigation with customizable labels (i18n-friendly)
- Optional
localStoragepersistence so tours don't repeat - Auto-scroll to bring targets into view
- React 18+ and TypeScript
- Accessible defaults (ESC to close, focus trap, keyboard navigation)
Quick Start
Point at any element. Open the tour. Ship.
import React, { useState } from "react";
import { ProductTour, type Step } from "react-product-tour-highlight";
export function Example() {
const [isOpen, setIsOpen] = useState(true);
const steps: Step[] = [
{
target: "#pricing",
title: "See pricing",
description: "This step highlights the pricing section.",
placement: "bottom",
},
{
target: "#start",
title: "Get started",
description: "Next, we guide you to the primary CTA.",
placement: "top",
},
];
return (
<>
<ProductTour
steps={steps}
isOpen={isOpen}
theme="light"
progress="bar"
storageKey="my-app-onboarding"
onClose={() => setIsOpen(false)}
onComplete={() => setIsOpen(false)}
/>
<div id="pricing" style={{ marginTop: 120 }}>
Pricing
</div>
<button id="start">Start</button>
</>
);
}Theming
Use a preset or override individual tokens:
<ProductTour
steps={steps}
isOpen={isOpen}
theme="dark"
// or partial overrides:
// theme={{ accentColor: "#e11d48", primaryBg: "#e11d48" }}
/>Export lightTheme, darkTheme, and resolveTheme() if you need the full token set.
Persistence
Skip re-showing a completed tour:
import { isTourCompleted, clearTourCompleted } from "react-product-tour-highlight";
if (!isTourCompleted("my-app-onboarding")) {
setIsOpen(true);
}
// Reset for testing:
clearTourCompleted("my-app-onboarding");Pass storageKey on ProductTour to persist completion when the user finishes or skips.
Steps
Each step points to a DOM node using either:
- A CSS selector string (e.g.
"#pricing"), or - A direct
HTMLElementreference
export type Step = {
target: string | HTMLElement;
title: string;
description?: string;
content?: React.ReactNode;
placement?: "top" | "bottom" | "left" | "right";
offset?: number;
spotlightPadding?: number;
spotlightRadius?: number;
};Custom step body:
<ProductTour
renderStepContent={(step) => step.content ?? step.description}
// ...
/>Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| steps | Step[] | required | Tour steps |
| isOpen | boolean | — | Controlled open state |
| defaultIsOpen | boolean | false | Uncontrolled initial open |
| initialStep | number | 0 | Starting step index |
| theme | "light" \| "dark" \| Partial<TourTheme> | "light" | Visual theme |
| progress | "bar" \| "dots" \| "fraction" | "bar" | Progress indicator style |
| labels | Partial<TourLabels> | — | Button labels (i18n) |
| storageKey | string | — | localStorage persistence key |
| spotlightPadding | number | theme default | Padding around highlight |
| spotlightRadius | number | theme default | Corner radius of highlight |
| overlayOpacity | number | theme default | Backdrop dim strength |
| spotlightPulse | boolean | true | Subtle pulse on spotlight |
| enableAutoScroll | boolean | true | Scroll target into view |
| allowBackdropClickToClose | boolean | true | Click outside to close |
| onClose | () => void | — | Called on skip/close |
| onComplete | () => void | — | Called on final step |
| onStepChange | (index: number) => void | — | Called when step changes |
| renderStepContent | (step, ctx) => ReactNode | — | Custom step body |
Also exported: useTour, isTourCompleted, markTourCompleted, clearTourCompleted.
Accessibility
- Uses a
dialogrole when open - ESC closes the tour
- Enter advances (when focus is not on an interactive element)
- Focus trap within the tooltip
Notes
- If a step target cannot be found, the library warns in the console and skips positioning for that step.
- Ensure target elements exist in the DOM when the tour opens.
License
MIT
