Storybook Storybook
v1.81.11

# Contribuindo para Coruja Web UI

Reserve um momento para revisar este documento para tornar o processo de contribuição fácil e eficaz para todos os envolvidos.

Seguir essas diretrizes ajuda a comunicar que você respeita o tempo dos desenvolvedores gerenciando e desenvolvendo este projeto. Em troca, eles devem retribuir esse respeito ao abordar seu problema ou avaliar as alterações.

Toda ajuda será bem-vinda, basta se atentar ao padrões e guias descritos aqui.

# Problemas erros ou novas sugestões e funcionalidades

Caso tenha alguma sugestão de funcionalidade ou erro para reportar, recomendamos que crie uma nova Issue (opens new window), assim conseguimos manter um histórico de decisões além de facilitar a gestão do projeto. 😄

Caso tenha alguma dúvida, busque o time de DesignOps no Slack no canal #tech-team-design-system.

# Fluxo de contribuição

Novas contribuições são muito bem vindas, porém é necessário alinhar as expectativas primeiro. Mudanças conceituais, de interação, design e propósito das peças do Design System devem sempre vir como uma demanda do time de Design primeiramente, e preferencialmente passando pelo time de DesignOps.

Fluxo de Contribuição

Claro que pequenas correções de erros ou ajustes de bugs podem ser realizadas diretamente a nível de código, realizando um Pull Request e seguindo nosso template de PR. Mas ainda sim é recomendado alinhar com o time de DesignOps primeiro ou abrindo uma Issue (opens new window), já que as vezes aquele bug pode ser uma feature 😄, ou o time pode já ter um fix em encaminhado para aquele problema.

# Contribuindo com uma PR

Antes de realizar grandes mudanças pedimos que cheque primeiro com o time de DesignOps se essas alterações fazem sentido, com o intuito de prover agilidade entre os times seguindo os passos descritos em Fluxo de contribuição.

Feito isso, ao abrir uma PR leve em consideração sempre os seguintes pontos:

  • Alinhei previamente com designer responsável ou com o time de DesignOps;
  • Tenho ciência de que as mudanças feitas aqui devem servir para outros projetos também;
  • Meu código segue os padrões declarados no Padrões de código do nosso projeto;
  • Realizei as alterações necessárias na documentação e Storybook.

# Documentação

Nossa documentação é construída utilizando o Vuepress (opens new window), usando apenas arquivos Markdown e fica alocada na pasta docs. Toda alteração de API dos componentes como uma nova prop, mudança de uma prop atual e etc. deve ser documentada para garantirmos que essas alterações serão propagadas para os outros times de forma fácil, não causando atritos ou quebras no desenvolvimento dos outros times.

# Criação da PR

Siga essas boas práticas para criar a PR da melhor maneira:

# Branch

Para nomear suas branches utilize nomes descritivos separados por hífen e em português.

Tipo Nome
❌ Errado branchDaFuncionalidadeXQueAdicionaTudoQuePrecisa
❌ Errado feat/bubbles
✅ Certo funcionalidade-x
✅ Certo melhoria-y
✅ Certo correcao-z

# Commits

Ao fazer seus commits utilize uma mensagem curta, no presente do indicativo e em português. A mensagem deve responder a pergunta: O que esse commit faz?.

Exemplos:

Tipo Mensagem
❌ Errado Essa é uma mensagem de paz, tranquilidade, amor e esperança que visa apresentar as melhorias na funcionalidade XPTO
✅ Certo Adiciona melhoria na funcionalidade X
✅ Certo Corrige fluxo de integração contínua
✅ Certo Altera escopo de funcionalidade Y

# Pull Request

Utilize títulos declarativos e adicione o número do cartão do Jira (caso disponível). Exemplo:

Tipo Título
✅ Certo [SVWEB-00] Padronização de documentação
❌ Errado (00) Melhorias
❌ Errado Correções

Não se esqueça de incluir as informações do que foi feito e como pode ser testado 😉

# Padrões de código

Aqui estão as definições dos padrões que estamos seguindo com o desenvolvimento dentro do Design System, com o objetivo de gerar um código acessível, manutenível, e visando o seu uso em diversas plataformas e projetos diferentes.

# Estrutura

.
├── .storybook        # Configurações do Storybook
├── docs              # Documentação de Design System
├── public            # Arquivos públicos
├── scripts           # Scripts de automatização de rotinas
│   └── templates     # Templates de componentes
└── src               # Arquivos do projeto
    ├── assets        # Ativos do projeto
    |-- cdk           # Component Development Kit: Utilizades Core para criação de componentes
    ├── components    # Componentes do projeto
    ├── icons         # Ícones do projeto
    ├── styles        # Estilos do projeto
    └── utils         # Utilidades do projeto
1
2
3
4
5
6
7
8
9
10
11
12
13

# Componentes

Usar CSS na hora de estilizar os componentes e definir suas classes usando o prefixo c- com nomes distintos referentes ao componente.

Correto:

.c-button {
  display: flex;
  background-color: var(--color-primary);
}
1
2
3
4

