Skip to main content

Is there a product tour library that works with Vue and React?

Compare cross-framework product tour libraries for Vue and React. Bundle sizes, accessibility, and DX tradeoffs for Shepherd.js, Driver.js, and alternatives.

DomiDex
DomiDexCreator of Tour Kit
April 11, 20268 min read
Share
Is there a product tour library that works with Vue and React?

Is there a product tour library that works with Vue and React?

If you run Vue on one product and React on another (or both in the same codebase), the standard advice is "pick Shepherd.js." That advice isn't wrong, but it skips the part where Shepherd's React and Vue wrappers are thin convenience layers over a vanilla JS core. You get cross-framework coverage, but you lose the idiomatic hooks and composability that made you choose Vue or React in the first place.

The real question isn't "does a cross-framework tour library exist?" It does. Several do. The question is whether the developer experience survives the abstraction.

npm install @tourkit/core @tourkit/react

We tested the major options in a Vite 6 + React 19 and a Nuxt 3 + Vue 3 project. Here's what we found.

Short answer

As of April 2026, three product tour libraries work across both Vue and React: Shepherd.js (13.7K GitHub stars, 656 kB unpacked), Driver.js (25.5K stars, 83 kB unpacked), and Intro.js (23.8K stars, 874 kB unpacked, AGPL-licensed). All three are vanilla JavaScript cores with framework wrappers. None provides first-class Vue 3 Composition API hooks or first-class React hooks from a shared engine. For React-only teams, Tour Kit ships at under 8 kB gzipped with native hooks and WCAG 2.1 AA accessibility. A @tour-kit/vue package is on the roadmap.

How cross-framework tour libraries actually work

Every library claiming "works with Vue and React" follows the same pattern: a vanilla JavaScript engine that manipulates the DOM directly, wrapped in thin framework adapters. The core calculates positions, draws overlays, manages step state. A Vue component wraps it for Vue projects. A React component wraps it for React projects.

This matters because wrapper quality varies wildly. Shepherd.js has official wrappers for React, Vue, Angular, even Ember. But the React wrapper is a class-based component that hasn't been rewritten for hooks. The Vue wrapper targets Vue 2 and Vue 3 but doesn't use the Composition API internally. You end up calling imperative methods on a ref instead of using reactive state.

Driver.js skips the wrapper question entirely. Pure vanilla JS. You call driver.highlight() and driver.drive() from inside a useEffect or onMounted. Honest, at least. You know what you're getting.

"Most teams severely underestimate the work involved: handling async DOM updates, keyboard navigation, accessibility, responsive behavior on mobile, animations, and tour state management," notes Chameleon's Vue product tours guide. The wrapper approach pushes all of that complexity onto you.

Detailed comparison

FeatureShepherd.jsDriver.jsIntro.jsTour Kit
React supportOfficial wrapperVanilla JS (manual)Community wrapperNative hooks
Vue supportOfficial wrapperVanilla JS (manual)Community wrapperRoadmap
Bundle size (unpacked)656 kB83 kB874 kBCore: ~20 kB, React: ~30 kB
Bundle size (gzipped)~25 kB~5 kB~30 kBCore: <8 kB, React: <12 kB
TypeScriptYesYes (built in TS)Types availableYes (strict mode)
LicenseMITMITAGPL-3.0 / CommercialMIT (core) / Commercial (extended)
WCAG 2.1 AAPartial (built-in keyboard nav)No explicit complianceNo explicit complianceYes (focus trap, ARIA, reduced motion)
React 19 compatibleWrapper untestedYes (no React dependency)Wrapper untestedYes
Analytics built-inNoNoNoYes (@tourkit/analytics)
ChecklistsNoNoNoYes (@tourkit/checklists)
Last npm publish~17 days ago~4 months ago~9 months agoPre-release
GitHub stars13,71625,53823,850New
Best forMulti-framework teams needing one libraryLightweight spotlights and guided toursQuick prototyping (check AGPL first)React teams wanting headless composability

Data sourced from npm, GitHub, and bundlephobia as of April 2026.

What about Vue-only options?

