- 🧑💻 在没有像 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,
},
});