mcpField
R
react-joyride

react-joyride

github.com/gilbarbara開発7.9k691 回インストール16 週間前に更新
リポジトリ

react-joyride について

React Joyride は、React アプリの画面を案内するツアーを作成するライブラリです。フックとコンポーネントの API を備え、ステップ設定、非同期フック、イベント処理、UI のカスタマイズに対応します。

主な機能

  1. 01フックとコンポーネントの API
  2. 02ツアーのステップと対象の設定
  3. 03非同期の前後フック
  4. 04イベント処理とプログラム制御
  5. 05スタイルとコンポーネントのカスタマイズ

活用シーン

  1. 01アプリ画面を通じたユーザー案内
  2. 02複数ステップでの操作説明
  3. 03ステップ表示前の UI 変更待ち
  4. 04ツアーの進行状況とイベント追跡

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gilbarbara/react-joyride --skill react-joyride

インストール後、Claude Code で/react-joyrideを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api-events-components.md
api-props-options.md
api-step-state-controls.md
patterns.md

詳細

React Joyride v3

React アプリでガイドツアーを作成できます。公開 API は 2 つあります。useJoyride() フック(推奨)と <Joyride> コンポーネントです。

オンラインドキュメント: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
        }
      }}
    />
  );
}

フックは { controls, failures, on, state, step, Tour } を返します。JSX で Tour をレンダリングしてください。

ドキュメント:https://v3.react-joyride.com/docs/getting-started

コアコンセプト

ツアーには 2 つの状態軸があります。

ツアーのステータス:idle -> ready -> waiting -> running <-> paused -> finished | skipped

  • idle:ステップが読み込まれていません
  • ready:ステップが読み込まれ、run: true になるのを待っています
  • waiting:run=true ですが、ステップを非同期で読み込んでいます(ステップが到着すると running に遷移します)
  • running:ツアーが実行中です
  • paused:ツアーが一時停止されています(COMPLETE 時の制御モード、または stop() の呼び出し)
  • finished / skipped:ツアーが終了しました

ステップのライフサイクル(各ステップ):init -> ready -> beacon_before -> beacon -> tooltip_before -> tooltip -> complete

  • *_before フェーズ:ここでスクロールと位置決めが行われます
  • beacon:脈動するインジケーターが表示されます(continuous で移動中の場合、skipBeacon の場合、または placement: 'center' の場合はスキップされます)
  • tooltip:ツールチップが表示され、操作可能になります

ドキュメント:https://v3.react-joyride.com/docs/how-it-works

ステップの設定

各ステップには target と content が必要です。それ以外のフィールドはすべて省略可能です。

{
  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') }
よく使うステップオプション(ステップごとに上書き可能)
オプションデフォルト説明
placement'bottom'ツールチップの位置です。モーダルスタイルにするには 'center' を使います(target: 'body' が必要です)
skipBeaconfalseビーコンをスキップし、ツールチップを直接表示します
buttons['back','close','primary']ツールチップ内のボタンです。スキップボタンを追加するには 'skip' を指定します
hideOverlayfalse暗いオーバーレイを表示しません
blockTargetInteractionfalseハイライトされた要素へのクリックをブロックします
before-(data) => Promise<void> — ステップ表示前に実行する非同期フックです
after-(data) => void — ステップ完了後に実行する非同期処理を待たないフックです
skipScrollfalseターゲットまでスクロールしません
scrollTarget-target の代わりにこの要素までスクロールします
spotlightTarget-target の代わりにこの要素をハイライトします
spotlightPadding10スポットライトの周囲の余白です。数値、または { top, right, bottom, left } を指定します
targetWaitTimeout1000ターゲットが表示されるまで待つ時間(ミリ秒)です。0 = 待機しません
beforeTimeout5000before フックを待つ時間(ミリ秒)です。0 = タイムアウトしません

すべての Options フィールドは、options プロパティを使ってグローバルに設定するか、ステップごとに設定できます。ステップごとの値はグローバル設定を上書きします。

ドキュメント:https://v3.react-joyride.com/docs/step | https://v3.react-joyride.com/docs/props/options

非制御モードと制御モード

非制御(デフォルト — 強く推奨)

ツアーがステップの移動を内部で管理します。ほとんどのユースケースではこちらが適切です。

ライブラリが非同期の遷移を処理します。 ステップで UI の変更(ドロップダウンを開く、データを読み込む、アニメーションなど)を待つ必要がある場合は、before フックを使います。ツアーはプロミスが解決するまで待ってからステップを表示します。ターゲット要素がまだ DOM にない場合は、targetWaitTimeout(デフォルト:1000 ミリ秒)によってポーリングされます。こうしたケースで制御モードを使う必要はありません。

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 を使用)— 必要な場合にのみ使用

