DEV Community

Klaus Kazlauskas
Klaus Kazlauskas

Posted on • Updated on

Como criar uma biblioteca de componentes com Angular e Storybook

Se você já tentou criar uma biblioteca de componentes pro seu sistema, você com toda certeza já alterou um componente que quebrou várias páginas e quando te perguntaram quem foi...

Um fantoche de macaco olha de canto de olho pra tela, e depois olha pra frente como se não tivesse visto nada

Pra eliminar esse e outros problemas, como não saber se um componente existe, como funciona ou em que página você pode ver um exemplo dele funcionando; existe o Storybook.

Logo do Storybook

O Storybook se denomina como "Um explorador de componentes UI para desenvolvedores front-end". Isso quer dizer que ele serve para gerar várias histórias dos nossos componentes, assim como a documentação deles, para facilitar a exploração visual dos nossos componentes.

Vídeo de exemplo do Storybook

Então, vamos criar passo-a-passo essa biblioteca de componentes.


Preparação

Na época que esse guia foi preparado, foram usadas as seguintes tecnologias:

tecnologia versão instalação
Node.js 11.6.0 como instalar
NPM 6.13.4 Já vem com o Node.js
Angular CLI 8.3.21 como instalar

Todo o código desse projeto está no GitHub, então, caso você se perca em qualquer parte, pode fazer uma comparação direta:

GitHub logo klauskpm / angular-storybook

Repositório para ensinar a usar Storybook com Angular.

⚠️ Caso você já saiba gerar uma biblioteca, você pode pular para a sessão Instalando o Storybook ⚠️

Gerando o projeto

Usando o Angular CLI, vamos criar um projeto chamado angular-storybook e uma biblioteca chamada storybook-ui:

ng new angular-storybook

# dentro do projeto angular-storybook
ng g lib storybook-ui --prefix ui # versão curta de ng generate library
Enter fullscreen mode Exit fullscreen mode

Já temos o projeto para usar nossos componentes, e temos a biblioteca onde vamos desenvolver eles. A biblioteca já vem com um componente pronto, mas não vamos usar ele. Então, vamos até a pasta /projects/storybook-ui/src/lib/ e deletamos tudo de lá. Nessa mesma pasta vamos criar o módulo e componente simple-button.

# dentro da pasta /projects/storybook/src/lib

ng g m simple-button # versão curta de ng generate module

ng g c simple-button --export # versão curta de ng generate componente
Enter fullscreen mode Exit fullscreen mode

E vamos dar uma cara de botão para o nosso componente:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'ui-simple-button',
  template: `
    <button>{{text}}</button>
  `,
  styles: [``]
})
export class SimpleButtonComponent {

  @Input() text = 'clique aqui';
}
Enter fullscreen mode Exit fullscreen mode

Agora, vamos no arquivo /projects/storybook/src/public_api.ts e substituir todo o conteúdo desse arquivo por:

export * from './lib/simple-button/simple-button.component';
export * from './lib/simple-button/simple-button.module';
Enter fullscreen mode Exit fullscreen mode

Para usar esse componente precisamos gerar o arquivo final da biblioteca:

ng b storybook-ui # versão curta de ng build
Enter fullscreen mode Exit fullscreen mode

Reescrever o /src/app/app.component.html:

Ola Mundo!
<ui-simple-button></ui-simple-button>
Enter fullscreen mode Exit fullscreen mode

E adicionar o SimpleButtonModule ao /src/app/app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { SimpleButtonModule } from 'storybook-ui';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SimpleButtonModule // modificado
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

Por último, vamos servir nossa aplicação e ver como ela está no http://localhost:4200 :

ng s # versão curta de ng serve angular-storybook
Enter fullscreen mode Exit fullscreen mode

Projeto de Angular rodando na porta 4200, com o texto

Pode comparar o seu progresso com a tag v1.2 do repositório


Instalando o Storybook

O Storybook tem um guia de como fazer a instalação em um projeto Angular e o jeito mais fácil é só usando uma única linha:

npx -p @storybook/cli sb init --type angular
Enter fullscreen mode Exit fullscreen mode

Executando essa linha no seu projeto, ele:

  • instala todas as dependências necessárias
  • adiciona os scripts storybook e build-storybook no seu package.json
  • cria os arquivos de configuração pro Storybook
  • cria as histórias de exemplo no seu projeto principal

Para ver o Storybook em ação, é só rodar o comando:

npm run storybook
Enter fullscreen mode Exit fullscreen mode

Página do Storybook rodando em localhost:6006, exibindo a história ˜with some emoji and action

Tudo bonito, tudo rodando. Mas, a configuração do Storybook está apenas pro seu projeto principal, e não para a sua biblioteca. Além disso, você sabe o que foi adicionado e para que? Então vamos voltar no tempo e seguir de forma manual.

Fazendo a instalação manualmente

1) Instale as dependências

npm install @storybook/angular babel-loader @babel/core --save-dev
Enter fullscreen mode Exit fullscreen mode

2) Adicione os scripts de npm

{
  "scripts": {
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook"
  }
}
Enter fullscreen mode Exit fullscreen mode

O script storybook vai executar o start-storybook para exibir nossas histórias no http://localhost:6006. O build-storybook vai executar o build-storybook que vai gerar os arquivos estáticos do Storybook na pasta storybook-static.

Você pode definir o diretório final mudando o comando build-storybook por build-storybook -o /dist/storybook, colocando os arquivos estáticos no mesmo diretório que os builds gerados pelo seu projeto.

3) Crie o arquivo de configuração

