用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill react-joyride命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | react-joyride |
| description | >- Use when this capability is needed. |
Create guided tours in React apps. Two public APIs: the useJoyride() hook (recommended) and the <Joyride> component.
Online docs: https://v3.react-joyride.com
import { useJoyride, STATUS, Status } from 'react-joyride';
function App() {
const { Tour } = useJoyride({
continuous: true,
run: true,
steps: [
{ target: '.my-element', content: 'This is the first step', title: 'Welcome' },
{ target: '#sidebar', content: 'Navigate here', placement: 'right' },
],
onEvent: (data) => {
if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
// Tour ended
}
},
});
return <div>{Tour}{/* rest of app */}</div>;
}
import { Joyride, STATUS, Status } from 'react-joyride';
function App() {
return (
<Joyride
continuous
run={true}
steps={[
{ target: '.my-element', content: 'First step' },
{ target: '#sidebar', content: 'Second step' },
]}
onEvent={(data) => {
if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
// Tour ended
}
}}
/>
);
}
The hook returns { controls, failures, on, state, step, Tour }. Render Tour in your JSX.
Docs: https://v3.react-joyride.com/docs/getting-started
The tour has two state dimensions:
Tour Status: idle -> ready -> waiting -> running <-> paused -> finished | skipped
idle: No steps loadedready: Steps loaded, waiting for run: truewaiting: run=true but steps loading async (transitions to running when steps arrive)running: Tour activepaused: Tour paused (controlled mode at COMPLETE, or stop() called)finished / skipped: Tour endedStep Lifecycle (per step): init -> ready -> beacon_before -> beacon -> tooltip_before -> tooltip -> complete
*_before phases: scrolling and positioning happen herebeacon: Pulsing indicator shown (skipped when continuous + navigating, skipBeacon, or placement: 'center')tooltip: The tooltip is visible and interactiveDocs: https://v3.react-joyride.com/docs/how-it-works
Each step requires target and content. All other fields are optional.
{
target: '.my-element', // CSS selector, HTMLElement, React ref, or () => HTMLElement
content: 'Step body text', // ReactNode
title: 'Optional title', // ReactNode
placement: 'bottom', // Default. Also: top, left, right, *-start, *-end, auto, center
id: 'unique-id', // Optional identifier
data: { custom: 'data' }, // Attached to event callbacks
}
// CSS selector
{ target: '.sidebar-nav' }
// HTMLElement
{ target: document.getElementById('my-el') }
// React ref
const ref = useRef(null);
{ target: ref }
// Function (evaluated each lifecycle)
{ target: () => document.querySelector('.dynamic-element') }
| Option | Default | Description |
|---|---|---|
placement | 'bottom' | Tooltip position. Use 'center' for modal-style (requires target: 'body') |
skipBeacon | false | Skip beacon, show tooltip directly |
buttons | ['back','close','primary'] | Buttons in tooltip. Add 'skip' for skip button |
hideOverlay | false | Don't show dark overlay |
blockTargetInteraction | false | Block clicks on highlighted element |
before | - | (data) => Promise<void> — async hook before step shows |
after | - | (data) => void — fire-and-forget hook after step completes |
skipScroll | false | Don't scroll to target |
scrollTarget | - | Scroll to this element instead of target |
spotlightTarget | - | Highlight this element instead of target |
spotlightPadding | 10 | Padding around spotlight. Number or { top, right, bottom, left } |
targetWaitTimeout | 1000 | ms to wait for target to appear. 0 = no waiting |
beforeTimeout | 5000 | ms to wait for before hook. 0 = no timeout |
All Options fields can be set globally via options prop or per-step. Per-step values override global.
Docs: https://v3.react-joyride.com/docs/step | https://v3.react-joyride.com/docs/props/options
The tour manages step navigation internally. This is the right choice for most use cases.
The library handles async transitions for you. If a step needs to wait for a UI change (dropdown opening, data loading, animation), use before hooks — the tour waits for the promise to resolve before showing the step. If a target element isn't in the DOM yet, targetWaitTimeout (default: 1000ms) handles polling for it. You do NOT need controlled mode for these cases.
const { Tour } = useJoyride({
continuous: true,
run: isRunning,
steps: [
{ target: '.nav', content: 'Navigation' },
{
target: '.dropdown-item',
content: 'Inside the dropdown',
before: () => {
// Open dropdown and wait for animation — tour waits automatically
openDropdown();
return new Promise(resolve => setTimeout(resolve, 300));
},
after: () => closeDropdown(), // Clean up after step (fire-and-forget)
},
{ target: '.main-content', content: 'Main content' },
],
onEvent: (data) => {
if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(data.status)) {
setIsRunning(false);
}
},
});
stepIndex) — use sparinglyOnly use controlled mode when the parent genuinely needs to manage the step index externally (e.g., syncing with URL params, external state machines, or complex multi-component coordination that before/after hooks can't handle).
const [stepIndex, setStepIndex] = useState(0);
const [run, setRun] = useState(true);
const { Tour } = useJoyride({
continuous: true,
run,
stepIndex, // This makes it controlled
steps,
onEvent: (data) => {
const { action, index, status, type } = data;
if (([STATUS.FINISHED, STATUS.SKIPPED] as Status).includes(status)) {
setRun(false);
return;
}
if (type === 'step:after' || type === 'error:target_not_found') {
setStepIndex(index + (action === 'prev' ? -1 : 1));
}
},
});
Controlled mode rules:
go() and reset() are disabled (logged warning)stepIndex in response to eventsbefore/after hooks unless you have a strong reason for external index managementonEvent callbackonEvent: (data: EventData, controls: Controls) => void
The data object contains the full tour state plus event-specific fields. The controls object lets you programmatically control the tour.
| Event | When |
|---|---|
tour:start | Tour begins |
step:before_hook | before hook is called |
step:before | Target found, step about to render |
scroll:start | Scrolling to target |
scroll:end | Scroll complete |
beacon | Beacon shown |
tooltip | Tooltip shown |
step:after | User navigated (next/prev/close/skip) |
step:after_hook | after hook called |
tour:end | Tour finished or skipped |
tour:status | Status changed (on stop/reset) |
error:target_not_found | Target element not found |
error | Generic error |
on()const { on, Tour } = useJoyride({ ... });
useEffect(() => {
const unsubscribe = on('tooltip', (data, controls) => {
analytics.track('tour_step_viewed', { step: data.index });
});
return unsubscribe;
}, [on]);
Docs: https://v3.react-joyride.com/docs/events
Available via useJoyride() return value or onEvent second argument:
| Method | Description |
|---|---|
next() | Advance to next step |
prev() | Go to previous step |
close(origin?) | Close current step, advance |
skip(origin?) | Skip the tour entirely |
start(index?) | Start the tour |
stop(advance?) | Stop (pause) the tour |
go(index) | Jump to step (uncontrolled only) |
reset(restart?) | Reset tour (uncontrolled only) |
open() | Open tooltip for current step |
info() | Get current state |
Docs: https://v3.react-joyride.com/docs/hook
Three layers of customization (from simple to full control):
options: {
primaryColor: '#1976d2', // Buttons and beacon
backgroundColor: '#1a1a2e', // Tooltip background
textColor: '#ffffff', // Tooltip text
overlayColor: 'rgba(0,0,0,0.7)', // Overlay backdrop
arrowColor: '#1a1a2e', // Arrow (match background)
}
styles: {
tooltip: { borderRadius: 12 },
buttonPrimary: { backgroundColor: '#1976d2' },
buttonBack: { color: '#666' },
spotlight: { borderRadius: 8 },
}
Style keys: arrow, beacon, beaconInner, beaconOuter, beaconWrapper, buttonBack, buttonClose, buttonPrimary, buttonSkip, floater, loader, overlay, tooltip, tooltipContainer, tooltipContent, tooltipFooter, tooltipFooterSpacer, tooltipTitle
See next section.
Docs: https://v3.react-joyride.com/docs/props/styles
Replace any UI component via props. Each receives render props with step data and button handlers.
import type { TooltipRenderProps } from 'react-joyride';
function MyTooltip({ backProps, index, primaryProps, size, skipProps, step, tooltipProps }: TooltipRenderProps) {
return (
<div {...tooltipProps} style={{ background: '#fff', padding: 16, borderRadius: 8, width: step.width }}>
{step.title && <h3>{step.title}</h3>}
<div>{step.content}</div>
<div>
{index > 0 && <button {...backProps}>Back</button>}
<button {...primaryProps}>Next</button>
</div>
</div>
);
}
// Usage
<Joyride tooltipComponent={MyTooltip} ... />
Important: Spread tooltipProps on the container (sets role="dialog" and aria-modal). Spread button props (backProps, primaryProps, closeProps, skipProps) on buttons for correct action handling.
Must render a <span> (placed inside a <button> wrapper). Receives BeaconRenderProps: { continuous, index, isLastStep, size, step }.
Receives ArrowRenderProps: { base, placement, size }.
Receives LoaderRenderProps: { step }. Set to null to disable the loader.
Docs: https://v3.react-joyride.com/docs/custom-components
| I need to... | Use |
|---|---|
| Wait for async UI changes between steps (dropdown, animation, data load) | before hook returning a Promise — not controlled mode |
| Control step navigation externally (URL sync, external state machine) | Controlled mode with stepIndex — but try before/after hooks first |
| Track which steps failed (target missing, hook error) | failures array from useJoyride() return |
Listen to specific events without onEvent switch | on('event:type', handler) from useJoyride() return |
| Show a centered modal-style step | target: 'body' + placement: 'center' |
debug: true firstThe debug prop is the most powerful troubleshooting tool. It logs detailed lifecycle transitions, state changes, and event emissions to the console. Always start here when something isn't working.
<Joyride debug={true} ... />
// or
useJoyride({ debug: true, ... })
The console output shows exactly which lifecycle phase the tour reaches, what actions are firing, and where it gets stuck.
run={true} is setsteps array is not empty and steps have valid target + content<Joyride> component (auto-guards DOM access) or check typeof window !== 'undefined'document.querySelector('.your-selector')display: none, visibility: hidden, or zero dimensions)targetWaitTimeout (default: 1000ms)targetWaitTimeout: 0 to skip waiting entirelyerror:target_not_found eventdebug: true and check the console to see which lifecycle phase is reachedoverflow: hidden on ancestors clipping the targetbefore/after hooks in uncontrolled modestepIndex in your onEvent handler when type === 'step:after'action !== 'prev') and backward (action === 'prev') navigationerror:target_not_found to skip broken stepsgo() and reset() don't work in controlled modebeforeTimeout is 5000ms — increase if your async operation takes longerbeforeTimeout: 0 for no timeoutloaderDelay (300ms) while waitingscrollTarget to scroll to a different element than the tooltip targetscrollOffset (default: 20px) for headers or fixed elementsskipScroll: true to disable auto-scrolling for a stepscrollToFirstStep: false by default — set to true if first step is off-screenplacement: 'center' with target: 'body' for modal-style centered tooltips// Named exports only (no default export in v3)
import { Joyride, useJoyride } from 'react-joyride';
// Constants for type-safe comparisons
import { ACTIONS, EVENTS, LIFECYCLE, ORIGIN, STATUS } from 'react-joyride';
// Types
import type { Step, Props, EventData, Controls, TooltipRenderProps } from 'react-joyride';
Docs: https://v3.react-joyride.com/docs/exports
Read these for complete API details:
references/api-props-options.md — Full Props, Options (all 30+ fields with defaults), Locale, FloatingOptions, Styles typesreferences/api-step-state-controls.md — Step, StepMerged, StepTarget, State, Controls (all 10 methods), UseJoyrideReturn, StepFailurereferences/api-events-components.md — All 13 event types, ACTIONS/LIFECYCLE/STATUS/ORIGIN constants, EventData, custom component render propsreferences/patterns.md — Complete working examples: controlled mode, before/after hooks, custom tooltip, event subscription, dynamic stepsSource: gilbarbara/react-joyride — distributed by TomeVault.