This storybook addon allows you to automatically display pseudo states (and attribute states) of a component in Storybook's preview area.
| Framework | Display States | Tool-Button to show/hide |
|---|---|---|
| Angular | + | + |
| React | + | + |
| Lit | + | + |
| HTML | + | + |
| Vue | + | + |
First, add the addon to your project as a dev dependency:
npm install @ergosign/storybook-addon-pseudo-states-vue --save-devNext, enable it by adding it as an addon to .storybook/main.js, e.g.
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@ergosign/storybook-addon-pseudo-states-vue',
],
};Since there's no way to force an element to appear with a specific pseudo state, the addon relies on specific classes to simulate the state. The Styling section explains how to generate them.
Once that's done, you can add the decorator to a story, as explained in Usage.
The recommended approach is to generate classes from your pseudo state CSS rules automatically. The easiest way is to use the postcss-pseudo-classes PostCSS plugin.
npm i -D postcss-pseudo-classesThen add it to your postcss.config.js:
module.exports = {
plugins: [require('postcss-pseudo-classes')],
};postcss-pseudo-classes extracts all pseudo states from your styling and creates a class for each of them by adding a prefix, e.g. button:hover {} becomes button.\:hover {}. The default prefix is \:, and storybook-addon-pseudo-states-vue is configured to work with that configuration. If you need a different prefix, pass it to the plugin options:
module.exports = {
plugins: {
'postcss-pseudo-classes': {
prefix: 'pseudoclass--',
},
},
};And update your story config accordingly (more on configuring stories below):
{
parameters: {
withPseudo: {
selector: "element",
prefix: "pseudoclass--"
},
},
};If you're unsure about how to set up PostCSS, you can check out the Vue CLI or PostCSS docs.
Alternatively, you can code the pseudo state classes manually. The naming pattern is prefix + pseudostate. With the default \: prefix, it would look something like this:
.element {
// ...
&:hover,
&\:hover {
// hover styling
}
&:focus,
&\:focus {
// focus styling
}
}You can enable a toolbar button that toggles the pseudo states in the preview area. See framework support for information on which frameworks support this feature.
Enable the button by adding it to your .storybook/main.js file:
module.exports = {
addons: ['@ergosign/storybook-addon-pseudo-states-vue'],
};
⚠️ withPseudoshould always come first in yourdecoratorsarray because it alters the template of the story.
import { withPseudo } from '@ergosign/storybook-addon-pseudo-states-vue';
const section = {
title: 'Button',
decorators: [withPseudo],
parameters: {
withPseudo: { selector: 'button' },
},
};
export default section;
export const Story = () => {
return {
component: ButtonComponent,
};
};import { withPseudo } from '@ergosign/storybook-addon-pseudo-states-vue';
storiesOf('Button', module)
.addDecorator(withPseudo)
.addParameters({
withPseudo: {
selector: 'button', // css selector of pseudo state's host element
pseudo: ['focus', 'hover', 'hover & focus', 'active'],
attributes: ['disabled', 'readonly', 'error'],
},
})
.add('Icon Button', () => <Button />);There is a default configuration for selector, pseudos and attributes. Thus, you can leave withPseudo options empty.
import { withPseudo } from '@ergosign/storybook-addon-pseudo-states-vue';
import { PseudoStateOrderDefault } from '@ergosign/storybook-addon-pseudo-states-vue/dist/share/types';
import SimpleButton from '../components/SimpleButton.vue';
export default {
title: 'Simple Button',
decorators: [withPseudo],
parameters: {
withPseudo: {
pseudo: PseudoStateOrderDefault,
attributes: ['disabled', { attr: 'appearance', value: 'primary' }],
},
},
argTypes: {
appearance: {
control: false,
},
},
};
const template = (args, { argTypes }) => ({
components: { SimpleButton },
props: Object.keys(argTypes),
template: '<simple-button :label="label" :disabled="disabled" />',
});
export const PseudoStates = template.bind({});
PseudoStates.args = {
label: 'Hello World',
disabled: false,
appearance: false,
};See types.ts
- Vue 2.x support/not tested with Vue 3
- Broken in docs view