コンテンツへスキップ
Fumadocs

ヘッドレス

ストーリーのUIを置き換えるか、ヘッドレスレイヤーを使って独自のUIを構築します。

概要

@fumadocs/story は <StoryProvider />、useStory()、useStoryArgs() をエクスポートしています。これらは UI を持たず、ストーリーの状態のみを提供します。

  • 選択中のバリアントと、そのバリアントに対応するプリセット
  • レンダリングされるコンポーネントの引数 (キー入力のたびに再レンダリングされないよう、デバウンスされます)

組み込みのパネルはこれらを基に作られており、パネルを独自のものに置き換えることもできます。

独自のパネル

defineStoryFactory() には WithControl コンポーネントを渡せます。このコンポーネントは、組み込みのパネルの代わりにレンダリングされます。

lib/story.tsx
import { defineStoryFactory } from '@fumadocs/story/next/client';
import { StoryPanel } from '@/components/story-panel';

export const { defineStory } = defineStoryFactory({ WithControl: StoryPanel });

このコンポーネントは、ストーリーのプリセットと、レンダリング対象のコンポーネントを受け取ります。

components/story-panel.tsx
'use client';
import { StoryProvider, useStory, useStoryArgs, type WithControlProps } from '@fumadocs/story';

export function StoryPanel(props: WithControlProps) {
  return (
    <StoryProvider {...props}>
      <Content />
    </StoryProvider>
  );
}

function Content() {
  const { presets, variant, setVariant, preset, Component } = useStory();
  const args = useStoryArgs();

  return (
    <div>
      <select value={variant} onChange={(e) => setVariant(e.target.value)}>
        {presets.map((item) => (
          <option key={item.variant} value={item.variant}>
            {item.variant}
          </option>
        ))}
      </select>
      <Component {...args} />
      <pre>{JSON.stringify(preset?.controls, null, 2)}</pre>
    </div>
  );
}
フック説明
useStory()プリセット、選択中の variant と setVariant、Component、frame を返します。
useStoryArgs()コントロールの値を反映した、レンダリング対象のコンポーネントの引数を返します。
useStoryFrame()frame の iframe 用の ref を返し、その iframe に引数を送信します。

コントロールの編集には、<StoryProvider /> がセットアップするフォームエンジン @fumari/stf を使用します。preset.controls は、コンポーネントの props の型ツリーです。

組み込みパネルをベースにする

コントロールパネルを一から作成するには、型ツリーのあらゆる種類のノードを処理する必要があります。以下の組み込みパネルをインストールし、 それを編集することをおすすめします。

UI のインストール

引数のコントロールを含む、パネル全体です。

npx @fumadocs/cli add story/controls
lib/story.tsx
import { defineStoryFactory } from '@fumadocs/story/next/client';
import { WithControl } from '@/components/story';

export const { defineStory } = defineStoryFactory({ WithControl });

How is this guide?

最終更新日