@govbr-ds/webcomponents-vue
v2.2.0
Published
Wrapper Vue para a biblioteca de Web Components do GovBR-DS.
Readme
Vue – @govbr-ds/webcomponents-vue
Este wrapper Vue encapsula os Web Components GovBR-DS, permitindo que sejam utilizados como componentes nativos no Vue.
Compatibilidade
- Faixa declarada (peerDependencies): Vue
>=3.4.38 <4.0.0. - Menor versão testada em CI: Vue
3.4.38. - Versão atual da matriz de teste: Vue
3.5.40. - Núcleo de Web Components:
@govbr-ds/webcomponents2.1.3. - Navegadores: A mesma política Baseline Widely Available dos Web Components. Internet Explorer não é suportado.
[!NOTE] Essa faixa acompanha o peer exigido pelo runtime do output target Vue. O Vue Router não é um requisito do wrapper. O wrapper não faz requisições HTTP, autenticação, cache ou transporte de dados — essas responsabilidades permanecem na aplicação consumidora.
Por que usar este wrapper? 🤔
- Verificação de tipos.
- Integração com Vue Router.
- Suporte a
v-modelpara componentes de formulário.
Mais detalhes na documentação do Stencil.
Instalação 📦
npm install @govbr-ds/webcomponents-vue
# ou
pnpm add @govbr-ds/webcomponents-vue
# ou
yarn add @govbr-ds/webcomponents-vuepeerDependencies
peerDependencies são pacotes que este wrapper não instala automaticamente — o seu projeto precisa tê-los instalados.
Observe que algumas peerDependencies podem ter suas próprias peerDependencies que também precisam ser atendidas. Consulte a documentação de cada pacote para garantir que todas as dependências necessárias estejam presentes.
Por que existem: Garantem que o seu app Vue e o wrapper compartilhem a mesma instância do Vue e dos Web Components. Versões duplicadas causam erros em tempo de execução.
O que isso implica: Se as peers não estiverem instaladas ou forem incompatíveis, componentes podem não funcionar.
As peers declaradas neste pacote são:
| Pacote | Versão mínima |
| ------------------------- | ------------- |
| vue | >=3.4.38 <4 |
| @govbr-ds/webcomponents | ^2 |
Se você seguiu o comando de instalação acima, ambas as peers já estão incluídas.
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:
node-linker=hoistedPor 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.
Quickstart Vue
Use o quickstart Vue como referência para configuração de projeto:
- Repositório: govbr-ds-wbc-quickstart-vue
- Servidor local:
pnpm dev - Formulários: estado com
v-model, binding manual e VeeValidate - Testes headless:
pnpm test:e2e - Porta padrão:
http://localhost:5173/
Uso 📚
Configuração do template
Ao usar @govbr-ds/webcomponents-vue, importe os componentes usados em cada SFC ou registre-os no aplicativo. Não marque br-* como isCustomElement: isso faz o compilador ignorar os proxies Vue e, com eles, a integração de v-model e eventos tipados. A opção isCustomElement serve somente para consumo direto de @govbr-ds/webcomponents, sem este wrapper.
Uso com componentes
import { BrButton } from '@govbr-ds/webcomponents-vue'Uso com v-model:
<script setup lang="ts">
import { BrInput } from '@govbr-ds/webcomponents-vue'
import { ref } from 'vue'
const name = ref('Lorem ipsum')
</script>
<template>
<h1>Olá {{ name }}</h1>
<BrInput name="name" placeholder="Seu nome" v-model="name" />
</template>O v-model padrão já aponta para a propriedade correta de cada proxy:
| Componentes | Propriedade/evento mapeados | Valor do modelo | Uso |
| --- | --- | --- | --- |
| input textual e textarea | value / input | string | v-model="texto" |
| datas simples | value / input | Date \| null | v-model="data" |
| select e radio group | value / change | seleção | v-model="selecao" |
| checkbox, radio e switch | checked / change | boolean | v-model="marcado" |
| slider simples | value / input | number | v-model="numero" |
| upload | files / change | FileList \| null | v-model="arquivos" |
| tag selecionável | selected / change | seleção | v-model="selecionado" |
Para aprender o contrato por baixo do wrapper, compare essa abordagem com o binding manual do quickstart, que usa :value/:checked e lê event.currentTarget em @input/@change.
Para datas simples, inicialize o ref com Date | null; não use a string exibida no campo como modelo. O componente só produz texto ao participar de FormData. Valores recuperados de JSON precisam ser convertidos e validados antes de voltar ao v-model.
Validação e acessibilidade com VeeValidate
O VeeValidate mantém o modelo e as regras; o Web Component continua responsável pela interface do campo e pela Constraint Validation nativa. Replique o erro em state, em texto e em aria-invalid.
<script setup lang="ts">
import { BrButton, BrInput, BrMessage } from '@govbr-ds/webcomponents-vue'
import { useField, useForm } from 'vee-validate'
const initialValues = { email: '' }
const { handleSubmit, resetForm } = useForm({ initialValues })
const { value: email, errorMessage: emailError, handleBlur } = useField<string>('email', (value) => {
if (!value) return 'O e-mail é obrigatório.'
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || 'Informe um e-mail válido.'
})
const submit = handleSubmit((values) => console.log(values))
const clear = () => resetForm({ values: { ...initialValues } })
</script>
<template>
<form @submit="submit" @reset="clear" novalidate>
<BrInput
name="email"
label="E-mail"
type="email"
required
v-model="email"
:state="emailError ? 'danger' : undefined"
:aria-invalid="Boolean(emailError)"
@blur="handleBlur"
/>
<BrMessage v-if="emailError" state="danger" is-feedback :message="emailError" />
<BrButton type="reset" emphasis="secondary">Limpar</BrButton>
<BrButton type="submit">Enviar</BrButton>
</form>
</template>O reset precisa alcançar as duas fontes de estado: o botão type="reset" limpa os controles associados, inclusive upload, e resetForm() restaura o modelo, erros e estado de interação do VeeValidate.
Modelos de intervalo
Para os componentes que trabalham com intervalo, o pacote oferece wrappers
aditivos com v-model:range-value:
<script setup lang="ts">
import { ref } from 'vue'
import { BrSliderRange } from '@govbr-ds/webcomponents-vue'
const intervalo = ref({ start: 20, end: 80 })
</script>
<template>
<BrSliderRange v-model:range-value="intervalo" :min="0" :max="100" />
</template>Os dados assíncronos continuam sob controle da aplicação. Por exemplo, use
loading, options e os eventos de busca do BrSelect; o wrapper não faz
requisições HTTP, cache ou autenticação.
Dependências de Build 🛠️
Este pacote é um wrapper gerado automaticamente e depende dos artefatos produzidos pelo núcleo de Web Components.
| Pacote | Dependência de Build | Motivo |
| :--- | :--- | :--- |
| @govbr-ds/webcomponents-vue | webcomponents:build | Necessita dos proxies gerados em src/stencil-generated; a preparação aponta esses proxies para o adaptador mantido em src/runtime.ts. |
Desenvolvimento 👨💻
Estrutura do projeto
├── 📁 src
│ ├── 📁 stencil-generated
│ ├── 📄 runtime.ts
│ └── 📄 index.ts[!WARNING] Tudo dentro de
stencil-generatedé sobrescrito ao gerar o build de Web Components.
src/runtime.ts não é gerado. Ele preserva o runtime oficial e impede que o marcador interno de uma prop ARIA ausente seja serializado como Symbol(). O passo de preparação reaplica automaticamente esse import após a geração dos proxies.
Scripts/Build
nx build webcomponents
nx build vueNuxt 3
O exemplo abaixo usa os Web Components diretamente no cliente, sem os proxies Vue. Nesse modo, configure vue.compilerOptions em nuxt.config.ts:
// nuxt.config.ts
export default defineNuxtConfig({
vue: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('br-'),
},
},
})Use o plugin defineNuxtPlugin para registrar os Web Components apenas no cliente:
// plugins/govbr-ds.client.ts
import { defineCustomElements } from '@govbr-ds/webcomponents/loader'
export default defineNuxtPlugin(() => {
defineCustomElements()
})Essa configuração trata br-* como elemento nativo e, portanto, não oferece o v-model do wrapper. Se o aplicativo registrar BrInput, BrSelect e os demais proxies Vue, remova isCustomElement e use uma estratégia de plugin compatível com o modo de renderização escolhido.
Formatos do build 📦
A tarefa nx build vue compila o wrapper e gera a saída em dist/vue/. Abaixo estão os artefatos produzidos e quando utilizá-los.
Estrutura do dist/vue/
dist/vue/
├── src/
│ ├── index.js ← Entrada principal (ESM)
│ ├── index.d.ts ← Tipos TypeScript
│ └── stencil-generated/
│ └── components.js ← Componentes proxy com v-model (gerados pelo Stencil)
├── package.json
└── README.mdQuando usar cada formato
| Artefato | Quando usar | Observações |
| ---------------- | -------------------------------------- | -------------------------------------------------------------- |
| src/index.js | Aplicações Vue 3 (Vite, Webpack, Nuxt) | Importação padrão via @govbr-ds/webcomponents-vue |
| src/index.d.ts | Autocomplete e tipagem TypeScript | Resolvido automaticamente pelo campo types do package.json |
v-model e componentModels
Os componentes de formulário suportam v-model nativamente graças à configuração componentModels do Stencil Vue output target. Isso significa que:
br-input,br-select,br-checkbox,br-radioe outros componentes de formulário emitem o evento correto e expõem a prop adequada para two-way binding.- Não é necessário configuração extra — use
v-modeldiretamente:
<script setup lang="ts">
import { ref } from 'vue'
import { BrInput } from '@govbr-ds/webcomponents-vue'
const nome = ref('')
</script>
<template>
<BrInput v-model="nome" label="Nome" />
</template>Documentações Complementares 📖
- Wiki: gov.br/ds/wiki/desenvolvimento/web-components
- MDN Web Components: developer.mozilla.org/Web_Components
Contribuindo 🤝
- Padrões e boas práticas: gov.br/ds/wiki
- Como contribuir: contribuindo com o DS
Reportar Bugs/Problemas 🐛
Abra uma issue: gitlab.com/.../issues/new
Commits 📝
Padrões de branches e commits: gov.br/ds/wiki
Precisa de ajuda? 🆘
- Site: gov.br/ds
- Web Components: gov.br/ds/webcomponents
- Discord: discord.gg/U5GwPfqhUP
Créditos 🎉
Desenvolvido pelo SERPRO com a comunidade.