Vue Tour (pulsardev) was the go-to Vue tour library for years. It hit 2,443 GitHub stars and ~20K weekly npm downloads. But its last publish was over five years ago. It doesn't support Vue 3's Composition API natively, and there's no TypeScript support.

VueJS Tour by GlobalHive targets Vue 3 with Composition API support, but adoption is limited. v-onboarding is lightweight and Composition API-ready, though it lacks accessibility features or analytics.

The Vue tour ecosystem has a maintenance problem. "As soon as you feel the tipping point — multiple tours, multiple teams, governance questions — it's worth considering a product-led platform instead of a library," Chameleon notes. That's fair advice if you're scaling. But for teams that want to own their onboarding code, the pickings are thin.

The wrapper tradeoff you should understand

Here's the pattern with framework-agnostic libraries. You install Shepherd.js in a React project:

// src/components/TourButton.tsx
import { useEffect, useRef } from 'react';
import Shepherd from 'shepherd.js';

export function TourButton() {
  const tourRef = useRef<Shepherd.Tour | null>(null);

  useEffect(() => {
    const tour = new Shepherd.Tour({
      defaultStepOptions: {
        cancelIcon: { enabled: true },
        classes: 'shepherd-theme-arrows',
      },
    });

    tour.addStep({
      id: 'welcome',
      text: 'Welcome to the dashboard.',
      attachTo: { element: '#dashboard-header', on: 'bottom' },
      buttons: [{ text: 'Next', action: tour.next }],
    });

    tourRef.current = tour;
    return () => tour.cancel();
  }, []);

  return <button onClick={() => tourRef.current?.start()}>Start tour</button>;
}

You're managing tour state imperatively through refs. No reactive step tracking. No access to current step index through React state. No composition with other hooks. You're writing the glue code that a native library would give you for free.

Compare that with a React-native approach:

// src/components/ProductTour.tsx
import { TourProvider, useTour } from '@tourkit/react';

const steps = [
  { id: 'welcome', target: '#dashboard-header', content: 'Welcome to the dashboard.' },
  { id: 'sidebar', target: '#sidebar-nav', content: 'Navigate between sections here.' },
];

function TourControls() {
  const { currentStep, totalSteps, next, back, isActive } = useTour();

  if (!isActive) return null;

  return (
    <div role="dialog" aria-label={`Tour step ${currentStep + 1} of ${totalSteps}`}>
      <p>{steps[currentStep].content}</p>
      <button onClick={back} disabled={currentStep === 0}>Back</button>
      <button onClick={next}>{currentStep === totalSteps - 1 ? 'Finish' : 'Next'}</button>
    </div>
  );
}

export function ProductTour() {
  return (
    <TourProvider steps={steps}>
      <TourControls />
    </TourProvider>
  );
}

Reactive state. Composable. Accessible by default. But React-only. That's the tradeoff.

Decision framework: which library fits your stack?

If your entire frontend is Vue 3: Use v-onboarding for simple tours or VueJS Tour for Composition API support. Accept that neither has accessibility compliance or analytics. Budget time for manual keyboard navigation and ARIA attributes.

If your entire frontend is React 18+: Use Tour Kit for headless composability with built-in accessibility, or React Joyride (~400K weekly downloads) if you want opinionated styling out of the box. Tour Kit gives you more control; Joyride gives you faster setup. Both support React 19.

If you need one library across Vue and React: Use Shepherd.js. It has the widest framework support, active maintenance (last publish ~17 days ago as of April 2026), and built-in keyboard navigation. Accept the 656 kB unpacked size and imperative wrapper DX. For lighter needs, Driver.js at 83 kB covers tours and spotlights without the weight.

If you're migrating from Vue to React (or vice versa): Start with a framework-agnostic library (Shepherd.js or Driver.js) during the migration. Once you've settled on a single framework, evaluate framework-native options for better DX.

If accessibility is a hard requirement: Tour Kit is the only library making explicit WCAG 2.1 AA compliance claims with focus trapping, ARIA landmarks, keyboard navigation, and prefers-reduced-motion support. Shepherd.js has partial keyboard navigation built in. Everything else requires manual implementation.

