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
- Create a Button story: Inside the
/components/elements/button
directory, create a new file calledButton.stories.js
.
- 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-lineexport 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.
- 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-lineexport 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-lineexport 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.
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.