É esse o arquivo que o Storybook vai usar para saber onde ele pode procurar as nossas histórias e como identificar os arquivos. No caso, vamos procurar arquivos com .stories.ts neles, dentro das pastas src e projects.

Crie o arquivo .storybook/config.js com o seguinte conteúdo:

import { configure } from '@storybook/angular';

configure([
  require.context('../src', true, /\.stories\.ts$/),
  require.context('../projects', true, /\.stories\.ts$/)
], module);
Enter fullscreen mode Exit fullscreen mode

4) Configure o Storybook para funcionar com TypeScript

Como o @storybook/angular usa o ForkTsCheckerWebpackPlugin, precisamos criar o arquivo .storybook/tsconfig.json:

{
  "extends": "../tsconfig.json",
  "exclude": [
    "../src/test.ts",
    "../src/**/*.spec.ts",
    "../projects/**/*.spec.ts"
  ],
  "include": [
    "../src/**/*",
    "../projects/**/*"
  ]
}
Enter fullscreen mode Exit fullscreen mode

5) Escreva sua história 🎉

Finalmente! Agora vamos criar nossa própria história e ver como ela se comporta.

Dentro da pasta do nosso componente simple-button, vamos criar o arquivo index.stories.ts com o conteúdo a seguir:

import { SimpleButtonComponent } from "./simple-button.component";

export default {
  title: 'UI | Button'
};

export const withDefaultValues = () => ({
  component: SimpleButtonComponent
});

export const withText = () => {

  return {
    component: SimpleButtonComponent,
    props: {
      text: 'Ola'
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Essa é uma das formas que podemos escrever as histórias. Ela é chamada de CSF (Component Story Format). Também temos a StoriesOf API e o MDX Syntax, que está por vir. Como o CSF é um adição nova no Storybook, boa parte dos exemplos da internet vão estar usando o StoriesOf API.

Dessa forma estamos falando que temos o componente Button, dentro do agrupador UI, com as histórias "With Default Values" e "With Text".

UI
└── Button
    ├── With Default Values
    ├── With Text

Enter fullscreen mode Exit fullscreen mode

6) Rode o projeto

Rode o projeto com o npm run storybook e veja o resultado final:

Alt Text

Pode comparar o seu progresso com a tag v1.3 do repositório

Próximos passos - addons

Agora que você aprendeu como configurar o Storybook e escrever uma história, você pode melhorar a qualidade das suas histórias com simples pluggins, chamados de addons.

Por exemplo, com o addon de actions você pode adicionar logs para ações, como clicks, e ouvir o que eles estão enviando. Com o addon de knobs você pode expor @Inputs do seu componente e altera-los na hora.

Pra não ficar só na explicação e sonhos, vamos montar ele agora. É muito fácil.

1) Instale as dependências

Além dos pacotes óbvios do knobs e do actions, precisamos também instalar o pacote do addons, que vai ser responsável por carregar os addons no Storybook.

npm install --save-dev @storybook/addons @storybook/addon-knobs @storybook/addon-actions
Enter fullscreen mode Exit fullscreen mode

2) Crie o arquivo de configuração dos addons

Crie o arquivo .storybook/addons.js com a seguinte configuração:

import '@storybook/addon-knobs/register';
import '@storybook/addon-actions/register';
Enter fullscreen mode Exit fullscreen mode

A ordem que você importa eles é importante. Ela vai dizer a ordem em que esses addons vão aparecer nos paineis

3) Aplique os addons na sua história

No nosso caso, vamos usar o knobs para expor o @Input text e o actions para exibir uma mensagem ao clicar no botão. Como vamos lidar com um evento e não uma propriedade, não podemos mais usar o component na história withText, pois o props só define propriedades e não eventos. Precisamos usar o template, mas para usarmos o template, precisamos definir o módulo com o componente SimpleButtonComponent.

No final das contas, o nosso index.stories.ts do SimpleButtonComponent vai ficar assim:

import { SimpleButtonComponent } from "./simple-button.component";
import { text, withKnobs } from '@storybook/addon-knobs';
import { moduleMetadata } from '@storybook/angular';
import { action } from '@storybook/addon-actions';

export default {
  title: 'UI | Button',
  decorators: [
    withKnobs,
    moduleMetadata({declarations: [SimpleButtonComponent]})
  ],
};

export const withDefaultValues = () => ({
  component: SimpleButtonComponent
});

export const withText = () => {
  return {
    template: `
        <ui-simple-button
          [text]="text"
          (click)="click($event)"
        ></ui-simple-button>
    `,
    props: {
      text: text('Text', 'Ola'),
      click: action('Clicou')
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

E quando rodarmos o Storybook:
História
História

Pode comparar o seu progresso com a tag v1.4 do repositório


Conclusão

Agora, você sabe como...
✅ Instalar e configurar o Storybook
✅ Criar histórias para componentes
✅ Instalar e configurar addons

Você não vai ter mais problemas em relação ao que sua aplicação tem ou não tem, e o desenvolvimento vai seguir com mais confiança e agilidade, por poder testar as mudanças em diversos cenários.

Se você se interessou pelo Storybook e quer saber o que mais ele pode fazer, você pode começar a ver como...
Aprender o que compõe uma história
Exportar e deployar arquivos estáticos das histórias
Tematizar o Storybook
🎉 E muito mais


Se você ❤️ esse artigo, não deixe de me seguir e compartilhar com seus colegas. E se achar que tem algo para mudar no artigo, não deixe de comentar!

Te vejo na próxima! 😬

Top comments (2)

Collapse
 
purigringo profile image
Anderson Christian

Valeu Klaus, ganhou um fã carioca!

Collapse
 
klauskpm profile image
Klaus Kazlauskas

Valeu mano 😬 !