親がステップインデックスを外部で管理する必要がある場合に限り、制御モードを使ってください(たとえば、URL パラメーターとの同期、外部のステートマシン、または before / after フックでは対応できない複雑な複数コンポーネント間の連携など)。

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));
    }
  },
});

制御モードのルール:

  • go() と reset() は無効になります(警告がログに記録されます)
  • イベントに応じて stepIndex を更新する必要があります
  • ツアーは COMPLETE で一時停止します — 自分で次に進める必要があります
  • インデックスを外部で管理する強い理由がない限り、before / after フックを使った非制御モードを推奨します

イベントシステム

onEvent コールバック
onEvent: (data: EventData, controls: Controls) => void

data オブジェクトには、ツアーの全状態とイベント固有のフィールドが含まれます。controls オブジェクトを使うと、ツアーをプログラムから制御できます。

イベントの種類(ステップごとの順序)
イベントタイミング
tour:startツアー開始時
step:before_hookbefore フックが呼び出されたとき
step:before対象が見つかり、ステップを表示する直前
scroll:start対象へのスクロール開始時
scroll:endスクロール完了時
beaconビーコン表示時
tooltipツールチップ表示時
step:afterユーザーが移動したとき(次へ/前へ/閉じる/スキップ)
step:after_hookafter フックが呼び出されたとき
tour:endツアー終了またはスキップ時
tour:statusステータス変更時(停止/リセット時)
error:target_not_found対象の要素が見つからないとき
error一般的なエラー
on() によるイベントの購読
const { on, Tour } = useJoyride({ ... });

useEffect(() => {
  const unsubscribe = on('tooltip', (data, controls) => {
    analytics.track('tour_step_viewed', { step: data.index });
  });
  return unsubscribe;
}, [on]);

ドキュメント:https://v3.react-joyride.com/docs/events

コントロール

useJoyride() の戻り値、または onEvent の第 2 引数から利用できます。

メソッド説明
next()次のステップに進む
prev()前のステップに戻る
close(origin?)現在のステップを閉じて、次に進む
skip(origin?)ツアー全体をスキップする
start(index?)ツアーを開始する
stop(advance?)ツアーを停止(一時停止)する
go(index)ステップに移動する(非制御モードのみ)
reset(restart?)ツアーをリセットする(非制御モードのみ)
open()現在のステップのツールチップを開く
info()現在の状態を取得する

ドキュメント:https://v3.react-joyride.com/docs/hook

スタイル設定とテーマ設定

カスタマイズには、簡単なものから完全な制御まで 3 つの方法があります。

1. 色のオプション(最も簡単)
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)
}
2. スタイルのオーバーライド
styles: {
  tooltip: { borderRadius: 12 },
  buttonPrimary: { backgroundColor: '#1976d2' },
  buttonBack: { color: '#666' },
  spotlight: { borderRadius: 8 },
}

スタイルキー:arrow、beacon、beaconInner、beaconOuter、beaconWrapper、buttonBack、buttonClose、buttonPrimary、buttonSkip、floater、loader、overlay、tooltip、tooltipContainer、tooltipContent、tooltipFooter、tooltipFooterSpacer、tooltipTitle

3. カスタムコンポーネント(完全な制御)

次のセクションを参照してください。

ドキュメント:https://v3.react-joyride.com/docs/props/styles

カスタムコンポーネント

props を使って任意の UI コンポーネントを置き換えられます。各コンポーネントには、ステップデータとボタンハンドラーを含むレンダープロップが渡されます。

カスタムツールチップ
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} ... />

重要:コンテナに tooltipProps を展開してください(role="dialog" と aria-modal が設定されます)。正しくアクションを処理するには、ボタンにボタン用 props(backProps、primaryProps、closeProps、skipProps)を展開してください。

カスタムビーコン

<button> ラッパー内に配置される <span> をレンダリングする必要があります。BeaconRenderProps を受け取ります:{ continuous, index, isLastStep, size, step }。

カスタム矢印

ArrowRenderProps を受け取ります:{ base, placement, size }。

カスタムローダー

LoaderRenderProps を受け取ります:{ step }。ローダーを無効にするには null に設定します。

ドキュメント:https://v3.react-joyride.com/docs/custom-components

問題 → 解決方法ガイド

