A modern, accessible, and performant React tour/onboarding library. A better alternative to react-joyride with zero legacy peer dependency issues.
- π Zero Legacy Dependencies - No
--forceor--legacy-peer-depsneeded - π― TypeScript First - Full TypeScript support with comprehensive types
- βΏ Accessible - Built with ARIA labels and keyboard navigation
- π¨ Highly Customizable - Customize colors, styles, labels, and behavior
- π± Responsive - Works seamlessly on all screen sizes
- β‘ Performant - Optimized with React hooks and efficient re-renders
- π Flexible - Support for CSS selectors or React refs
- β¨οΈ Keyboard Navigation - Arrow keys and Escape support
- πͺ Auto Positioning - Smart tooltip placement with auto-detection
- π¬ Smooth Animations - Polished transitions and effects
- π Production Ready - Battle-tested and ready for enterprise use
npm install @bilalmohib7896/react-tour-guide
# or
yarn add @bilalmohib7896/react-tour-guide
# or
pnpm add @bilalmohib7896/react-tour-guideimport { Tour } from "@bilalmohib7896/react-tour-guide";
import "@bilalmohib7896/react-tour-guide/styles.css"; // Optional: import default styles
function App() {
const [run, setRun] = useState(false);
const steps = [
{
target: "#my-button",
content: <div>This is the first step!</div>,
placement: "bottom",
},
{
target: "#my-input",
content: <div>This is the second step!</div>,
placement: "right",
},
];
return (
<>
<button onClick={() => setRun(true)}>Start Tour</button>
<Tour
steps={steps}
run={run}
callback={(data) => {
if (data.status === "finished" || data.status === "skipped") {
setRun(false);
}
}}
/>
</>
);
}import { Tour } from "@bilalmohib7896/react-tour-guide";
const steps = [
{
target: ".feature-1",
content: <h3>Welcome to Feature 1</h3>,
placement: "bottom",
},
{
target: ".feature-2",
content: <h3>This is Feature 2</h3>,
placement: "right",
},
];
function MyComponent() {
const [isRunning, setIsRunning] = useState(false);
return (
<>
<button onClick={() => setIsRunning(true)}>Start Tour</button>
<Tour
steps={steps}
run={isRunning}
callback={(data) => {
if (data.status === "finished" || data.status === "skipped") {
setIsRunning(false);
}
}}
/>
</>
);
}import { useRef } from "react";
import { Tour } from "@bilalmohib7896/react-tour-guide";
function MyComponent() {
const buttonRef = useRef<HTMLButtonElement>(null);
const [run, setRun] = useState(false);
const steps = [
{
target: buttonRef,
content: <div>This button does something special!</div>,
},
];
return (
<>
<button ref={buttonRef}>Click me</button>
<Tour steps={steps} run={run} />
</>
);
}<Tour
steps={steps}
run={run}
primaryColor="#FF6B6B"
overlayOpacity={0.7}
showProgress={true}
showSkipButton={true}
showBackButton={true}
labels={{
next: "Continue",
back: "Previous",
skip: "Skip Tour",
finish: "Complete",
}}
className={{
tooltip: "custom-tooltip-class",
overlay: "custom-overlay-class",
}}
keyboardNavigation={true}
disableBodyScroll={false}
/>const steps = [
{
target: "#element-1",
content: <div>Step 1</div>,
placement: "auto", // Auto-detect best position
disableSpotlight: false,
disableScroll: false,
offset: {
top: 10,
left: 20,
},
},
{
target: "#element-2",
content: <div>Step 2</div>,
placement: "center", // Center in viewport
disableSpotlight: true, // No highlight
},
];<Tour
steps={steps}
run={run}
callback={(data) => {
switch (data.type) {
case "tour:start":
console.log("Tour started");
break;
case "tour:end":
console.log(`Tour ${data.status}`);
break;
case "step:after":
console.log(`Moved to step ${data.index}`);
break;
case "target:notfound":
console.warn(`Target not found for step ${data.index}`);
break;
}
}}
/>import "@tour-guide/react/styles";The component uses semantic class names that you can override:
.tour-overlay- Overlay backdrop.tour-tooltip- Tooltip container.tour-progress- Progress indicator.tour-content- Step content.tour-actions- Action buttons container.tour-button-primary- Primary button (Next/Finish).tour-button-back- Back button.tour-button-skip- Skip button
.tour-tooltip {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 12px;
}
.tour-button-primary {
background: white;
color: #667eea;
}| Prop | Type | Default | Description |
|---|---|---|---|
steps |
TourStep[] |
required | Array of tour steps |
run |
boolean |
false |
Whether the tour is running |
stepIndex |
number |
0 |
Initial step index |
continuous |
boolean |
true |
Auto-proceed to next step |
showProgress |
boolean |
true |
Show progress indicator |
showSkipButton |
boolean |
true |
Show skip button |
showBackButton |
boolean |
true |
Show back button |
callback |
(data: TourCallbackProps) => void |
- | Callback for tour events |
primaryColor |
string |
"#0F6CBD" |
Primary color for buttons/highlights |
zIndex |
number |
10000 |
Z-index for overlay and tooltip |
overlayOpacity |
number |
0.5 |
Overlay opacity (0-1) |
disableOverlayClose |
boolean |
false |
Disable closing on overlay click |
className |
object |
- | Custom class names |
labels |
object |
- | Custom button labels |
keyboardNavigation |
boolean |
true |
Enable keyboard navigation |
scrollPadding |
number |
20 |
Scroll padding when scrolling to target |
disableBodyScroll |
boolean |
false |
Disable body scroll when tour is active |
spotlightPadding |
number |
8 |
Spotlight padding around element |
spotlightBorderRadius |
number |
8 |
Spotlight border radius |
| Property | Type | Default | Description |
|---|---|---|---|
target |
string | RefObject<HTMLElement> |
required | CSS selector or React ref |
content |
ReactNode |
required | Step content |
placement |
Placement |
"bottom" |
Tooltip placement |
disableSpotlight |
boolean |
false |
Disable spotlight for this step |
disableScroll |
boolean |
false |
Disable scrolling to target |
offset |
{ top?: number; left?: number } |
- | Custom tooltip offset |
data |
Record<string, string> |
- | Custom data attributes |
type Placement = "top" | "bottom" | "left" | "right" | "center" | "auto";interface TourCallbackProps {
status: "idle" | "running" | "paused" | "finished" | "skipped";
type: "tour:start" | "tour:end" | "step:before" | "step:after" | "target:notfound";
index?: number;
step?: TourStep;
}| Feature | @bilalmohib7896/react-tour-guide | react-joyride |
|---|---|---|
| Modern Dependencies | β Yes | β Requires --legacy-peer-deps |
| TypeScript Support | β Full | |
| React 18+ Support | β Yes | |
| Bundle Size | β Smaller | |
| Accessibility | β Built-in | |
| Customization | β Extensive | |
| Performance | β Optimized | |
| Maintenance | β Active |
Contributions are welcome! Please feel free to submit a Pull Request.
MIT Β© bilalmohib
Built with β€οΈ for the React community. Inspired by the need for a modern, dependency-free tour library.