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

@tour-kit/react

v0.12.0

Published

React onboarding & product tour components — accessible, headless, Tailwind & shadcn-ready, with Next.js, React Router, TanStack adapters.

Readme

@tour-kit/react

React onboarding & product tour components — accessible, headless, Tailwind & shadcn-ready, with Next.js, React Router, TanStack Router adapters.

npm version npm downloads bundle size types license

The components layer for React onboarding, product tours, guided walkthroughs, and onboarding wizards. Ships accessible defaults plus headless render-prop variants — works with Tailwind, shadcn/ui, Radix UI, or Base UI, and includes router adapters for Next.js (App + Pages), React Router, and TanStack Router.

Alternative to: React Joyride, Reactour, Intro.js React, Shepherd.js, Userpilot, Appcues, Pendo.

Features

  • React onboarding componentsTour, TourStep, TourCard, TourNavigation, TourProgress, TourOverlay
  • Headless variants with render props — TourCardHeadless, TourNavigationHeadless, etc. for full UI control
  • Accessible by default — focus trap, ARIA live regions, keyboard navigation, prefers-reduced-motion, RTL
  • Next.js App Router-ready — every component starts with 'use client'
  • Router adapters — Next.js (App + Pages), React Router v6/v7, TanStack Router
  • Multi-tour registryMultiTourKitProvider registers many tours, trigger by id with useTours()
  • Lazy entry@tour-kit/react/lazy exports React.lazy() wrappers for code-splitting
  • Tailwind plugin@tour-kit/react/tailwind ships a CVA-aware preset
  • TypeScript-first — strict types, full inference, supports React 18 & 19

Installation

npm install @tour-kit/react
# or
pnpm add @tour-kit/react
# or
yarn add @tour-kit/react

Quick Start

import { Tour, TourStep, TourKitProvider } from '@tour-kit/react'

function App() {
  return (
    <TourKitProvider>
      <Tour id="welcome-tour" autoStart>
        <TourStep
          id="step-1"
          target="#feature-button"
          title="Welcome!"
          content="Let me show you around."
        />
        <TourStep
          id="step-2"
          target="#another-element"
          title="This is great"
          content="Here's another feature."
        />
      </Tour>
    </TourKitProvider>
  )
}

i18n & interpolation

All user-facing strings in @tour-kit/react accept the {{var | fallback}} interpolation grammar from @tour-kit/core. Wrap your tree in <LocaleProvider> and every step title, content, and button label resolves automatically.

import { LocaleProvider } from '@tour-kit/core'
import { Tour, TourStep, TourKitProvider } from '@tour-kit/react'

<LocaleProvider locale="en" messages={{ welcome: 'Hi {{user.name | there}}' }}>
  <TourKitProvider>
    <Tour id="welcome-tour">
      <TourStep id="s1" target="#cta" title={{ key: 'welcome' }} />
    </Tour>
  </TourKitProvider>
</LocaleProvider>

Full guide: https://usertourkit.com/docs/guides/i18n

Why @tour-kit/react?

| | @tour-kit/react | React Joyride | Reactour | Intro.js React | Shepherd.js | |---|---|---|---|---|---| | Headless variants | ✅ | ❌ | ❌ | ❌ | Partial | | TypeScript-native | ✅ | ✅ | ✅ | Partial | ✅ | | Next.js App Router | ✅ ('use client') | Manual | Manual | Manual | Manual | | Multi-page tours | ✅ (built-in adapters) | Manual | Manual | ❌ | Manual | | Branching & skip logic | ✅ | Limited | Limited | ❌ | Limited | | prefers-reduced-motion | ✅ | ❌ | ❌ | ❌ | ❌ | | RTL support | ✅ | ❌ | ❌ | ❌ | ❌ | | Tailwind preset | ✅ | ❌ | ❌ | ❌ | ❌ | | License | MIT | MIT | MIT | MIT | MIT |

Tailwind CSS setup

// tailwind.config.ts
import { tourKitPlugin } from '@tour-kit/react/tailwind'

export default {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    './node_modules/@tour-kit/react/dist/**/*.js',
  ],
  plugins: [tourKitPlugin],
}

@tour-kit/react/tailwind also exports tourKitPreset for Tailwind v4.

Headless components

For full UI control, use the headless render-prop variants from the /headless entry:

import { TourCardHeadless } from '@tour-kit/react/headless'

