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

May 16, 2025 - 23:12
 0
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<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 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';

<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 chamada Show code que mostra o código para usar o componente mostrado:

Image description

  • 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:

Image description

  • 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:

Image description

E a documentação da seguinte forma:

Image description

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