Storybook 实时示例插件

Storybook 实时示例插件

在 Github 上查看
  • 🧑‍💻 在没有像 Codepen 这样的第三方服务的情况下玩代码
  • 👥 与他人分享示例
  • 🐛 与他人分享错误复现的链接
  • 🧱 检查组件如何协同工作
  • 支持 Typescript

阅读文档尝试实时演示

入门

1. 安装附加组件

yarn add -D storybook-addon-live-examples
# npm install --save-dev storybook-addon-live-examples

2. 在 main.js 中注册附加组件

module.exports = {
    addons: ['storybook-addon-live-examples'],
};

3. 在 preview.js 中设置附加组件(可选步骤)

import { addons } from '@storybook/addons';
import { LIVE_EXAMPLES_ADDON_ID } from 'storybook-addon-live-examples';
import theme from 'prism-react-renderer/themes/github';

import AllComponents from '../packages';

addons.setConfig({
    [LIVE_EXAMPLES_ADDON_ID]: {
        // custom theme from prism-react-renderer (optional)
        editorTheme: theme,
        // internationalization (optional)
        copyText: ['Copy', 'Copied'],
        expandText: ['Show code', 'Hide code'],
        shareText: ['Share', 'Shared'],
        // scope (globally accessible components & functions) (optional)
        scope: {
            ...AllComponents,
            someFunction: () => 42
        },
    },
});

4. 配置 webpack(仅适用于 storybook 7)

const { patchWebpackConfig } = require('storybook-addon-live-examples/dist/cjs/utils');

module.exports = {
    webpackFinal: (config) => {
        patchWebpackConfig(config);
        
        return config;
    }
};

用法

CSF

将渲染实时示例而不是默认的 addon-docs 画布。

您可以通过参数自定义示例

export default {
    title: 'Components/Button',
    parameters: {
        scope: {
            scopeValue,
        },
    }
};

const scopeValue = 42;

export const Primary = () => <button>{scopeValue}</button>;

Primary.parameters = {
    expanded: true
};

export const Secondary = () => <button>{scopeValue}</button>;

注意:安装附加组件后,您很可能会遇到错误。不要惊慌,只需将故事中使用的所有变量传递到范围

MDX

在基于 MDX 的故事中,您可以使用纯 Markdown 编写代码示例。

只需将代码放在三个引号内

|```tsx live
|<h4>Wow, so simple</h4>
|```

或渲染自定义画布

// Import custom Canvas from addon
import { Canvas } from 'storybook-addon-live-examples';

<Canvas live={true} scope={{ value: 42 }}>
    <h4>Wow, so simple, {value}</h4>
</Canvas>

或直接使用示例

import { Example } from 'storybook-addon-live-examples';

<Example live={true} code={`<h4>Wow, so simple</h4>`} />

带有 MDX 的 CSF

// Button.stories.js

import mdx from './Button.mdx';

export default {
    title: 'Components/Button',
    parameters: {
        docs: {
            page: mdx,
        },
    },
};

const scopeValue = 42;

export const Primary = () => <button>{scopeValue}</button>;

Primary.parameters = {
    scope: {
        scopeValue,
    },
};
// Button.mdx

import { ArgsTable, Story } from '@storybook/addon-docs';

import { Button } from './Button';

# Button

<ArgsTable of={Button} />

<Story id='components-button--primary' />

示例道具

您可以使用道具或元字符串自定义示例的显示

live

|```tsx live
|<span>This example can be edited</span>
|```
<span>This example can be edited</span>

expanded

|```tsx live expanded
|<span>This example will be rendered with expanded code sources</span>
|```
<span>This example will be rendered with expanded code sources</span>

复杂示例

render(() => {
    const [counter, setCounter] = React.useState(0);
    return (
        <>
            <h2>Super live counter: {counter}</h2>
            <button type='button' onClick={() => setCounter((c) => c + 1)}>
                Increment
            </button>
        </>
    );
});

范围

Storybook-addon-live-examples 在幕后使用 react-live

范围允许您将一些全局变量传递给您的代码示例。默认情况下,它只注入 React,这意味着您可以像这样在代码中使用它

render(() => {
//                                ↓↓↓↓↓
    const [counter, setCounter] = React.useState(0);
    return counter;
}

- 通过道具将您自己的组件传递到范围

import { Canvas } from 'storybook-addon-live-examples';
import MyComponent from '../packages/my-component';

<Canvas live={true} scope={{ MyComponent }}>
    <MyComponent>Amazing</MyComponent>
</Canvas>

- 全局设置范围

这是为整个项目设置一次范围的最简单方法

//.storybook/manager.js

import { addons } from '@storybook/addons';
import { LIVE_EXAMPLES_ADDON_ID } from 'storybook-addon-live-examples';

addons.setConfig({
    [LIVE_EXAMPLES_ADDON_ID]: {
        scope: {
            MyComponent,
        },
    },
});
<MyComponent>Now, you can use MyComponent in all examples</MyComponent>

- 在单体仓库中设置范围

这是一个示例,说明如何将所有使用的组件和辅助函数添加到范围。

// .storybook/scope.ts

import { ComponentType } from 'react';

import * as icons from 'some-icons-pack';
import * as knobs from '@storybook/addon-knobs';

// packages/{componentName}/index.ts
const req = require.context('../packages', true, /^\.\/(.*)\/index.ts$/);

const components = req.keys().reduce((acc: Record<string, ComponentType>, key) => {
    Object.entries(req(key)).forEach(([componentName, component]: [string, any]) => {
        acc[componentName] = component;
    });

    return acc;
}, {});

export default {
    ...components,
    ...icons,
    ...knobs,
};

// .storybook/manager.js

import scope from './scope';

addons.setConfig({
    [LIVE_EXAMPLES_ADDON_ID]: {
        scope,
    },
});