介绍
组件开发环境,可以更直观、无依赖地开发和展示组件
Writing Stories
一个组件对应一个story
a story is a function that returns something that can be rendered to screen.
import React from 'react';
import { action } from '@storybook/addon-actions';
import Button from './Button';
export default {
component: Button, // 组件
title: 'Button', // storybook启动后界面左边展示地文案
};
export const text = () => <Button onClick={action('clicked')}>Hello Button</Button>;
export const emoji = () => (
<Button onClick={action('clicked')}>
<span role="img" aria-label="so cool">
😀 😎 👍 💯
</span>
</Button>
);
Story file location
- 组件文件同一路径
- src同路径
Loading stories
Stories are loaded in the .storybook/main.js file or .storybook/preview.js file.
- 通过文件名引入stories(如果你的stories文件放在src/components文件下,你可以使用下面方式引用)
// .storybook/main.js
module.exports = {
stories: ['../src/components/**/*.stories.js'],
};
- 你也可以在 .storybook/preview.js中引入所有的stories
import { configure } from '@storybook/react';
configure(require.context('../src/components', true, /\.stories\.js$/), module);
如果stories放在多个路径,可以使用数组
import { configure } from '@storybook/react';
configure(
[
require.context('../src/components', true, /\.stories\.js$/),
require.context('../lib', true, /\.stories\.js$/),
],
module
);
枚举引入
import { configure } from '@storybook/react';
const loaderFn = () => [
require('./welcome.stories.js'),
require('./prelude.stories.js'),
require('./button.stories.js'),
require('./input.stories.js'),
];
configure(loaderFn, module);
混合引入
import { configure } from '@storybook/react';
const loaderFn = () => {
const allExports = [require('./welcome.stories.js')];
const req = require.context('../src/components', true, /\.stories\.js$/);
req.keys().forEach(fname => allExports.push(req(fname)));
return allExports;
};
configure(loaderFn, module);
If you are using the storiesOf API directly, or are using @storybook/react-native where CSF is unavailable, you should use a loader function with no return value:
import { configure } from '@storybook/react';
const loaderFn = () => {
// manual loading
require('./welcome.stories.js');
require('./button.stories.js');
// dynamic loading, unavailable in react-native
const req = require.context('../src/components', true, /\.stories\.js$/);
req.keys().forEach(fname => req(fname));
};
configure(loaderFn, module);
Decorators
- global decorator : applied in the Storybook config files
// .storybook/preview.js:
import React from 'react';
import { addDecorator } from '@storybook/react';
addDecorator(storyFn => <div style={{ textAlign: 'center' }}>{storyFn()}</div>);
- component/local decorators
import React from 'react';
import MyComponent from './MyComponent';
export default {
title: 'MyComponent',
decorators: [storyFn => <div style={{ backgroundColor: 'yellow' }}>{storyFn()}</div>],
};
export const normal = () => <MyComponent />;
export const special = () => <MyComponent text="The Boss" />;
special.story = {
decorators: [storyFn => <div style={{ border: '5px solid red' }}>{storyFn()}</div>],
};