Help Menu Integration
Tours should be triggerable on demand — not just on first visit. A help menu, a ”?” button, or a keyboard shortcut should let users re-run the tour for whatever page they are on.
The registry pattern
TourRegistryProvider + useRegisterTour gives you a single startCurrentTour() function in your layout that always triggers the right tour for whatever page is mounted.
1. Wrap your layout
Add TourRegistryProvider around your app’s persistent shell (the component that contains your sidebar or navbar):
import { TourRegistryProvider } from '@trailguide/runtime'
export default function RootLayout({ children }) {
return (
<TourRegistryProvider>
<AppShell>{children}</AppShell>
</TourRegistryProvider>
)
}2. Wire up the help button
In your sidebar or navbar, call useTourRegistry().startCurrentTour():
import { useTourRegistry } from '@trailguide/runtime'
export function AppShell({ children }) {
const { startCurrentTour } = useTourRegistry()
return (
<div>
<Sidebar>
<button onClick={startCurrentTour}>
Quick Start Tour
</button>
</Sidebar>
<main>{children}</main>
</div>
)
}3. Register each page’s tour
In each page component, replace useTrailManager with useRegisterTour. It does everything useTrailManager does, plus registers the tour with the nearest TourRegistryProvider:
import { useRegisterTour, Trailguide } from '@trailguide/runtime'
import { dashboardTour } from './tours'
export default function DashboardPage() {
const { isActive, dismiss } = useRegisterTour(dashboardTour, {
once: true,
})
return (
<>
{/* page content */}
{isActive && <Trailguide trail={dashboardTour} onComplete={dismiss} onSkip={dismiss} />}
</>
)
}Now when the help button is clicked, it calls the registered show() function of whatever page is currently mounted — dashboard, settings, analytics, or any other page.
How it works
TourRegistryProviderholds a ref to the current page’sshow()function.- When a page mounts,
useRegisterTourregisters itsshow()and returns a cleanup function. - When the page unmounts, the cleanup function deregisters it.
startCurrentTour()calls whatever is currently registered — always the active page’s tour.
Only one tour can be registered at a time, so clicking the help button always runs the right tour.
Keyboard shortcut
You can wire the tour to a keyboard shortcut in your layout alongside the button:
import { useEffect } from 'react'
import { useTourRegistry } from '@trailguide/runtime'
export function AppShell({ children }) {
const { startCurrentTour } = useTourRegistry()
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if (e.key === '?' && !e.metaKey && !e.ctrlKey) {
startCurrentTour()
}
}
window.addEventListener('keydown', handler)
return () => window.removeEventListener('keydown', handler)
}, [startCurrentTour])
return <>{children}</>
}useRegisterTour accepts the same options as useTrailManager, including once, enabled, delay, resumable, and all callbacks.