必要なこと使用するもの
ステップ間の非同期 UI 変更(ドロップダウン、アニメーション、データ読み込み)を待つPromise を返す before フック。制御モードは使用しない
ステップの移動を外部から制御する(URL 同期、外部ステートマシン)stepIndex を使った制御モード。ただし、まず before/after フックを試してください
失敗したステップ(対象が見つからない、フックエラー)を追跡するuseJoyride() の戻り値に含まれる failures 配列
onEvent の switch を使わずに特定のイベントをリッスンするuseJoyride() の戻り値から on('event:type', handler) を使用
中央揃えのモーダル形式のステップを表示するtarget: 'body' + placement: 'center'

よくある注意点とデバッグ

まず debug: true を使う

debug prop は、最も強力なトラブルシューティングツールです。ライフサイクルの遷移、状態の変更、イベントの発行について詳細なログをコンソールに出力します。問題が発生した場合は、必ずここから始めてください。

<Joyride debug={true} ... />
// or
useJoyride({ debug: true, ... })

コンソール出力には、ツアーがどのライフサイクルフェーズまで進んだか、どのアクションが実行されているか、どこで停止しているかが正確に表示されます。

ツアーが開始されない
  • run={true} が設定されていることを確認する
  • steps 配列が空でなく、各ステップに有効な target と content があることを確認する
  • SSR の場合: <Joyride> コンポーネントを使用する (DOM アクセスを自動でガードします)、または typeof window !== 'undefined' を確認する
ターゲットが見つからない
  • コンソールでセレクターをテストする: document.querySelector('.your-selector')
  • 要素が表示されている必要があります (display: none、visibility: hidden、またはサイズがゼロであってはなりません)
  • 要素が後からマウントされる場合は、targetWaitTimeout を増やします (デフォルトは 1000ms)
  • targetWaitTimeout: 0 を設定すると待機を完全にスキップします
  • 非制御モードでは、ターゲットが見つからない場合は自動的に次へ進みます。制御モードでは、error:target_not_found イベントを処理してください
ツールチップが表示されない / オーバーレイがちらつく
  • debug: true を追加し、コンソールでどのライフサイクルフェーズに到達しているかを確認する
  • ターゲット要素がビューポート内にあるか、スクロール可能であることを確認する
  • 祖先要素の CSS overflow: hidden がターゲットをクリップしていないか確認する
  • ポータルやモーダルを使用している場合、ターゲットにアクセスできない可能性があります
制御モードでスタックする
  • 最初の疑問: 本当に制御モードが必要ですか? 非同期のニーズのほとんどは、非制御モードの before/after フックで解決できます
  • 制御モードを使用する場合: type === 'step:after' のときに onEvent ハンドラーで stepIndex を必ず更新してください
  • 前方ナビゲーション (action !== 'prev') と後方ナビゲーション (action === 'prev') の両方を処理してください
  • 壊れたステップをスキップするために error:target_not_found も処理してください
  • go() と reset() は制御モードでは動作しません
before フックのタイムアウト
  • デフォルトの beforeTimeout は 5000ms です — 非同期操作にそれ以上かかる場合は増やしてください
  • beforeTimeout: 0 を設定するとタイムアウトしません
  • 待機中は loaderDelay (300ms) の後にローダーが表示されます
スクロールの問題
  • scrollTarget を使用すると、ツールチップのターゲットとは別の要素にスクロールできます
  • ヘッダーや固定要素のために scrollOffset (デフォルトは 20px) を調整します
  • ステップの自動スクロールを無効にするには skipScroll: true を設定します
  • scrollToFirstStep はデフォルトで false です — 最初のステップが画面外にある場合は true に設定してください
中央配置
  • モーダルスタイルの中央配置ツールチップには、target: 'body' とともに placement: 'center' を使用します
  • 中央配置ではビーコンと矢印が自動的に非表示になります
インポート
// 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';

ドキュメント: https://v3.react-joyride.com/docs/exports

リファレンスファイル

完全な API の詳細については、以下をお読みください:

  • references/api-props-options.md — Props、Options (デフォルト値付きの全 30 以上のフィールド)、Locale、FloatingOptions、Styles 型の全体
  • references/api-step-state-controls.md — Step、StepMerged、StepTarget、State、Controls (全 10 メソッド)、UseJoyrideReturn、StepFailure
  • references/api-events-components.md — 全 13 種類のイベント、ACTIONS/LIFECYCLE/STATUS/ORIGIN 定数、EventData、カスタムコンポーネントの render props
  • references/patterns.md — 完全な動作例: 制御モード、before/after フック、カスタムツールチップ、イベント購読、動的ステップ

コメント