Automatically create stories for all your components and keep them up-to-date without any effort
Curently supports Vue and React projects
- Install Storybook as usual, make sure knobs addon is installed as well.
- Create stories.js file to configure storybook-automation package
- Configure storybook as usual, point it to load previously created stories.js file
- Start storybook as usual
- That's all, no matter what changes you do to your components, it will be automatically displayed in storybook
Moule exports only one method called generateStories()
, it takes an options object as only parameter. Possible options are:
- storiesOf - Storybook's function to generate stories (required | webpack's require context function)
- e.g.:
import { storiesOf } from "@storybook/vue"
- e.g.:
- filesContext - A context to all component files (required | webpack's require context function)
- e.g.:
require.context('../components/', true, /\.vue$/)
- e.g.:
- plugins - Object with vue's plugins used in your project (optional | Object)
- e.g.:
{ i18n: new VueI18n({})}
- e.g.:
- defineDefault - Function used to define default value for component's prop other than defined in your component (optional | Function)
- e.g.: Component defines prop
items: { type: Array, default: [] }
, but we want to display it as[{ title: 'Title 1' }, {title: 'Title 2' }]
- e.g.: Component defines prop
- defineEnum - Function used to define if commponent's prop should be displayed as dropdown (optional | Function)
- e.g.: Component defines props
size: { type: String, default: 'MEDIUM' }
. The types isstring
, but in reality it is enumerabletype = { SMALL: 'SMALL', MEDIUM: 'MEDIUM', LARGE: 'LARGE' }
- e.g.: Component defines props
There are many informations passed to these two methods to help you determine if
- some special default value shouuld be used
- prop value should be displayed as dropdown
Both functions receive optioons object as its only parameter. Passed informations are:
- componentName - name of component
- component - actual component object
- module - webpack module containing the component
- parent - compoonent's parent folder name
- propName - name of prop
- prop - prop definition (usually in format
{ type: String, default: '', required: false }
)
configure(loadStories, module)
### Basic Example
```javascript
// .storybook/stories.js
import { storiesOf } from "@storybook/vue"
import { generateStories } from 'storybook-automation'
generateStories({
storiesOf,
filesContext: require.context('../components/', true, /\.vue$/)
})
// .storybook/stories.js
import { storiesOf } from "@storybook/vue"
import { generateStories } from 'storybook-automation'
import VueI18n from 'vue-i18n'
generateStories({
storiesOf,
filesContext: require.context('../components/', true, /\.vue$/),
plugins: {
i18n: new VueI18n({})
}
})
Story for Component1.vue will be created with 2 knobs.
items
will use knob type array with 2 items insideactvieItem
will use knob type number with 0 set
// components/Component1/Component1.vue
export default class TheNavbar extends Vue {
@Prop({ type: Array, default: () => [] }) readonly items!: Array<string>
@Prop({ type: Number, default: 0 }) readonly activeItem!: number
}
// .storybook/stories.js
import { storiesOf } from "@storybook/vue"
import { generateStories } from 'storybook-automation'
generateStories({
storiesOf,
filesContext: require.context('../components/', true, /\.vue$/),
defineDefault: ((options) => {
if (options.propName === items) {
return ['Navbar Item 1', 'Navbar Item 2']
}
}
})
Story for Component1.vue will be created with 2 knobs.
type
will use knob type select with 3 options and SECONDARY selectedisEnabled
will use knob type boolean and it will be checked
// components/Component1/Component1.vue
export default class TheButton extends Vue {
@Prop({ type: String, default: TheButton.constants.TYPE.SECONDARY }) readonly type!: string
@Prop({ type: Boolean, default: true }) readonly isEnabled!: string
public static constants: { TYPE } = {
TYPE: {
PRIMARY: 'PRIMARY',
SECONDARY: 'SECONDARY',
TERTIARY: 'TERTIARY'
}
}
}
// .storybook/stories.js
import { storiesOf } from "@storybook/vue"
import { generateStories } from 'storybook-automation'
generateStories({
storiesOf,
filesContext: require.context('../components/', true, /\.vue$/),
defineEnum: ((options) => {
const constName = options.propName.toUpperCase()
return options.component.constants
? options.component.constants[constName]
: undefined
}
})
Story for Component1.jsx will be created with 2 knobs.
type
will use knob type select with 3 options and SECONDARY selectedisEnabled
will use knob type boolean and it will be checked
// components/Component1/ComponentTypes.js
export const ButtonTypes = Object.freeze({
PRIMARY: "PRIMARY",
SECONDARY: "SECONDARY"
});
// components/Component1/Component1.jsx
import { ButtonTypes, ButtonSizes } from "./Component1Types";
export default class Button extends Component {}
Button.propTypes = {
type: PropTypes.oneOf(Object.values(ButtonTypes)),
disabled: PropTypes.bool,
size: PropTypes.oneOf(Object.values(ButtonSizes)),
};
Button.defaultProps = {
type: ButtonTypes.PRIMARY,
disabled: false,
size: ButtonSizes.MEDIUM
};
// .storybook/stories.js
import { storiesOf } from "@storybook/vue"
import { generateStories } from 'storybook-automation'
import { ButtonTypes, ButtonSizes } from "../src/Component1Types";
const ButtonEnums = {
type: ButtonTypes,
size: ButtonSizes
}
generateStories({
storiesOf,
filesContext: require.context('../components/', true, /\.jsx$/),
defineEnum: (options) => {
if (options.componentName === 'Component1')
return ButtonEnums[options.propName]
}
})