Documentação de componentes em React com Typescript usando Storybook (versão 8)
Introdução English version: Documentation of components in React with TypeScript using Storybook (version 8) Anteriormente escrevi em um artigo sobre a documentação de componentes usando storybook, quando a versão estava abaixo da 8. Devido a algumas mudanças que vieram com essa versão e ter me aprofundado mais com a lib, estou escrevendo uma versão atualizada nesse artigo. Storybook é uma ferramenta que permite, dentre outras coisas, documentar componentes de forma isolada paralelamente à aplicação. Nesse artigo, vou apresentar uma forma de customização da documentação de componentes, que espero que auxilie a dar visibilidade a algumas opções dentre várias disponíveis usando essa lib. Será seguido as seguintes etapas: setup: configuração do storybook stories: definição dos principais cenários dos componentes a serem documentados mdx: documentação dos componentes, trazendo as customizações definidas nos stories exemplo: vai ser apresentado um exemplo de documentação de um componente Cada componente terá seu próprio arquivo mdx e de stories. Setup Para adicionar o storybook em uma aplicação com React, com as configurações iniciais, é necessário executar no terminal: npx storybook init. Esse comando vai detectar as dependências do projeto e pode apresentar algumas perguntas durante o processo. Alguns exemplos: se está usando webpack ou vite no projeto se é para documentação ou testes No caso seria escolher a que corresponde ao seu projeto e no contexto de documentação, informar isso quando perguntar. Observação: algumas libs usam o rollup ao invés de vite e webpack, em uma lib que uso para estudo, que usa rollup, escolhi a opção do vite e funciona bem, mas precisa adicionar duas novas libs: yarn add vite @storybook/builder-vite --dev Stories Para cada componente vai ser definido um arquivo *.stories.tsx, onde será definido os cenários de customização mais importantes a serem documentados, seguindo a seguinte estrutura: import React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import Component from "./Component"; const meta: Meta = { title: "Component", component: Component, argTypes: {}, }; export default meta; type Story = StoryObj; export const Default: Story = { args: {}, render: (args) => ( ), }; export const Scenario1: Story = { args: {}, render: (args) => ( ), }; // Scenario2 // Scenario3 Dos imports do @storybook/react: Meta: define a metadata do componente a ser documentado, nesse caso está se passando o componente em si em component e o título que vai parecer no menu lateral em title StoryObj: permite definir os cenários de customização do componente a serem exibidos na documentação, que corresponde as definições de Default, Scenario1, Scenario2... acima Para cada cenário definido, vai ser criado uma entrada no menu lateral, dentro da "pasta" com o nome definido no title de Meta, com a seguinte estrutura: Component Default Scenario1 Scenario2 Scenario3 Em Default é renderizado o componente com as propriedades default dele. Em args: {} do Scenario1 acima não foi passado nenhuma props, com o objetivo de trazer na primeira renderização do componente uma base com o comportamento default dele. Já nas duas outras renderizações do Scenario1 é variada a props props1, onde o objetivo desse cenário é mostrar na documentação o que acontece com o componente ao mudar essa props. MDX Vai ser a documentação do componente, onde vai ser trazido os cenários presentes no arquivo de *.stories.tsx e definido textos para explicar as principais funcionalidades do componente, seguindo a seguinte estrutura: import { Canvas, Controls, Meta, Story } from '@storybook/blocks'; import * as Stories from './Component.stories'; # Component Descrição do Component. ## Predefined properties ### Scenario 1 Descrição do uso da props1. ## Custom properties // ### Scenario 2 // ### Scenario 3 É um arquivo mix de markdown com javascript. Dos imports do @storybook/blocks: Canvas: vai criar uma caixa onde os componentes do cenário a ser puxado do arquivo *.stories estarão presentes, que possui uma opção chamada Show code que mostra o código para usar o componente mostrado: Controls: vai trazer uma tabela com o nome de todas as props disponíveis pelo componente, a descrição delas (trazendo os types das props), se tem um valor default e um lugar onde pode ser mexida as props do componente para visualizar as mudanças que acontecem. Colocando em conjunto: Está se definindo que o Controls vai impactar o componente que vem de Stories.Default e acima está se trazendo ele , então a cada mudança de props vai dar para ver como o componente vai sendo customizado: Meta: define onde está o arquivo de stories associado a documentação, que vem do import import * as Stories from './Component.stories'; Exemplo Vou apresentar um exemplo sim