Incorreto (ex.: usando Tailwind):

<div class="flex ui-bg-primary"></div>
1

#


Usar a semântica correta para os elementos.

Correto:

<button @click="doSomething()">Clique aqui!</button>
1

Incorreto:

<div @click="doSomething()">Clique aqui!</div>
1

#


Preferir unidades em valores relativos ao root element (rem) do que pixel e outras unidades.

Correto:

.c-button {
  height: 3.5rem;
}
1
2
3

Incorreto:

.c-button {
  height: 56px;
}
1
2
3

# Testes

Criar uma função de setup que cuidará de realizar o mount do componente, e retornará um objeto com o qual iremos realizar as asserções.

Para os testes estamos utilizando a Vue Testing Library (opens new window).

Para um guia de boas práticas do Testing Library consulte aqui (opens new window)

O Padrão abaixo da função setup se chama Testing Object Factory, você pode ler mais sobre aqui (opens new window) e aqui (opens new window)

import { render, screen } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import Component from './Component.vue'

function setup (props = {}, slots = {}, listeners = {}) {
  return render(Component, {
    props: {
      ...props
    },
    slots: {
      ...slots
    },
    listeners: {
      ...listeners
    }
  })
}

describe('Component', () => {
  it('should match the snapshot', () => {
    // Não precisamos usar o retorno aqui para casos simples
    setup()
    // Acessamos o que esta renderizado através do screen
    // O screen é limpo automaticamente em cada render
    expect(screen.getByText('my-component')).toMatchSnapshot()
  })

  // Disparando eventos
  it('should allow to be clicked', () => {
    const clickStub = jest.fn()
    setup({}, {}, {
      click: clickStub
    })

    userEvent.click(screen.getByRole('button'))
    expect(clickStub).toHaveBeenCalled()
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Nos testes devemos sempre testar levando em conta o user behaviour - o que o usuário vê e interage na aplicação, dessa forma devemos priorizar testes que checam por textos, e elementos visíveis na tela na hora de buscar por eles e então testar se eles atendem nossos cenários e evitar a todo custo testar detalhes da implementação (como props, data do Vue, etc).

Alguns exemplos:


Checar se a string que passamos na prop do componente bate com o valor.

Correto:

it('should match the text', () => {
  setup({
    myText: 'Meu texto de teste'
  })

  expect(screen.getByText('Meu texto de teste')).toBeVisible()
})
1
2
3
4
5
6
7

Incorreto:

it('should match the text', () => {
  const wrapper = shallowMount(Component, {
    propsData: {
      myText: 'Meu texto de teste'
    }
  })

  expect(wrapper.vm.$props.myText).toEqual('Meu texto de teste')
})
1
2
3
4
5
6
7
8
9

#

# Como testar

Como nossos componentes serão usados por diversos projetos e situações diferentes, é importante testarmos suas funcionalidades de forma bem abrangente.

Temos duas formas de visualizar o trabalho feito hoje:

  • Rodando o storybook localmente npm run story

  • Rodando a documentação localmente npm run docs

E ainda temos um comando de health check geral, que irá fazer tudo: rodar testes, lint, build do storybook para prod, build da documentação para prod, e build da propria lib para prod gerando todos os assets.

Recomendamos que o desenvolvimento de novas funcionalidades seja feito pelo Storybook, e que ao final dele seja executado o comando de health check:

npm run healthcheck

Para o futuro imaginamos ter um projeto de exemplo rodando todos os componentes e com testes de integração automatizados.

# Browser Support

Não temos um suporte de cross-browser definido hoje, porém a princípio seria de dar cobertura aos browsers que suportam a sintaxe do ES6 (opens new window) e do Flexbox (opens new window).

# Como executo a lib em outro projeto localmente?

Para poder testar como suas alterações impactam os outros projetos, deixe o build rodando no modo watch, com o comando:

npm run build:watch

E faça um install apontando para a sua pasta do Coruja localmente. Ex.:

Caso seu repositório do Coruja esteja em: ~/Sites/coruja-web-ui e seu projeto esteja em: ~/Sites/meu-projeto-cool, você irá de dentro do seu projeto precisar subir um nível de pasta ao apontar para o coruja, rodando o seguinte comando:

npm i ../coruja-web-ui

Esse comando idealmente só deve precisar ser executado uma vez, e irá atualizar seu package.json com o caminho para a lib do Coruja, assim:

{
  // package.json
  "dependencies": {
    "@estrategiahq/coruja-web-ui": "file:../coruja-web-ui",
    //...outras deps
  }
}
1
2
3
4
5
6
7

Formando então um symlink. Dessa forma toda vez que nosso comando de watch re-buildar nossos arquivos, a sua aplicação poderá acessá-los na mesma hora.

# Executando o pacote já criado

Caso você tenha alguma necessidade maior nos seus testes e precise de um ambiente mais limpo para testar suas alterações (já que nem sempre o symlink nos fornece a melhor Developer Experience), pode usar o Verdaccio (opens new window) que é um registro NPM local, que com alguns comandos você consegue publicar seus pacotes e consumi-los localmente.