< voltar para todos artigos
Criando uma lib de componentes React, Parte 1

Introdução ao projeto, criação do repositório no github e a instação e configuração do storybook

Nessa série de posts iremos criar uma biblioteca de componentes bem completa! Criaremos desde o repositório no github até a publicação automatizada no NPM via TravisCI.

Iremos abordar assuntos como:

  • Tematização;
  • Tree-shaking;
  • Versionamento;
  • Estrutura;
  • CSS-in-JS;
  • Linter;
  • Testes;
  • Deploy;
  • CI/CD;
  • Padronização de commits
  • etc…

Também conheceremos algumas ferramentas para nos ajudar com o desenvolvimento, build e deploy. Como por exemplo:

Criando repositório no GitHub

Por mais simples que seja, precisamos começar criando o repositório de nossa biblioteca no github. Primeiramente você precisa ter um usuário no github, se ainda não tiver, vá criar agora! (https://github.com/join).

Após logado, crie um novo repositório, escolha o nome da sua biblioteca, no meu caso, será “frigobar”. Coloque também uma descrição para o projeto, escolha se é privado ou público (é claro que será público, né? você usa trocentos projetos open-source, porque sua biblioteca não seria??). É bom já iniciar com um README.md, um .gitignore e adicionar uma licença, e é claro que será MIT.

Imagem do formulário de novo projeto do github preenchido

Após criado, clone seu projeto!

Imagem do pop-over para clonar o projeto do github

git clone [email protected]:SEU-USUARIO/SEU-PROJETO.git

Percebeu que ele veio com o .gitignore, README.md e LICENSE? Foi porque selecionamos no formulário do github. O .gitignore já vem preenchido com alguns arquivos comumente ignorados para a stack de node, ele já contempla todos os arquivos que precisaremos ignorar, como por exemplo, node_modules, yarn-error, etc.

Pronto! já temos nosso repositório criado e clonado em nossa máquina.

Iniciando o desenvolvimento

Primeiramente, iremos criar nosso package.json. Para isso, abra o terminal e vá até a pasta do seu projeto que você clonou. Rode npm init, responda as perguntas, (o test command pode ficar em branco mesmo). No meu caso ficou assim:

Imagem CLI do npm init Isso irá gerar nosso package.json.

Agora vamos instalar nossas primeiras dependências para criação de nossa biblioteca. Primeiramente, vamos instalar o react e o react-dom.

npm install react react-dom

Após a instalação, as duas dependências serão adicionadas no package.json:

Imagem do package.json mostrando o react e react-dom como dependências

Mais pra frente veremos que o react e o react-dom não devem ficar nesse nó de dependencies no package.json.

Storybook

Agora, pra gente não precisar criar uma aplicação pra conseguir visualizar os componentes que iremos criar, e também pra dar um certo tipo de documentação pra quem quiser visualizar quais componentes nossa lib disponibiliza, iremos utilizar o Storybook. Ele é uma ferramenta para desenvolver componentes visuais em React, Vue e Angular, ele mantém a visualização de seus componentes organizada e eficiente.

Essa é a cara do storybook:

Imagem da interface do storybook

Pra gente instalar, basta rodar:

npx -p @storybook/cli sb init

A instalação do Storybook vai detectar que estamos utilizando React e vai instalar a versão pro framework/lib correto. Após o término da instalação vamos rodar:

npm run storybook

E se tudo der certo vamos ver a mensagem para acessar nosso storybook local:

Imagem da mensagem de que o storybook esta rodando

Acessando https://localhost:6006/ veremos o nosso próprio storybook!

Imagem do storybook local

Perceba que o storybook criou alguns arquivos no root do projeto:

├── .gitignore
├── LICENSE
├── package.json
├── package-lock.json
├── README.md
├── stories /* Essa*/
│ ├── 0-Welcome.stories.js
│ └── 1-Button.stories.js
└── .storybook /* E essa */
└── main.js

A pasta stories é a pasta default onde o storybook procura suas histórias. Uma história geralmente é a representação de um estado de um componente, perceba também que já temos duas histórias nesta pasta, vamos analisar o conteúdo do 0-Welcome.stories.js.

Vamos dar uma olhada no que é importado dentro do arquivo:

/* 0-Welcome.stories.js */
import React from 'react';
import { linkTo } from '@storybook/addon-links';
import { Welcome } from '@storybook/react/demo';

linkTo

Como você pode perceber, o linkTo está sendo importado como addon, o storybook possui vários addons para dar algumas funcionalidades a mais à sua história, você pode conferir alguns no próprio site do storybook.

Welcome

É um componente React comum, está ali apenas para popular a história que vem por padrão.

Agora vamos analisar o código que está gerando o que vemos na tela:

export default {
title: 'Welcome',
component: Welcome,
};
export const ToStorybook = () => <Welcome showApp={linkTo('Button')} />;
ToStorybook.story = {
name: 'to Storybook',
};

Essa é a forma que se escreve as histórias do storybook, o nome desse formato se chama Component Story Format (CSF) é a forma recomendada pelo storybook de se escrever stories.

No CSF as stories e os componentes são definidos como ES Modules, cada arquivo de story necessita ter um export default e um ou mais named exports, no caso acima, nosso named export é a const ToStorybook que estamos exportando.

Export default

O export default define dados sobre o seu componente, incluindo o componente em sí, e também o título do grupo das histórias que será exibido no menu lateral do storybook.

Não é obrigatório definir o componente, porém, é recomendado que faça. Essa propriedade component do export default pode ser usada em addons para exibir informações do componente, como por exemplo, uma tabela de props.

O título é exibido no grupo de histórias na barra lateral do storybook. Ele deve ser único. Esse grupo de histórias também é comumente chamado de kind.

Repare também que estamos adicionando uma propriedade que é um objeto chamado story ao nosso ToStorybook. Essa propriedade é um objeto que contém name. Esse nome é o nome da história do componente ToStorybook.

Não necessáriamente precisamos dessa propriedade name. Por padrão o storybook nomeia suas histórias baseadas no named export, ou seja, se retirarmos o name do ToStorybook.story, por exemplo:

export default {
title: 'Welcome',
component: Welcome,
};
export const ToStorybook = () => <Welcome showApp={linkTo('Button')} />;
// ToStorybook.story = {
// name: 'to Storybook',
// };

O nome de nossa história será “To Storybook” (pois está pegando o nome do export) e não mais “to Storybook” (com “t” minúsculo), como quando utilizavamos a propriedade name.

Imagem da história com titulo alterado

Como você pode perceber, a nossa váriavel esta em PascalCase mas no storybook há um espaço separando as palavras, isso ocorre porque o storybook altera o nome antes de enviar para o menu, veja alguns exemplos:

name -> 'Name'
someName -> 'Some Name'
someNAME -> 'Some NAME'
some_custom_NAME -> 'Some Custom NAME'
someName1234 -> 'Some Name 1234'
someName1_2_3_4 -> 'Some Name 1 2 3 4'

Você pode utilizar o story.name quando quiser que o título contenha alguma palavra reservada do javascript, como por exemplo default, ou se quiser utilizar emojis.

Estrutura de uma história

Bom, para criar uma história basta seguir como no exemplo da história do Welcome. Edite a história que vem por default para ver os efeitos que são aplicados no storybook. O código editado deve ficar assim:

import React from 'react';
import { linkTo } from '@storybook/addon-links';
import { Welcome } from '@storybook/react/demo';
export default {
title: 'Bem vindo',
component: Welcome,
};
export const ToStorybook = () => <Welcome showApp={linkTo('Button')} />;
ToStorybook.story = {
name: 'ao Storybook',
};

Esse trecho de código editou o título do grupo de histórias do componente Welcome e o titulo da história ToStorybook.

A pasta .storybook

Você também deve ter percebido que surgiu uma pasta .storybook no seu projeto. As configurações de carregamento das stories, addons e webpack ficam aqui. O storybook possuí um webpack por baixo dos panos, caso você queira editar alguma configuração, basta editar o arquivo main.js dessa pasta e sobrescrever o que necessita ser alterado. Você pode ver melhor aqui: https://storybook.js.org/docs/configurations/custom-webpack-config/.

Atualmente a propriedade addons está registrando dois addons, o actions e links, vamos ver o que esses addons fazem.

actions

O addon actions está sendo usado nas stories do Button, ele está sendo usado no onClick do componente Button.

Ao abrir a story Button > Text perceba que há um painel chamado Actions na parte inferior da página, ao clicar no botão que está sendo exibido na story, serão logados as informações do evento de click na aba de Actions.

O addon actions pode ser usado para exibir os dados recebidos por event-handlers no storybook, como onClick, onKeyDown, etc. Ou qualquer outro tipo de dado que você queira logar no painel de Actions.

Se você quiser saber mais sobre o funcionamento desse addon, veja o github do projeto.

links

Como o próprio nome diz, o addon links serve para linkar stories entre sí. Na story do componente <Welcome /> que vem por default, há um link para a story chamada “Button”.

Esse link é feito através do linkTo que está sendo usado na prop showApp do componente Welcome.

export const ToStorybook = () => <Welcome showApp={linkTo('Button')} />;

Ao clicar no link stories, vamos parar na primeira história do kind Button.

Se você quiser ir para uma story específica (não mais a primeira), você pode passar um segundo parâmetro, que é o nome da story.

Vamos alterar o linkTo para linkar para story Emoji:

0-Welcome.stories.js
import React from 'react';
import { linkTo } from '@storybook/addon-links';
import { Welcome } from '@storybook/react/demo';
export default {
title: 'Bem vindo',
component: Welcome,
};
export const ToStorybook = () => (
<Welcome showApp={linkTo('Button', 'Emoji')} />
);
ToStorybook.story = {
name: 'ao Storybook',
};

Agora ao clicar no link stories estamos indo para story Emoji e não mais a Text.

Gif do link stories funcionando com segundo parâmetro

Conclusão

Até agora nós criamos o repositório no github, instalamos o React e o ReactDOM, configuramos e editamos o Storybook.

Vimos todos os arquivos que a instalação do storybook criou e também vimos as funções e plugins desses arquivos.

No próximo post vamos começar a configurar ferramentas, como o commitizen, eslint e algumas outras.