React Joyride alternatives for React 19 (2026)
Teams usually go looking for a React Joyride alternative for one of three reasons: v2 wouldn't install on React 19, the v3 migration looked like work, or the bundle felt heavy for a three-step tour. Here's what the alternatives actually offer — and when upgrading Joyride is the better move.
Last checked: October 10, 2026 — versions, licenses and downloads from the npm registry.
If React 19 was the problem, upgrade to React Joyride v3 before switching — it supports React 16.8–19. If you want something lighter, Driver.js (MIT, no dependencies) is the most popular alternative. Reactour is the closest React-native swap. On Next.js, NextStep gives you route-aware tours. Avoid Shepherd.js unless you're prepared to buy its commercial license.
- React Joyride 3.2.0 supports React 19; v2.9.3 (its last v2 release) declares React 15–18 as peers.
- Driver.js — MIT, framework-agnostic, the lightest mainstream option.
- @reactour/tour — MIT, React 16–19, provider + hook API, small bundle; last release May 2025.
- NextStep and Onborda — MIT, Next.js-first, with per-step nextRoute for multi-page tours.
- react-shepherd — capable, but AGPL-3.0 with a paid commercial license.
React Joyride is still the default React tour library — about 16.5 million npm downloads in the 90 days to October 8, 2026, roughly triple the same window a year earlier. So before you replace it, check whether the reason you're leaving still applies.
"React Joyride doesn't work with React 19." That was true of v2: the last v2 release, 2.9.3 from November 2024, declares React 15–18 as peer dependencies. Version 3, released in March 2026, declares React 16.8–19 and is SSR-safe according to its README. "v3 broke my code." It's a breaking release — named export, run defaulting to false, callback renamed to onEvent, props moved into options, getHelpers replaced by the useJoyride() hook — but there's a codemod: npx react-joyride-migrate v3 src/. "It's heavy." That one stands: bundlephobia measures 3.2.0 at about 25.6 kB gzipped including ten dependencies (the README says v3 is about 30% smaller than v2).
If you're still leaving, here are the options worth your time, in rough order of how often they're the right answer. For the bigger picture of React onboarding — including what every library leaves you to build — see our React guide and the Next.js guide.
The comparison table.
| React Joyridereact-joyride | Driver.jsdriver.js | Reactour@reactour/tour | NextStepnextstepjs | Onbordaonborda | Shepherd.jsshepherd.js | |
|---|---|---|---|---|---|---|
| License | MIT | MIT | MIT | MIT | MIT | AGPL-3.0 + paid commercial |
| Current version | 3.2.0 (Jul 9, 2026) | 1.9.0 (Oct 3, 2026) | 3.8.0 (May 7, 2025) | 2.3.0 (Jul 20, 2026) | 1.2.5 (Dec 22, 2024) | 15.3.0 (Aug 24, 2026) |
| Framework support | React 16.8–19 only | Any — vanilla TypeScript, no framework bindings needed | React 16–19 only | Next.js 13+, plus React Router and Remix adapters; needs motion | Next.js 13+ (App Router); needs framer-motion and Tailwind | Any; official React, Angular and Vue wrappers (also AGPL) |
| Size & approach | 25.6 kB gzip incl. 10 dependencies (bundlephobia) | ~5 kB gzip per its README; zero dependencies | 7.2 kB gzip incl. 3 dependencies (bundlephobia) | Not measured — bundlephobia didn't return a result | 2.3 kB gzip, excluding its framer-motion peer (bundlephobia) | 15.3 kB gzip incl. 2 dependencies (bundlephobia) |
| Multi-page / routes | Not built in; you navigate (controlled mode or an async before hook) and it polls for the target | Not built in; official docs pattern saves the step, then resumes with drive(index). waitForElement since 1.8 | Not built in; the project ships React Router sandboxes for route switching | Built in: nextRoute / prevRoute per step | Built in: nextRoute / prevRoute via next/navigation | Not built in; beforeShowPromise and waitForElement help across async renders |
| Accessibility | alertdialog role, focus trap with focus restore, configurable Esc | Keyboard-controllable; closeBtnLabel sets the close button's aria-label (1.9) | Focus lock (react-aria FocusScope), Esc and arrow keys | Arrow keys and Esc | Not documented in the README | Arrow-key navigation, Esc to exit, per-step aria-label |
| Styling | options for colors, styles prop, or your own tooltip/beacon components | Plain CSS file, popoverClass, CSS variables, onPopoverRender hook | Provider-level styles and swappable components | Default card or your own card component | Tailwind default card or your own card component | Minimal default CSS plus per-step classes — you do the design |
| Maintenance | Active — v3 rewrite March 2026, 3.2.0 in July | Very active — 1.5 through 1.9 shipped June–October 2026 | Slower — last release May 2025 | Active — 2.3.0 in July 2026 | Quiet — last release December 2024 | Active — 15.x through 2026 |
| npm downloads, 90 days | 16.5M | 22.4M | 2.5M | 749k | 468k | 4.0M |
Versions, publish dates, licenses and download counts (July 11 – October 8, 2026) from the npm registry. Sizes are bundlephobia’s min+gzip measurement of the package and its own dependencies, excluding peers such as React — or the library’s own README figure where noted.
Each one, honestly — with the code.
First, the upgrade path: React Joyride v3
- License:
- MIT
- Version:
- react-joyride 3.2.0
v3 is a substantial rewrite rather than a patch. Positioning moved from Popper/react-floater to Floating UI, the overlay is now an SVG cutout, steps gained async before hooks, targets can be refs or functions, and the tour polls for missing targets up to targetWaitTimeout before moving on. The hook API makes programmatic control much cleaner than v2's getHelpers.
"use client";
import { useJoyride } from "react-joyride";
const steps = [
{ target: "#new-project", content: "Everything starts here." },
{ target: "#invite", content: "Invite a teammate early." },
];
export function TourLauncher() {
const { controls, Tour } = useJoyride({ steps, continuous: true });
return (
<>
<button onClick={() => controls.start()}>Take the tour</button>
{Tour}
</>
);
}Driver.js — lightest, and not React-specific
- License:
- MIT
- Version:
- driver.js 1.9.0
Driver.js is the most-downloaded tour library on npm (about 22.4 million in the same 90 days) and the usual pick when the complaint is weight. It's MIT, has no dependencies, and runs from a useEffect. The trade-off is that steps are strings or HTML rather than React components, and the tour state lives outside React. We cover this match-up in depth in Driver.js vs React Joyride.
"use client";
import { useEffect } from "react";
import { driver } from "driver.js";
import "driver.js/dist/driver.css";
export function OnboardingTour() {
useEffect(() => {
const tour = driver({
showProgress: true,
steps: [
{ element: "#new-project", popover: { title: "Create a project", description: "Everything starts here." } },
{ element: "#invite", popover: { title: "Invite your team", description: "Tours work better with company." } },
],
});
tour.drive();
return () => tour.destroy(); // safe: destroy() on an inactive tour is a no-op
}, []);
return null;
}Reactour — the closest React-native swap ("react joyride vs react tour")
- License:
- MIT
- Version:
- @reactour/tour 3.8.0
When people search "react joyride vs react tour" they usually mean Reactour, published today as @reactour/tour (the old unscoped reactour package is the legacy v1, with React peers capped at 18). It's MIT, supports React 16–19, and uses a provider-plus-hook model: wrap the app in TourProvider, then open the tour from anywhere with useTour(). Focus is locked inside the popover with react-aria's FocusScope, keyboard navigation covers Esc and the arrow keys, and bundlephobia measures it at about 7.2 kB gzipped.
The caution is cadence: 3.8.0 shipped in May 2025 and there hasn't been a release since, although the GitHub repository shows activity in 2026. Fine for a stable tour; check the issue tracker before betting a complex one on it.
"use client";
import { TourProvider, useTour } from "@reactour/tour";
const steps = [
{ selector: "#new-project", content: "Everything starts here." },
{ selector: "#invite", content: "Tours work better with company." },
];
// Wrap your app once…
export function TourRoot({ children }: { children: React.ReactNode }) {
return <TourProvider steps={steps}>{children}</TourProvider>;
}
// …and open the tour from anywhere below it.
export function StartTourButton() {
const { setIsOpen } = useTour();
return <button onClick={() => setIsOpen(true)}>Take the tour</button>;
}NextStep and Onborda — route-aware tours for Next.js
- License:
- MIT
- Version:
- nextstepjs 2.3.0
Both are MIT and built for the App Router, and both solve the problem Joyride leaves to you: tours that cross pages. Each step can declare nextRoute and prevRoute, and the library navigates for you. NextStep (nextstepjs 2.3.0, July 2026) also ships adapters for React Router and Remix and requires the motion package. Onborda (1.2.5, December 2024) depends on framer-motion and Tailwind for its default card, and its README notes a fixed 500 ms delay after route changes. Both have grown fast: about 749k and 468k downloads respectively in the last 90 days.
Choose NextStep if you want the more actively released of the two; choose either only if you're on Next.js (or, for NextStep, one of its adapters).
// app/layout.tsx — npm i nextstepjs motion
import { NextStep, NextStepProvider, type Tour } from "nextstepjs";
const tours: Tour[] = [
{
tour: "welcome",
steps: [
{
icon: null,
title: "Create a project",
content: "Everything starts here.",
selector: "#new-project",
side: "bottom",
showControls: true,
showSkip: true,
nextRoute: "/settings", // the next step lives on another route
},
{
icon: null,
title: "Invite your team",
content: "Tours work better with company.",
selector: "#invite",
side: "bottom",
showControls: true,
showSkip: true,
prevRoute: "/",
},
],
},
];
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<NextStepProvider>
<NextStep steps={tours}>{children}</NextStep>
</NextStepProvider>
</body>
</html>
);
}
// Anywhere in a client component:
// const { startNextStep } = useNextStep();
// startNextStep("welcome");react-shepherd — capable, but check the license ("react joyride vs shepherd")
- License:
- AGPL-3.0 + paid commercial
- Version:
- shepherd.js 15.3.0
Shepherd's React wrapper (react-shepherd 7.0.6, React 18–19) exposes the full Shepherd engine through a ShepherdJourneyProvider and useShepherd() hook. Technically it's a strong alternative. Commercially it isn't a drop-in for an MIT library: Shepherd and its wrappers are AGPL-3.0, and the license file requires a commercial license ($50 or $300 lifetime at the time of writing) for revenue-generating products and companies. If Joyride's MIT license was part of why you chose it, keep that in mind.
Which should you pick?
You left because of React 19
→ React Joyride v3
It supports React 16.8–19; run the codemod and stay.
Bundle size is the complaint
→ Driver.js
MIT, zero dependencies, the lightest mainstream option.
You want tour steps that are React components, but lighter than Joyride
→ @reactour/tour
Provider + hook API, focus lock, about 7 kB gzipped.
Next.js App Router, tour spans several routes
→ NextStep
Per-step nextRoute/prevRoute, actively released, adapters for other routers.
You need conditional steps and a rich event model and can buy a license
→ react-shepherd
Shepherd's engine is the most configurable — under AGPL or a paid license.
When a no-code tool makes more sense.
Sometimes the reason for leaving Joyride is not the library at all. It's that every copy change goes through a pull request, nobody can see where users abandon the tour, and "show this only to new admins on the Pro plan" turned into a week of work. Swapping one library for another won't fix any of that.
If that sounds familiar, a no-code onboarding tool is worth pricing against the engineering time. Wakeline is one option: a script snippet plus an identify() call, tours built visually on your live app, a free plan covering 3 flows and 1,000 monthly active users, and paid plans from $49/month. If your tour is small and stable, an MIT library is still the leaner answer.
Does React Joyride work with React 19?
Yes, from version 3. react-joyride 3.x declares React 16.8 through 19 as supported peers. The last v2 release, 2.9.3, declares React 15 through 18, which is why v2 installs on React 19 hit peer-dependency errors.
What is the best React Joyride alternative?
It depends on why you're leaving. For a lighter bundle, Driver.js (MIT, no dependencies). For a React-native API, @reactour/tour (MIT, React 16–19). For multi-route tours on Next.js, NextStep (MIT). If React 19 was the only issue, upgrading to Joyride v3 is usually the smallest change.
How do I migrate from React Joyride v2 to v3?
Run npx react-joyride-migrate v3 src/ (add --dry --print to preview). It handles the import change, prop renames, the options restructuring and the buttons array. Review spread props, dynamic values and any getHelpers usage by hand, since getHelpers is replaced by the useJoyride hook.
React Joyride vs Reactour: which is better?
React Joyride has more features, stronger documented accessibility defaults and more frequent releases. @reactour/tour is smaller, about 7 kB gzipped against Joyride's 25.6 kB on bundlephobia, and has a simple provider-and-hook API, but its last release was May 2025. Both are MIT.
React Joyride vs Shepherd: what's the difference?
Both are capable step engines. React Joyride is MIT and React-only. Shepherd.js, with its react-shepherd wrapper, is framework-agnostic and very configurable, but it's AGPL-3.0, and its license requires a paid commercial license for revenue-generating products.
Is there a React Joyride alternative with multi-page support?
NextStep and Onborda both support per-step nextRoute and prevRoute. NextStep works with Next.js, React Router and Remix through adapters, and Onborda works with Next.js. Joyride, Driver.js and Reactour leave navigation to you.
Rather not maintain a tour library?
The free plan covers 3 flows and 1,000 monthly active users — enough to compare against the library route on your own app.
Free plan available · No credit card · No demo call