<TourCardHeadless
  render={({ currentStep, next, prev, floatingStyles }) => (
    <div style={floatingStyles}>
      <h2>{currentStep?.title}</h2>
      <button onClick={prev}>Back</button>
      <button onClick={next}>Next</button>
    </div>
  )}
/>

Available headless components:

  • TourCardHeadless
  • TourNavigationHeadless
  • TourProgressHeadless
  • TourOverlayHeadless
  • TourCloseHeadless

Router adapters

Each framework has a factory (testable, dependency-injected) and a direct hook (convenient):

import { useNextAppRouter, TourProvider } from '@tour-kit/react'

function App() {
  const router = useNextAppRouter()
  return (
    <TourProvider tours={[multiPageTour]} router={router}>
      <YourApp />
    </TourProvider>
  )
}

| Framework | Hook | Factory | |---|---|---| | Next.js App Router | useNextAppRouter() | createNextAppRouterAdapter(usePathname, useRouter) | | Next.js Pages Router | useNextPagesRouter() | createNextPagesRouterAdapter(useRouter) | | React Router v6 / v7 | useReactRouter() | createReactRouterAdapter(useLocation, useNavigate) |

Direct hooks call dynamic require() for the framework — they throw if the framework isn't installed. Factories accept your own router primitives so tests don't need the framework as a dependency.

Lazy / code-split entry

import { Suspense } from 'react'
import { LazyTour, LazyTourStep } from '@tour-kit/react/lazy'

<Suspense fallback={null}>
  <LazyTour id="welcome-tour">
    <LazyTourStep id="step-1" target="#cta" content="Click here" />
  </LazyTour>
</Suspense>

API Reference

Tour components

| Export | Purpose | |---|---| | Tour | Tour wrapper that registers steps declaratively | | TourStep | Single step (target, title, content, placement) | | TourCard, TourCardHeader, TourCardContent, TourCardFooter | Composable step card | | TourNavigation, TourProgress, TourClose | Footer controls | | TourOverlay | Spotlight overlay | | TourPortal, TourArrow | Low-level primitives | | TourRoutePrompt | Multi-page route confirmation prompt | | MultiTourKitProvider | Registers many tours; trigger by id with useTours() |

Variants (CVA)

For styling customization, every component exposes its class-variance-authority config:

import {
  tourButtonVariants,
  tourCardVariants,
  tourCardHeaderVariants,
  tourCardContentVariants,
  tourCardFooterVariants,
  tourProgressVariants,
  tourProgressDotVariants,
  tourOverlayVariants,
} from '@tour-kit/react'

Hooks (own)

| Hook | Description | |---|---| | useTours() | Multi-tour registry consumer | | useTourRoute() | Current route info from the active adapter |

Hooks (re-exported from @tour-kit/core)

useTour, useStep, useSpotlight, useElementPosition, useKeyboardNavigation, useFocusTrap, usePersistence, useRoutePersistence, useMediaQuery, usePrefersReducedMotion, useBranch, useUILibrary.

Utilities (re-exported)

createTour, createStep, waitForElement, isElementVisible, getScrollParent, scrollIntoView, generateId, announce, prefersReducedMotion, getStepAnnouncement, createStorageAdapter, createPrefixedStorage, safeJSONParse, calculatePosition, cn.

Slot & UI library

import {
  Slot, Slottable,            // Radix UI primitives
  UnifiedSlot,                // Reconciles Radix + Base UI render-prop styles
  UILibraryProvider,          // Switch to Base UI
  useUILibrary,
} from '@tour-kit/react'

Types

Re-exported from core. Note the rename: TourStep and Tour components shadow the type names from core, so types come through as TourStepConfig and TourConfig.

import type {
  TourConfig, TourStepConfig, TourState, TourCallbackContext,
  Placement, KeyboardConfig, SpotlightConfig, PersistenceConfig,
  RouterAdapter, MultiPagePersistenceConfig,
  Branch, BranchTarget, UseBranchReturn,
  UseTourReturn, UseStepReturn, UseSpotlightReturn,
  UseFocusTrapReturn, UsePersistenceReturn, UseRoutePersistenceReturn,
} from '@tour-kit/react'

Single import surface

Always import from @tour-kit/react. Do not mix @tour-kit/core and @tour-kit/react imports in the same file — react re-exports nearly the full core surface to keep your imports flat.

Related packages

Documentation

Full documentation: https://usertourkit.com/docs/react

See Troubleshooting for React 19 / Next 16 caveats.

License

MIT © Tour Kit Team