@govbr-ds/webcomponents
Version:
Biblioteca de Web Components baseado no GovBR-DS
334 lines (234 loc) • 15.8 kB
Markdown
# Web Components – @govbr-ds/webcomponents
[](https://www.npmjs.com/package/@govbr-ds/webcomponents)
A biblioteca de Web Components do [GovBR-DS](https://gov.br/ds) é desenvolvida utilizando o [Stencil](https://stenciljs.com/), um compilador que cria Web Components (Custom Elements). O Stencil combina os melhores conceitos dos frameworks mais populares em uma ferramenta simples e eficiente. Para mais informações, visite o [site oficial do Stencil](https://stenciljs.com/).
## Demonstração 🚀
Confira nossos componentes em ação:
- [Versão 1.x](https://gov.br/ds/webcomponents/)
- [Versão 2.x (em desenvolvimento)](https://govbr-ds.gitlab.io/bibliotecas/wbc/govbr-ds-wbc/)
## Tecnologias 💻
Este projeto utiliza as seguintes tecnologias:
1. [GovBR-DS](https://gov.br/ds/ 'GovBR-DS')
1. [Stencil](https://stenciljs.com/ 'Stencil')
1. [Font Awesome](https://fontawesome.com/ 'Font Awesome')
1. [Fonte Rawline](https://www.cdnfonts.com/rawline.font/ 'Fonte Rawline')
1. [NX Monorepo](https://nx.dev/ 'NX Monorepo')
## O que são Web Components? ❓
Web Components são um conjunto de tecnologias que permitem criar novos elementos HTML personalizados, reutilizáveis e encapsulados para uso em páginas e aplicativos web. Baseados em padrões da web, são suportados por todos os navegadores modernos.
O diagrama abaixo ilustra os três principais componentes dos Web Components:
- **Elementos HTML personalizados**: Tags HTML definidas com JavaScript, usadas como qualquer outro elemento HTML.
- **Shadow DOM**: Um espaço de nome encapsulado para cada elemento HTML personalizado, garantindo que estilos e scripts não interfiram no restante da página.
- **Templates**: Fragmentos de HTML reutilizáveis em vários elementos.
- **Slots**: Áreas em um elemento HTML personalizado onde templates podem ser inseridos.
### Ciclo de Vida
Para entender melhor o ciclo de vida dos componentes, acesse a página [https://stenciljs.com/docs/component-lifecycle](https://stenciljs.com/docs/component-lifecycle).
## Integração com frameworks 🔗
Integrar Web Components com frameworks pode ser desafiador em algumas situações. Para facilitar, criamos bibliotecas de integração (wrappers), que encapsulam os Web Components em bibliotecas nativas de frameworks, simplificando a integração com funcionalidades como binding.
Para mais detalhes, consulte a [documentação do Stencil sobre integrações](https://stenciljs.com/docs/overview).
Vale lembrar que, em alguns casos, a integração pode não ser possível, dependendo da evolução da especificação de Web Components e do suporte dos frameworks.
## Instalação 📦
Instale o pacote e os estilos base do DS como dependências de produção:
```bash
npm install @govbr-ds/webcomponents @govbr-ds/core
# ou
pnpm add @govbr-ds/webcomponents @govbr-ds/core
# ou
yarn add @govbr-ds/webcomponents @govbr-ds/core
```
> [!NOTE]
> O pacote `@govbr-ds/core` fornece os tokens/estilos base que os componentes utilizam.
## Nota importante: pnpm e tree-shaking
Se ao consumir estes pacotes você notar que o bundler não está removendo código não utilizado (tree‑shaking), pode haver uma incompatibilidade com o layout padrão do pnpm.
Solução rápida (opcional, somente se precisar): crie um arquivo `.npmrc` na raiz do seu projeto com:
```properties
node-linker=hoisted
```
Por que isso ajuda: por padrão, o pnpm organiza as dependências em pastas isoladas com symlinks. Alguns bundlers/otimizadores se baseiam na estrutura de `node_modules` e no campo `sideEffects` para decidir o que pode ser eliminado. O layout hoisted aproxima o formato “achatado” (similar ao npm/yarn), facilitando essa análise e, em muitos casos, restaurando o tree‑shaking.
Observações:
- Use apenas se o tree‑shaking realmente não estiver funcionando.
- Pode aumentar o uso de disco e alterar a resolução de dependências do seu projeto.
## Uso 📚
### Font Awesome e Fonte Rawline
Nossos componentes utilizam a [Fonte Rawline](https://www.cdnfonts.com/rawline.font/ 'Fonte Rawline') e a [Font Awesome](https://fontawesome.com/ 'Font Awesome') padrão do DS. Ambas são essenciais para garantir a estética e funcionalidade dos componentes. Consulte a documentação no site do [GovBR-DS](https://www.gov.br/ds/como-comecar/instalacao 'GovBR-DS') para mais detalhes sobre como importá-las via CDN.
- **[Font Awesome](https://fontawesome.com/ 'Font Awesome')**: Biblioteca amplamente utilizada para adicionar ícones vetoriais e logotipos aos projetos, fácil de integrar e personalizar.
- **[Fonte Rawline](https://www.cdnfonts.com/rawline.font/ 'Fonte Rawline')**: Fonte moderna e elegante, alinhada à identidade visual do Design System do GovBR-DS.
### Passo-a-passo
Os Web Components GOVBR são elementos HTML regulares ou personalizados (Web Components). Em uma página HTML simples, podem ser usados como qualquer outro elemento.
```html
<html>
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@govbr-ds/webcomponents/dist/webcomponents/webcomponents.css"
/>
<script
type="module"
src="https://cdn.jsdelivr.net/npm/@govbr-ds/webcomponents/dist/webcomponents/webcomponents.esm.js"
></script>
<link rel="stylesheet" href="node_modules/@govbr-ds/core/dist/core-tokens.min.css" />
</head>
<body>
<br-button>Clique aqui</br-button>
</body>
</html>
```
### Eventos
Você pode escutar eventos padrão, como clique e mouseover, da mesma forma que faria com elementos HTML normais. Muitos componentes também emitem eventos personalizados, que recomendamos fortemente utilizar. Esses eventos funcionam como os eventos padrão, mas possuem nomes específicos. Consulte a documentação de cada componente para obter detalhes sobre os nomes e dados dos eventos.
```html
<br-button>Label</br-button>
<script>
const button = document.querySelector('br-button')
button.addEventListener('click', (event) => {
console.log('Botão foi clicado', event.detail.valor)
})
</script>
```
### Exemplos de uso
Disponibilizamos exemplos de como usar este projeto com diferentes tecnologias. Consulte o [nosso grupo no GitLab](https://gitlab.com/govbr-ds/bibliotecas/wc 'GovBR-DS/WC') e procure pelos projetos de 'Quickstart' para mais detalhes.
## Desenvolvimento 👨💻
### Estrutura do Projeto
```plaintext
├── 📁 src
├── 📁 components
├── 📁 br-component
├── 📁 sections
├── 📄 migrate.md
├── 📁 _tests
├── 📄 br-component.e2e.ts
├── 📄 br-component.spec.tsx
├── 📄 readme.md
├── 📄 br-component.scss
├── 📄 br-component.tsx
├── 📁 pages
├── 📁 components
├── 📁 br-component
├── 📄 index.js
├── 📄 exemplo.html
├── 📁 scripts
├── 📄 index.html
├── 📁 value-accessors
├── 📄 stencil.config.ts
├── ...
```
- **src**: Contém o código-fonte do projeto.
- **components**: Diretório com os componentes Web criados com Stencil. Cada componente possui sua própria pasta.
- **br-component**: Pasta específica para o componente `br-component`.
- **sections**: Contém arquivos markdown para inclusão no site.
- **migrate.md**: Explica como migrar o componente da versão anterior para a nova.
- **\_tests**: Contém os arquivos de teste.
- **br-component.e2e.ts**: Testes end-to-end (E2E) do componente.
- **br-component.spec.tsx**: Testes unitários (Unit) do componente.
- **br-component.tsx**: Arquivo principal do componente, com lógica e estrutura.
- **br-component.scss**: Arquivo de estilo do componente.
- **readme.md**: Documentação gerada automaticamente durante o `build`.
- **pages**: Contém exemplos dos componentes Web criados com Stencil.
- **components**: Diretório com exemplos dos componentes.
- **br-component**: Pasta específica para o componente `br-component`.
- **index.js**: Arquivo para executar ações nos exemplos, como escutar eventos.
- **exemplo.html**: Arquivo com o código de cada exemplo.
- **scripts**: Scripts usados no ambiente de desenvolvimento.
- **value-accessors**: Configurações para 2-way binding em Angular e Vue.
- **index.html**: Página inicial do servidor de desenvolvimento.
- **stencil.config.ts**: Arquivo principal de configuração do projeto Stencil, onde são definidas opções como saída do build, plugins e scripts globais.
### Scripts Disponíveis
No arquivo `package.json` e `project.json`, você encontrará diversos scripts úteis. Abaixo está uma lista com a descrição de cada um deles:
- **`nx start webcomponents`**: Inicia o site localmente para desenvolvimento.
- **`nx build webcomponents`**: Realiza a compilação do projeto para produção.
- **`nx test:unit webcomponents`**: Executa os testes unitários.
- **`nx lint:tsx webcomponents`**: Realiza a análise estática nos arquivos TypeScript.
- **`nx lint:md webcomponents`**: Realiza a análise estática nos arquivos markdown.
- **`nx lint:styles webcomponents`**: Realiza a análise estática nos arquivos de estilo.
**Gerenciar baseline de tamanho:**
```bash
# Da raiz do monorepo:
pnpm run baseline:update:webcomponents # Atualizar baseline
pnpm run baseline:compare:webcomponents # Comparar com baseline atual
```
### Build
Ao gerar o `build` deste projeto Stencil, são automaticamente criados:
- O arquivo `readme.md` dentro da pasta de cada componente.
- Documentações dos componentes na pasta `apps/site/docs/stencil-generated-docs`, que podem ser utilizadas e versionadas pelo site.
```bash
nx build webcomponents
```
### Testes
Nossa estratégia de testes é dividida em duas abordagens principais: testes unitários e testes end-to-end (E2E).
#### Testes Unitários (\*.spec.tsx)
Os testes unitários são ideais para validar a lógica interna dos componentes de forma isolada e eficiente. Utilizamos o método `newSpecPage()` para verificar:
- Estado inicial: comportamento do componente sem propriedades.
- Propriedades: valores válidos, inválidos e alterações em tempo de execução.
- Classes CSS: presença e ausência de classes condicionais.
- Slots: renderização correta do conteúdo.
- Lógica interna: métodos, cálculos e transformações.
- Validações básicas: required, minLength, maxValue, entre outras.
```typescript
import { newSpecPage } from '@stencil/core/testing'
import { BrComponent } from '../component'
it('deve inicializar com o estado padrão', async () => {
const page = await newSpecPage({
components: [BrComponent],
html: /*html*/ `<br-component></br-component>`,
})
expect(page.root).toEqualHtml(`<br-component>...</br-component>`)
})
```
### Testes E2E (\*.e2e.ts)
Os testes E2E são realizados em um navegador real utilizando o método `newE2EPage()`. Embora sejam mais lentos, são fundamentais para validar:
- Eventos do componente: clique, blur, change, entre outros.
- Interações do usuário: drag-drop, digitação, atalhos.
- Integrações DOM: forms, validação nativa, atributos aria-\*.
- Estilos visuais: dimensões, cores, transições.
- Shadow DOM: slots, parts, estilos encapsulados.
```typescript
import { newE2EPage } from '@stencil/core/testing'
describe('br-component', () => {
it('deve renderizar', async () => {
const page = await newE2EPage()
await page.setContent(/*html*/ `<br-component></br-component>`)
const element = await page.find('br-component')
expect(element).toHaveClass('hydrated')
})
it('deve ter shadow root', async () => {
const page = await newE2EPage()
await page.setContent(/*html*/ `<br-component-component></br-component-component>`)
const element = await page.find('br-component')
expect(element.shadowRoot).not.toBeNull()
})
})
```
Para mais informações sobre testes no Stencil, consulte a [documentação oficial](https://stenciljs.com/docs/testing-overview).
## VS Code
Durante o desenvolvimento de nossos Web Components, utilizamos custom elements. O VS Code, por padrão, não reconhece esses componentes, o que impede sugestões inteligentes no autocomplete. Para resolver isso, geramos um arquivo com as definições dos componentes, disponibilizado junto ao pacote npm.
Para importar no seu VS Code, adicione o seguinte campo, ajustando o caminho para o local onde o `node_modules` está armazenado no seu projeto:
```json
{
"html.customData": ["./node_modules/@govbr-ds/webcomponents/dist/webcomponents/webcomponents.html-custom-data.json"]
}
```
## Documentações Complementares 📖
Consulte a seção sobre Web Components na nossa [Wiki](https://gov.br/ds/wiki/desenvolvimento/web-components) para obter mais informações sobre este projeto.
Para mais detalhes sobre a especificação de Web Components, recomendamos a consulta ao [MDN](https://developer.mozilla.org/pt-BR/docs/Web/Web_Components 'Web Components | MDN').
## Contribuindo 🤝
Antes de abrir um Merge Request, considere as seguintes orientações:
- Este é um projeto open-source, e contribuições são sempre bem-vindas.
- Para facilitar a aprovação da sua contribuição, utilize um título claro e explicativo no MR e siga os padrões descritos em nossa [wiki](https://gov.br/ds/wiki/ 'Wiki').
- Deseja contribuir? Consulte o nosso guia [como contribuir](https://gov.br/ds/wiki/comunidade/contribuindo-com-o-ds/ 'Como contribuir?').
## Reportar Bugs/Problemas ou Sugestões 🐛
Caso encontre problemas ou tenha sugestões de melhorias, abra uma [issue](https://gitlab.com/govbr-ds/bibliotecas/wbc/govbr-ds-wbc/-/issues/new). Utilize o modelo apropriado e forneça o máximo de detalhes possível.
Nos comprometemos a responder a todas as issues.
## Commits 📝
Este projeto segue um padrão específico para branches e commits. Consulte a documentação em nossa [wiki](https://gov.br/ds/wiki/ 'Wiki') para entender mais sobre esses padrões.
## Precisa de ajuda? 🆘
Por favor, **não** crie issues para dúvidas gerais.
Utilize os canais abaixo para esclarecer suas dúvidas:
- Site do GovBR-DS [http://gov.br/ds](http://gov.br/ds)
- Web Components [https://gov.br/ds/webcomponents](https://gov.br/ds/webcomponents)
- Canal no Discord [https://discord.gg/U5GwPfqhUP](https://discord.gg/U5GwPfqhUP)
## Créditos 🎉
Os Web Components do [GovBR-DS](https://gov.br/ds/ 'GovBR-DS') foram desenvolvidos pelo [SERPRO](https://www.serpro.gov.br/ 'SERPRO | Serviço Federal de Processamento de Dados') em parceria com a comunidade.
## Nota sobre pnpm e tree-shaking
Em alguns cenários, para que o tree‑shaking funcione corretamente (especialmente em bundlers que dependem da estrutura de `node_modules` e da resolução de `sideEffects`), pode ser necessário configurar o pnpm para usar o layout de dependências "hoisted".
Crie um arquivo `.npmrc` na raiz do seu projeto (caso ainda não exista) com:
```properties
node-linker=hoisted
```
Por quê: o layout padrão do pnpm usa pastas isoladas com symlinks, o que pode confundir determinadas ferramentas de build/otimização ao analisar limites de módulos e `sideEffects`. O `node-linker=hoisted` aproxima o layout do de npm/yarn (flat/hoisted), facilitando a análise estática e, consequentemente, o tree‑shaking. Use essa opção apenas se perceber problemas de eliminação de código morto; ela pode aumentar o uso de disco e alterar a resolução de dependências.