Introdução
English version: Documentation of components in React with TypeScript using Storybook (version 8)
Anteriormente escrevi em um artigo sobre a documentação de componentes usando storybook, quando a versão estava abaixo da 8. Devido a algumas mudanças que vieram com essa versão e ter me aprofundado mais com a lib, estou escrevendo uma versão atualizada nesse artigo.
Storybook é uma ferramenta que permite, dentre outras coisas, documentar componentes de forma isolada paralelamente à aplicação.
Nesse artigo, vou apresentar uma forma de customização da documentação de componentes, que espero que auxilie a dar visibilidade a algumas opções dentre várias disponíveis usando essa lib. Será seguido as seguintes etapas:
- setup: configuração do storybook
- stories: definição dos principais cenários dos componentes a serem documentados
- mdx: documentação dos componentes, trazendo as customizações definidas nos stories
- exemplo: vai ser apresentado um exemplo de documentação de um componente
Cada componente terá seu próprio arquivo mdx
e de stories
.
Setup
Para adicionar o storybook em uma aplicação com React, com as configurações iniciais, é necessário executar no terminal: npx storybook init
.
Esse comando vai detectar as dependências do projeto e pode apresentar algumas perguntas durante o processo. Alguns exemplos:
- se está usando
webpack
ouvite
no projeto - se é para documentação ou testes
No caso seria escolher a que corresponde ao seu projeto e no contexto de documentação, informar isso quando perguntar.
Observação: algumas libs usam o rollup
ao invés de vite
e webpack
, em uma lib que uso para estudo, que usa rollup
, escolhi a opção do vite
e funciona bem, mas precisa adicionar duas novas libs:
yarn add vite @storybook/builder-vite --dev
Stories
Para cada componente vai ser definido um arquivo *.stories.tsx
, onde será definido os cenários de customização mais importantes a serem documentados, seguindo a seguinte estrutura:
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import Component from "./Component";
const meta: Meta<typeof Component> = {
title: "Component",
component: Component,
argTypes: {},
};
export default meta;
type Story = StoryObj<typeof Component>;
export const Default: Story = {
args: {},
render: (args) => (
<Component {...args} />
),
};
export const Scenario1: Story = {
args: {},
render: (args) => (
<>
<Component {...args} />
<Component {...args} props1="option1" />
<Component {...args} props1="option2" />
</>
),
};
// Scenario2
// Scenario3
Dos imports do @storybook/react
:
- Meta: define a metadata do componente a ser documentado, nesse caso está se passando o componente em si em
component
e o título que vai parecer no menu lateral emtitle
- StoryObj: permite definir os cenários de customização do componente a serem exibidos na documentação, que corresponde as definições de
Default
,Scenario1
,Scenario2
... acima
Para cada cenário definido, vai ser criado uma entrada no menu lateral, dentro da "pasta" com o nome definido no title
de Meta
, com a seguinte estrutura:
- Component
- Default
- Scenario1
- Scenario2
- Scenario3
Em Default
é renderizado o componente com as propriedades default dele.
Em args: {}
do Scenario1
acima não foi passado nenhuma props, com o objetivo de trazer na primeira renderização do componente uma base com o comportamento default dele.
Já nas duas outras renderizações do Scenario1
é variada a props props1
, onde o objetivo desse cenário é mostrar na documentação o que acontece com o componente ao mudar essa props.
MDX
Vai ser a documentação do componente, onde vai ser trazido os cenários presentes no arquivo de *.stories.tsx
e definido textos para explicar as principais funcionalidades do componente, seguindo a seguinte estrutura:
import { Canvas, Controls, Meta, Story } from '@storybook/blocks';
import * as Stories from './Component.stories';
<Meta of={Stories} />
# Component
Descrição do Component.
<Canvas of={Stories.Default} withToolbar />
<Controls of={Stories.Default} />
## Predefined properties
### Scenario 1
Descrição do uso da props1.
<Canvas of={Stories.Scenario1} withToolbar />
## Custom properties
// ### Scenario 2
// ### Scenario 3
É um arquivo mix de markdown com javascript.
Dos imports do @storybook/blocks
:
- Canvas: vai criar uma caixa onde os componentes do cenário a ser puxado do arquivo
*.stories
estarão presentes, que possui uma opção chamadaShow code
que mostra o código para usar o componente mostrado:
- Controls: vai trazer uma tabela com o nome de todas as props disponíveis pelo componente, a descrição delas (trazendo os types das props), se tem um valor default e um lugar onde pode ser mexida as props do componente para visualizar as mudanças que acontecem. Colocando em conjunto:
<Canvas of={Stories.Default} withToolbar />
<Controls of={Stories.Default} />
Está se definindo que o Controls vai impactar o componente que vem de Stories.Default
e acima está se trazendo ele , então a cada mudança de props vai dar para ver como o componente vai sendo customizado:
- Meta: define onde está o arquivo de stories associado a documentação, que vem do import
import * as Stories from './Component.stories';
Exemplo
Vou apresentar um exemplo simples de documentação partindo do que foi passado acima.
Começando pela criação de um componente definido em Tag.tsx
:
import React from "react";
import styled from "styled-components";
export interface TagProps {
text?: string;
backgroundColor?: string;
type?: "default" | "success" | "alert" | "error";
}
export interface StyledTagProps {
$backgroundColor?: string;
$type?: "default" | "success" | "alert" | "error";
}
export const StyledTag = styled.div<StyledTagProps>`
border: none;
padding: 10px 12px;
background-color: ${(props) =>
props.$backgroundColor
? props.$backgroundColor
: props.$type === "error"
? "#e97451"
: props.$type === "alert"
? "#f8de7e"
: props.$type === "success"
? "#50c878"
: props.$type === "default"
&& "#d3d3d3"};
pointer-events: none;
border-radius: 5px;
width: fit-content;
`;
const Tag = ({
text="Tag",
backgroundColor,
type="default",
}: TagProps) => (
<StyledTag
$type={type}
$backgroundColor={backgroundColor}
>
<span>{text}</span>
</StyledTag>
);
export default Tag;
É um componente de Tag que tem uma propriedade predefinida type
, ou seja, a própria app define o css associado de acordo com o type passado. Podendo ser default
, error
, alert
e success
.
E uma propriedade customizável backgroundColor
, ou seja, customizável por quem está usando o componente, podendo escolher a cor que desejar.
No exemplo estou definindo o css a partir de uma lib chamada styled-components
, mas a documentação é indiferente a forma que o css é definido.
E é definido os Types tanto das props do componente em si, quanto a referente ao styled component.
Agora será criado um componente específico para documentação StorybookContainer
, que será responsável em centralizar dentro do Canvas
do arquivo mdx, os componentes do cenário a ser mostrado, com um pequeno espaçamento entre eles. No arquivo StorybookContainer.tsx
:
import React from "react";
import styled from "styled-components";
export interface StorybookContainerProps {
children: React.ReactNode;
}
export const StyledStorybookContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
`;
const StorybookContainer = ({ children }: StorybookContainerProps) => (
<StyledStorybookContainer>
{children}
</StyledStorybookContainer>
);
export default StorybookContainer;
Vai ser criado o arquivo Tag.stories.tsx
com o Default e os dois cenários a serem apresentados na documentação:
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import Tag from "./Tag";
import StorybookContainer from "../StorybookContainer/StorybookContainer";
const meta: Meta<typeof Tag> = {
title: "Tag",
component: Tag,
argTypes: {},
};
export default meta;
type Story = StoryObj<typeof Tag>;
export const Default: Story = {
args: {},
render: (args) => (
<StorybookContainer>
<Tag {...args} />
</StorybookContainer>
),
};
export const PredefinedType: Story = {
args: {},
render: (args) => (
<StorybookContainer>
<Tag {...args} />
<Tag {...args} type="success" />
<Tag {...args} type="alert" />
<Tag {...args} type="error" />
</StorybookContainer>
),
};
export const BackgroundColor: Story = {
args: {
backgroundColor: "#d3d3d3",
},
render: (args) => (
<StorybookContainer>
<Tag {...args} />
<Tag {...args} backgroundColor="#89cff0" />
<Tag {...args} backgroundColor="#f0aa89" />
</StorybookContainer>
),
};
Foram definidos dois cenários no arquivo, para mostrar como o componente muda com a variação da props type
(que é uma propriedade pre-definida na app) e como o componente muda com a variação da props backgroundColor
(que é uma propriedade customizável, pois o usuário pode passar a cor que quiser usar).
Por fim vai ser criado o arquivo da documentação do componente Tag.mdx
, onde vai ser mostrada os dois cenários definidos no arquivo de stories:
import { Canvas, Controls, Meta } from "@storybook/blocks";
import * as Stories from "./Tag.stories";
<Meta of={Stories} />
# Tag
Tag base component.
<Canvas of={Stories.Default} withToolbar />
<Controls of={Stories.Default} />
## Predefined properties
### Type
There are four predefined types: default, success, alert and error.
<Canvas of={Stories.PredefinedType} withToolbar />
## Custom properties
### Background Color
Tag background color can be modified.
<Canvas of={Stories.BackgroundColor} withToolbar />
Onde vai estar descrito o componente que está sendo mostrado, com uma tabela permitindo controlar as prop do componente logo acima dela devido a inclusão do
, onde vai ser mostrado um cenário de customização usando a variação da props type
(propriedade pre-definida) e vai ser mostrado um cenário usando a variação da props backgroundColor
(propriedade customizável).
Por fim, é executar no terminal yarn storybook
.
Ficando o menu lateral da seguinte forma:
E a documentação da seguinte forma:
Conclusão
A ideia desse artigo foi apresentar uma ferramenta de documentação de componentes que permite customizar a documentação usando um arquivo mdx de diversas formas, a partir de blocks
que a lib fornece. Foi apresentado um modo de escrita desse arquivo de documentação, mas dado a várias possibilidades que a lib fornece, vou colocar nas referências alguns links para quem quiser se aprofundar mais no assunto.
Referências
Stories File
Blocks
Controls Block
Canvas Block
Meta Block
Stories Block
MDX File