npm init stencil
Answer this way
✔ Pick a starter > component
✔ Project name > storybook-wc-stencil
cd storybook-wc-stencil
yarn install
Add skipLibCheck property to exclude node_modules code
tsconfig.json
{
"compilerOptions": {
...
"skipLibCheck": true,
},
...
src/typings.d.ts
declare module '*.jpg';
declare module '*.md' {
const value: string; // markdown is just a string
export default value;
}
declare module '*.css' {
const content: { [className: string]: string };
export default content;
}
npx -p @storybook/cli sb init --type html
yarn add -D @storybook/addon-notes
.storybook/main.js
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-notes',
],
framework: '@storybook/html',
};
.storybook/preview.js
import { defineCustomElements } from '../dist/esm/loader';
defineCustomElements();
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
Let's remove all content from stories directory
Create a new file called my-component.stories.tsx inside src/stories directory
Your project structure should look like this
./storybook-wc-stencil/
|
|---- .storybook/
| |---- main.js
| |---- preview.js
|---- src/
| |---- components/
| | |---- my-component/
| | |---- my-component.css
| | |---- my-component.e2e.ts
| | |---- my-component.spec.ts
| | |---- my-component.tsx
| | |---- readme.md
| |---- stories/
| |---- components/
| |---- my-component.stories.tsx
|---- .editorconfig
|---- .gitignore
|---- .prettierrc.json
|---- LICENSE
|---- package.json
|---- readme.md
|---- stencil.config.ts
|---- tsconfig.json
|---- yarn.lock
We can use the next command to automatically generate our components on our components directory
yarn generate component-name
For having hot reload, we must execute this two commands in parallel, so we can use two terminals or create a new script
yarn build -- --watch
yarn storybook
We are going to face some disadvantages when working storybook with stencil
- We need to define properties that we want to use in controls
- We need to define default props for controls
- We need to add description and prop types for Docs pages
- defaultValue property is not working for Doc pages
- We need to pass args values on the template
// This md file is generated by stencil, and we are going to use it as a note page
import notes from '../../components/my-component/readme.md';
export default {
title: 'UI/My Component',
args: {
// Here we define default values that we want to show on controls
// Also, only props defined here are going to be shown
first: 'Juan Fernando',
middle: 'Gómez',
last: 'Maldonado',
},
argTypes: {
// Here we can add description and prop value type
first: {
description: 'First name',
// First way to define type
table: {
type: {
summary: 'string',
},
},
},
middle: {
// Second and shorter way to define type
type: {
summary: 'string',
},
},
last: {
// We can disable the property
// This will hide it in controls and Doc page
table: {
disable: true,
},
},
},
parameters: {
// This will create a note page for our story component
notes,
},
};
const Template = args =>
`<my-component first="${args.first}" middle="${args.middle}" last="${args.last}"></my-component>`;
export const Basic = Template.bind({});
export const Another = Template.bind({});
Another.args = {
first: 'John',
};
We are going to use the library story-wc-generator to generate args, argTypes and the template.
yarn add story-wc-generator
import notes from '../../components/cool-button/readme.md';
import storyGenerator from 'story-wc-generator';
const { args, argTypes, Template } = storyGenerator('cool-button', {
text: { value: 'Click me!', description: 'Text label', type: 'string' },
color: {
value: 'primary',
description: 'Color of button',
control: 'select',
options: ['primary', 'secondary', 'dark'],
type: 'primary | secondary | dark',
},
});
export default {
title: 'UI/Cool Button',
args,
argTypes,
parameters: {
notes,
},
};
export const Primary = Template.bind({});
export const Secondary = Template.bind({});
Secondary.args = {
color: 'secondary',
};
...
This example includes all properties that can be used, but you can go to the documentation for more description about the library
The previous implementation will give us stories with controls and documentation
Also, Stencil generates readme files for each component, so thanks to the notes addon we can use that readme as a new page for more specifications about the component.