npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@maskxin/react-spotlight-tour

v0.1.1

Published

A spotlight-based guided tour component for React apps. Headless hook + default Tailwind UI included.

Readme

react-spotlight-tour

A spotlight-based guided tour component for React apps. Highlights target elements with a spotlight overlay and shows step-by-step popover cards.

  • Headless hook (useTour) — bring your own UI
  • Default Tailwind UI (TourOverlay + TourCard) — drop in and go
  • Zero runtime deps — only React as a peer dependency
  • localStorage persistence — remembers when the tour was completed
  • Responsive positioning — auto-adjusts card placement to fit viewport
  • Reveal support — auto-expands collapsed sections before spotlighting

Install

npm install react-spotlight-tour
# or
pnpm add react-spotlight-tour

Peer dependencies: react >= 18 and react-dom >= 18

The default TourCard uses Tailwind CSS classes. If you use the default card, make sure Tailwind scans node_modules/react-spotlight-tour (or add the package to your content config).

Quick Start

import { TourProvider, TourOverlay } from "react-spotlight-tour";
import type { TourStep } from "react-spotlight-tour";

const steps: TourStep[] = [
  {
    id: "welcome",
    title: "Welcome!",
    description: "This is your dashboard. Let's take a quick tour.",
    targetSelectors: ['[data-tour-id="dashboard"]'],
    placement: "center",
  },
  {
    id: "sidebar",
    title: "Navigation",
    description: "Use the sidebar to switch between sections.",
    targetSelectors: ['[data-tour-id="sidebar"]'],
    placement: "right",
    spotlightPadding: 4,
  },
  {
    id: "create-button",
    title: "Create Something",
    description: "Click here to create your first item.",
    targetSelectors: ['[data-tour-id="create-btn"]'],
    placement: "left",
  },
];

function App() {
  return (
    <TourProvider steps={steps} onComplete={() => console.log("Tour done!")}>
      <TourOverlay />
      <YourApp />
    </TourProvider>
  );
}

Then add data-tour-id attributes to the target elements in your app:

<aside data-tour-id="sidebar">...</aside>
<button data-tour-id="create-btn">Create</button>

API Reference

<TourProvider>

Wraps your app and provides tour state via React context.

| Prop | Type | Default | Description | |------|------|---------|-------------| | steps | TourStep[] | required | Ordered list of tour steps | | autoShow | boolean | true | Auto-show on mount if not completed | | storage | TourStorageOptions | — | Customize localStorage key | | onStart | (trigger) => void | — | Called when tour starts | | onStepChange | (index, direction) => void | — | Called on step navigation | | onComplete | () => void | — | Called when user finishes the tour | | onSkip | (stepIndex) => void | — | Called when user skips/closes early |

useTour()

Hook to access tour state and controls. Must be inside <TourProvider>.

const {
  isActive,        // boolean — is the tour showing?
  currentStepIndex,// number — zero-based step index
  currentStep,     // TourStep | undefined
  totalSteps,      // number
  trigger,         // "auto" | "manual" | null
  next,            // () => void
  back,            // () => void
  skip,            // () => void — close & mark completed
  finish,          // () => void — finish on last step
  start,           // (trigger?) => void — restart the tour
} = useTour();

<TourOverlay>

Default spotlight overlay. Renders the backdrop, spotlight ring, and card.

| Prop | Type | Default | Description | |------|------|---------|-------------| | CardComponent | ComponentType<TourCardProps> | TourCard | Custom card component | | backdropZIndex | number | 40 | z-index for the backdrop | | cardZIndex | number | 70 | z-index for the card | | spotlightBorderColor | string | "rgba(59,130,246,0.5)" | Spotlight ring color | | overlayColor | string | "rgba(0,0,0,0.25)" | Overlay backdrop color |

<TourCard>

Default card UI. You can use it standalone or replace it via TourOverlay's CardComponent prop.

TourStep

interface TourStep {
  id: string;
  title: string;
  description: string;
  tip?: string;
  targetSelectors: string[];
  spotlightPadding?: number;    // default: 10
  revealSelectors?: string[];
  placement?: "center" | "right" | "left" | "top";
}

Headless Mode

Use useTour() with your own UI — skip <TourOverlay> entirely:

import { TourProvider, useTour } from "react-spotlight-tour";

function MyCustomTourUI() {
  const { isActive, currentStep, next, back, skip, finish } = useTour();
  if (!isActive || !currentStep) return null;

  return (
    <div className="my-custom-tour-popover">
      <h3>{currentStep.title}</h3>
      <p>{currentStep.description}</p>
      <button onClick={back}>Back</button>
      <button onClick={next}>Next</button>
      <button onClick={skip}>Skip</button>
    </div>
  );
}

function App() {
  return (
    <TourProvider steps={steps}>
      <MyCustomTourUI />
      <YourApp />
    </TourProvider>
  );
}

Custom Card Component

Replace only the card while keeping spotlight positioning:

import { TourOverlay, type TourCardProps } from "react-spotlight-tour";

function MyCard({ step, currentStep, totalSteps, onNext, onBack, onClose, onFinish }: TourCardProps) {
  return (
    <div className="my-card">
      <h3>{step.title}</h3>
      <p>{step.description}</p>
      <span>{currentStep + 1} / {totalSteps}</span>
      <button onClick={onNext}>Next</button>
    </div>
  );
}

// In your app:
<TourOverlay CardComponent={MyCard} />

Programmatic Control

function SettingsPage() {
  const { start } = useTour();

  return (
    <button onClick={() => start("manual")}>
      Replay tour
    </button>
  );
}

Storage

By default, completion is persisted to localStorage under the key "react-spotlight-tour.completed". Customize it:

<TourProvider
  steps={steps}
  storage={{
    storageKey: "my-app.tour.completed.v1",
    legacyKeys: ["old-app.onboarding.done"],
  }}
>

Use clearCompleted() to reset:

import { clearCompleted } from "react-spotlight-tour";
clearCompleted("my-app.tour.completed.v1");

Tailwind Setup

Add the package to your Tailwind content config so the default card styles are included:

// tailwind.config.js
export default {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
    "./node_modules/react-spotlight-tour/dist/**/*.js",
  ],
};

License

MIT