Storybook


Let's create a Storybook for the custom Button component that we created in the previous section. Storybook allows us to build a library of interactive UI components. Here's how we can set it up:

First, we need to open our Storybook server by running the following command: yarn workspace YOUR_WORKSPACE storybook:dev

  1. Create a Button story: Inside the /components/elements/button directory, create a new file called Button.stories.js.
Remember, It's a good practice to name your element's story file with the format ELEMENT_NAME.stories.js.
  1. Define the Button story: In Button.stories.js, import React and the Button component. Then, create a new Storybook story for the Button:

button/Button.stories.jsx

import React from "react"
import { Button } from "./Button"
const Template = (args) => {
return <Button {...args}></Button>
}
  • We defined a template function called Template that takes an args object as its argument. The Template function returns the Button component with the spread operator ({...args}) to pass any arguments received from Storybook to the Button component.

button/Button.stories.jsx

import React from "react"
import { Button } from "./Button"
const Template = (args) => {
return <Button {...args}></Button>
}
export const ButtonStories = Template.bind({})
  • This line exports a named export ButtonStories which is bound to the Template function, allowing it to be rendered and displayed by Storybook.

button/Button.stories.jsx

import React from "react"
import { Button } from "./Button"
const Template = (args) => {
return <Button {...args}></Button>
}
export const ButtonStories = Template.bind({})
ButtonStories.argTypes = {
variant: {
defaultValue: "primary",
control: { type: "select" },
options: ["primary", "secondary"],
},
}
  • This code block defines the argument types argTypes for the ButtonStories story. In this case, it sets up the variant argument to have a default value of primary and provides a select control in Storybook with options for primary and secondary.

button/Button.stories.jsx

import React from "react"
import { Button } from "./Button"
const Template = (args) => {
return <Button {...args}></Button>
}
export const ButtonStories = Template.bind({})
ButtonStories.argTypes = {
variant: {
defaultValue: "primary",
control: { type: "select" },
options: ["primary", "secondary"],
},
}
// eslint-disable-next-line
export default {
title: "Primitives/Button",
}
  • This line exports a default export (required by Storybook) that configures the story's title. In this case, the title is set to "Primitives/Button", indicating that this story belongs to the Primitives category in Storybook and specifically showcases the Button component.

Overall, this code defines a Storybook story for the Button component, specifying the template, argument types, and other configuration options. It allows the Button component to be rendered and interacted with in the Storybook UI, providing a convenient way to develop, showcase, and test components in isolation.

  1. Share the source code: Now that we have created the Button story, let's make the source code available to other users.
  • Importing the Button component's source code as a string using the raw-loader and assigns it to the ButtonCode variable.

button/Button.stories.jsx

import React from "react"
import { Button } from "./Button"
import ButtonCode from "!!raw-loader!./Button"
const Template = (args) => {
return <Button {...args}></Button>
}
export const ButtonStories = Template.bind({})
ButtonStories.argTypes = {
variant: {
defaultValue: "primary",
control: { type: "select" },
options: ["primary", "secondary"],
},
}
// eslint-disable-next-line
export default {
title: "Primitives/Button",
}
  • Including the componentSource parameter in the story's configuration. This parameter is used to provide the source code for the component associated with the story.

button/Button.stories.jsx

import React from "react"
import { Button } from "./Button"
import ButtonCode from "!!raw-loader!./Button"
const Template = (args) => {
return <Button {...args}></Button>
}
export const ButtonStories = Template.bind({})
ButtonStories.argTypes = {
variant: {
defaultValue: "primary",
control: { type: "select" },
options: ["primary", "secondary"],
},
}
// eslint-disable-next-line
export default {
title: "Primitives/Button",
parameters: {
componentSource: {
code: ButtonCode,
language: "javascript",
},
},
}

And voila! Now your source code is available within the Button story, as you can see in the image below.

⚠️
Don't forget to run `yarn workspace YOUR_WORKSPACE storybook:build` to check for any warnings or errors, And don't forget to fix them

By importing the source code in this way, you can access the code programmatically, allowing for various use cases such as displaying the code in documentation, generating code snippets, or even performing code analysis or transformations.