"A React team should not force a framework-agnostic library if the wrapper quality is poor, and a vanilla JS team should not drag in React-only assumptions," Userorbit's comparison points out. Match the library to the stack, not the other way around.

What about web components?

CSS anchor positioning is worth watching. CSS-Tricks documented a <hand-hold> web component that uses native CSS anchor-name and position-area properties to position tour tooltips without any JavaScript position calculations. It works in Chromium 125+ today.

This matters for cross-framework scenarios because web components work everywhere. A <tour-step> custom element would render in React, Vue, Angular, Svelte, or plain HTML without wrappers. The positioning would be CSS-native. The framework runtime wouldn't matter.

We're not there yet. Browser support is Chromium-only, polyfills add weight, and you still need JavaScript for step sequencing, analytics, and keyboard navigation. But in 12-18 months, a web component + CSS anchor positioning approach could make the "which framework" question irrelevant for tour positioning.

What we recommend (and why)

We built Tour Kit, so take this with appropriate skepticism. Every claim below is verifiable against npm, GitHub, and bundlephobia.

For React teams, Tour Kit's headless architecture means you render your own components, compose with your own hooks, and keep full control over styling. The core ships at under 8 kB gzipped with zero runtime dependencies. You get WCAG 2.1 AA accessibility without configuration. And the extended packages (analytics, checklists, surveys, announcements, scheduling) exist in the same monorepo, so they share types and context.

Tour Kit doesn't support Vue today. The core package (@tour-kit/core) is framework-agnostic by design — step state, position calculation, storage, keyboard navigation all live outside React. A @tour-kit/vue package using Vue 3 Composition API is on the roadmap. When it ships, it would share the same core logic with identical TypeScript types and accessibility guarantees. No wrapper tradeoffs.

Honest limitations: no visual builder (you write code), React 18+ only, smaller community than Shepherd.js or React Joyride. The Vue package doesn't exist yet. If you need cross-framework support today, Shepherd.js or Driver.js are your practical options.

Get started with Tour Kit: usertourkit.com

FAQ

Can Shepherd.js work with both Vue 3 and React 19?

Shepherd.js has official wrappers for Vue and React. The Vue wrapper supports Vue 3, and the vanilla JS core works with React 19 since it doesn't touch React internals. The React wrapper is still class-based, though. As of April 2026, Shepherd.js has 13,716 GitHub stars with a publish ~17 days ago.

What is the lightest product tour library that works with Vue and React?

Driver.js is the lightest cross-framework option at 83 kB unpacked (roughly 5 kB gzipped). It's pure vanilla JavaScript with no framework wrappers, which means you call it imperatively from Vue's onMounted or React's useEffect. Tour Kit's core is under 8 kB gzipped but currently supports only React. Shepherd.js is 656 kB unpacked and Intro.js is 874 kB unpacked.

Is Intro.js free for commercial use?

Not for closed-source apps. Intro.js uses AGPL-3.0, which requires you to open-source your entire application if you distribute it. Commercial use requires a paid license, a common gotcha that surfaces during legal reviews. Driver.js, Shepherd.js, React Joyride, and Tour Kit's core all use MIT, which permits unrestricted commercial use.

Does any product tour library support WCAG 2.1 AA accessibility across frameworks?

None make explicit WCAG 2.1 AA compliance claims as of April 2026. Shepherd.js includes built-in keyboard navigation, which is a start. Tour Kit provides focus trapping, ARIA landmarks, keyboard navigation, and prefers-reduced-motion support, though only in React today. Accessibility remains the widest gap in cross-framework tour libraries.

Should I use a framework-agnostic library or a framework-native one?

Use a framework-native library if you're committed to one framework. You get reactive state, composable hooks, better TypeScript integration. Pick a framework-agnostic option (Shepherd.js, Driver.js) only if you genuinely run multiple frameworks in production. The wrapper DX tradeoff is real: you lose reactive state management for cross-framework coverage.


Disclosure: We built Tour Kit. Data points in this article are sourced from npm, GitHub, and bundlephobia and can be independently verified. Tour Kit is MIT-licensed (core packages) with commercial extended packages.

Ready to try userTourKit?

$ pnpm add @tour-kit/react