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

guidex-react

v0.1.0

Published

Lightweight, zero-dependency onboarding tour component for React. Spotlight overlay, smart positioning, keyboard navigation, and customizable steps.

Readme

guidex-react

Lightweight, zero-dependency onboarding tour component for React.
Spotlight overlay, smart positioning, keyboard navigation, dark mode support, and fully customizable steps.

npm version bundle size license downloads

InstallationQuick StartAPI ReferenceStylingExamples

Why guidex-react?

| | guidex-react | intro.js | react-joyride | |:---|:---:|:---:|:---:| | Zero dependencies | ~4 KB | ~30 KB (7+ deps) | ~45 KB | | React-native support | Hooks + Portal | jQuery-style DOM | Wrapper | | TypeScript | Full | Partial | Full | | Dark mode | Built-in | Manual CSS | No | | localStorage | Built-in hook | Manual | Manual | | License | MIT (free) | AGPL (paid commercial) | MIT |

Installation

npm install guidex-react
yarn add guidex-react
# or
pnpm add guidex-react

Quick Start

import { OnboardingTour, useOnboardingTour } from "guidex-react";
import "guidex-react/styles.css";

const steps = [
  {
    title: "Welcome!",
    content: "Let us show you around.",
  },
  {
    target: "[data-tour='sidebar']",
    title: "Navigation",
    content: "Use the sidebar to navigate between pages.",
    position: "right" as const,
  },
  {
    target: "[data-tour='search']",
    title: "Search",
    content: "Find anything quickly with the search bar.",
    position: "bottom" as const,
  },
  {
    title: "All Done!",
    content: "You're ready to go. Enjoy!",
  },
];

function App() {
  const { active, complete, reset } = useOnboardingTour("my-app-tour");

  return (
    <div>
      <nav data-tour="sidebar">Sidebar</nav>
      <input data-tour="search" placeholder="Search..." />
      <button onClick={reset}>Replay Tour</button>

      <OnboardingTour steps={steps} active={active} onComplete={complete} />
    </div>
  );
}

Step-by-Step Guide

1. Import styles

Add this once at the top level of your app (App.tsx, layout.tsx, or _app.tsx):

import "guidex-react/styles.css";

2. Mark target elements

Add data-tour attributes to elements you want to highlight:

<aside data-tour="sidebar">...</aside>
<header data-tour="header">...</header>
<button data-tour="cta-button">Get Started</button>

You can also use any valid CSS selector: #my-id, .my-class, [aria-label='Search']

3. Define your steps

import type { TourStep } from "guidex-react";

const steps: TourStep[] = [
  // No target = centered floating tooltip (great for welcome/finish)
  { title: "Welcome!", content: "We'll walk you through the main features." },

  // With target = spotlight on element
  {
    target: "[data-tour='sidebar']",
    title: "Sidebar",
    content: "Navigate between pages here.",
    position: "right",
  },

  { title: "You're All Set!", content: "Start exploring." },
];

Position options:

| Position | Tooltip appears... | |:---|:---| | "top" | Above the target | | "bottom" | Below the target (default) | | "left" | Left of the target | | "right" | Right of the target | | (omitted) | Centered on screen |

4. Add the component

function App() {
  const { active, complete, reset } = useOnboardingTour("my-app-tour");

  return (
    <>
      <Layout>
        <MainContent />
      </Layout>

      <OnboardingTour
        steps={steps}
        active={active}
        onComplete={complete}
        startDelay={1000}
      />
    </>
  );
}

The tour shows automatically on first visit and persists completion in localStorage.

Framework Examples

// app/(dashboard)/layout.tsx
"use client";

import { OnboardingTour, useOnboardingTour } from "guidex-react";
import "guidex-react/styles.css";

const steps = [
  { title: "Welcome!", content: "Let's explore your dashboard." },
  { target: "[data-tour='sidebar']", title: "Sidebar", content: "Navigate here.", position: "right" as const },
  { target: "[data-tour='header']", title: "Header", content: "Your controls.", position: "bottom" as const },
  { title: "All Done!", content: "Enjoy the app!" },
];

export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  const { active, complete } = useOnboardingTour("dashboard-tour");

  return (
    <div className="flex">
      <Sidebar />
      <div className="flex-1">
        <Header />
        <main>{children}</main>
      </div>
      <OnboardingTour steps={steps} active={active} onComplete={complete} startDelay={1500} />
    </div>
  );
}
// pages/_app.tsx
import type { AppProps } from "next/app";
import { OnboardingTour, useOnboardingTour } from "guidex-react";
import "guidex-react/styles.css";

const steps = [/* ... your steps ... */];

export default function App({ Component, pageProps }: AppProps) {
  const { active, complete } = useOnboardingTour("app-tour");

  return (
    <>
      <Component {...pageProps} />
      <OnboardingTour steps={steps} active={active} onComplete={complete} />
    </>
  );
}
// src/App.tsx
import { OnboardingTour, useOnboardingTour } from "guidex-react";
import "guidex-react/styles.css";

const steps = [/* ... your steps ... */];

function App() {
  const { active, complete, reset } = useOnboardingTour("vite-app-tour");

  return (
    <div>
      <button onClick={reset}>Replay Tour</button>
      <OnboardingTour steps={steps} active={active} onComplete={complete} />
    </div>
  );
}

API Reference

<OnboardingTour /> Props

| Prop | Type | Default | Description | |:---|:---|:---:|:---| | steps | TourStep[] | required | Array of tour steps | | active | boolean | required | Whether the tour is active | | onComplete | () => void | required | Called when tour finishes or is skipped | | doneLabel | string | "Get Started" | Label for the final step button | | nextLabel | string | "Next" | Label for the next button | | backLabel | string | "Back" | Label for the back button | | overlayOpacity | number | 0.55 | Overlay background opacity (0-1) | | spotlightPadding | number | 6 | Padding around spotlight (px) | | tooltipGap | number | 14 | Gap between target and tooltip (px) | | tooltipMaxWidth | number | 360 | Max tooltip width (px) | | startDelay | number | 0 | Delay before tour starts (ms) | | className | string | - | Custom class for tooltip container | | style | CSSProperties | - | Inline styles for tooltip | | onStepChange | (index: number) => void | - | Callback when step changes |

TourStep

interface TourStep {
  target?: string;                                   // CSS selector
  title: string;                                     // Bold heading
  content: string;                                   // Description text
  position?: "top" | "bottom" | "left" | "right";   // Tooltip placement
}
  • No target = centered floating tooltip (ideal for welcome/finish screens)
  • Target not found in DOM = graceful fallback to centered

useOnboardingTour(storageKey?)

const { active, start, complete, reset } = useOnboardingTour("my-unique-key");

| Return | Type | Description | |:---|:---|:---| | active | boolean | Whether the tour should show | | start | () => void | Manually activate the tour | | complete | () => void | Mark complete, persist to localStorage | | reset | () => void | Clear storage and restart |

Default key: "onboarding_tour_complete". Use unique keys when running multiple tours.

Styling & Customization

Dark Mode

Supported out of the box via three methods:

<!-- CSS class (next-themes, manual toggle) -->
<html class="dark">

<!-- data-theme attribute -->
<html data-theme="dark">

<!-- Automatic via prefers-color-scheme (no config needed) -->

Custom Brand Colors

.rot-btn-next       { background: #10b981; }
.rot-btn-next:hover { background: #059669; }
.rot-progress-bar   { background: #10b981; }
.rot-spotlight      { border-color: rgba(16, 185, 129, 0.5); }

Custom Tooltip Styles

/* Glassmorphism */
.rot-tooltip {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 20px;
}

Or via props:

<OnboardingTour
  className="my-custom-tooltip"
  style={{ borderRadius: 20, fontSize: 16 }}
  ...
/>

| Class | Element | |:---|:---| | .rot-spotlight | Spotlight overlay with cutout | | .rot-tooltip | Tooltip card container | | .rot-close | Close (X) button | | .rot-title | Step title | | .rot-content | Step description text | | .rot-progress-track | Progress bar track | | .rot-progress-bar | Progress bar fill | | .rot-footer | Footer container | | .rot-step-count | "1 of 5" counter text | | .rot-buttons | Button group container | | .rot-btn | Base button style | | .rot-btn-next | Next / Done button | | .rot-btn-prev | Back button |

Advanced Usage

const adminSteps: TourStep[] = [
  { target: "[data-tour='admin-panel']", title: "Admin Panel", content: "Manage users here.", position: "right" },
];

const baseSteps: TourStep[] = [
  { title: "Welcome!", content: "Let's get started." },
  { target: "[data-tour='dashboard']", title: "Dashboard", content: "Your overview.", position: "bottom" },
];

const steps = user.role === "admin" ? [...baseSteps, ...adminSteps] : baseSteps;

Use separate storage keys per page:

// Dashboard page
const { active, complete } = useOnboardingTour("dashboard-tour");

// Settings page
const { active, complete } = useOnboardingTour("settings-tour");
function HelpButton() {
  const { active, start, complete } = useOnboardingTour("help-tour");

  return (
    <>
      <button onClick={start}>Help Tour</button>
      <OnboardingTour steps={steps} active={active} onComplete={complete} />
    </>
  );
}
<OnboardingTour
  steps={steps}
  active={active}
  onComplete={() => {
    analytics.track("tour_completed");
    complete();
  }}
  onStepChange={(index) => {
    analytics.track("tour_step_viewed", { step: index, title: steps[index].title });
  }}
/>

Wait for data to load before starting:

<OnboardingTour steps={steps} active={active} onComplete={complete} startDelay={2000} />

Keyboard Shortcuts

| Key | Action | |:---|:---| | Right Arrow / Enter | Next step | | Left Arrow | Previous step | | Escape | Skip / close tour |

Browser Support

| Browser | Version | |:---|:---| | Chrome | 80+ | | Firefox | 80+ | | Safari | 14+ | | Edge | 80+ |

Requires backdrop-filter support for glassmorphism. Falls back gracefully in older browsers.

Features

  • Zero external dependencies (React peer dep only)
  • Spotlight overlay with smooth transitions
  • Smart tooltip positioning (top, bottom, left, right, auto-centered)
  • Keyboard navigation (Arrow keys, Enter, Escape)
  • Auto-scroll target elements into view
  • Animated progress bar with step counter
  • Dark mode support (.dark, [data-theme="dark"], prefers-color-scheme)
  • localStorage persistence via useOnboardingTour hook
  • Fully typed with TypeScript
  • ~4 KB minified + gzipped
  • Works with Next.js, Vite, CRA, Remix, and any React 17+ project

License

MIT