Tour

Utility

Step-by-step product tour overlay.

Preview

Product tour for onboarding. Highlights UI elements with tooltips step by step.

Step 1 of 2

Welcome

Click here to start

Usage

example.jsx
import { Tour } from "@/components/ui/tour";

export default function Example() {
  return <Tour />;
}

Source Code

Copy this file into components/ui/tour.jsx in your project.

tour.jsx
"use client";

import { forwardRef, useState, useEffect } from "react";
import { cn } from "@/lib/utils";

const Tour = forwardRef(({ className, steps = [], onComplete, ...props }, ref) => {
  const [current, setCurrent] = useState(0);
  const step = steps[current];
  if (!step) return null;

  return (
    <div ref={ref} className={cn("fixed inset-0 z-[9999]", className)} {...props}>
      <div className="absolute inset-0 bg-black/50" onClick={onComplete} />
      <div className="absolute left-1/2 top-1/2 w-80 -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-popover p-6 shadow-xl">
        <div className="text-xs text-muted-foreground">Step {current + 1} of {steps.length}</div>
        <h4 className="mt-1 font-semibold">{step.title}</h4>
        <p className="mt-2 text-sm text-muted-foreground">{step.description}</p>
        <div className="mt-4 flex justify-between">
          <button onClick={() => setCurrent(Math.max(0, current - 1))} disabled={current === 0}
            className="rounded-md border px-3 py-1.5 text-sm disabled:opacity-50"
          >Back</button>
          <button onClick={() => current < steps.length - 1 ? setCurrent(current + 1) : onComplete?.()}
            className="rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground"
          >{current === steps.length - 1 ? "Finish" : "Next"}</button>
        </div>
      </div>
    </div>
  );
});
Tour.displayName = "Tour";

export { Tour };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge