Ir para o conteúdo principal
WBC - GovBR-DS
Copiar página como Markdown para IA

React – @govbr-ds/webcomponents-react

Este é um wrapper React que encapsula os Web Components GovBR-DS, permitindo seu uso como componentes nativos do React.

Compatibilidade​

  • Faixa declarada: react e react-dom conforme as peerDependencies do pacote, com react-dom na mesma major de react.
  • Núcleo de Web Components: @govbr-ds/webcomponents na mesma versão deste wrapper.
  • Navegadores: A mesma política Baseline Widely Available dos Web Components. Internet Explorer não é suportado.

[!NOTE] React 18 e React 19 continuam suportados no cliente (CSR). O caminho SSR assíncrono do wrapper React (@govbr-ds/webcomponents-react/ssr) é verificado a partir do React 19 Server Components. No React 18, use a entrada principal para SSR clássico. 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? 🤔​

  • Bindings JSX para props/eventos.
  • Tipagens e autocomplete nos IDEs.
  • Soluciona limitações de passagem de objetos/arrays e captura de eventos em custom elements no React.

Para mais detalhes, consulte a documentação oficial do Stencil e o Custom Elements Everywhere.

Instalação 📦​

npm install @govbr-ds/webcomponents-react
# ou
pnpm add @govbr-ds/webcomponents-react
# ou
yarn add @govbr-ds/webcomponents-react

peerDependencies​

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 e o wrapper compartilhem a mesma instância do React e dos Web Components. Versões duplicadas podem causar erros em tempo de execução ou comportamentos inesperados.

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:

  • react
  • react-dom
  • @govbr-ds/webcomponents

As versões aceitas estão em peerDependencies no package.json publicado deste pacote (também exibidas na página do npm e na política de compatibilidade). O peer @govbr-ds/webcomponents exige exatamente a mesma versão deste wrapper.

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=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.

Quickstart React​

Use o quickstart React como referência para configuração de projeto:

  • Repositório: govbr-ds-wbc-quickstart-react
  • Servidor local: pnpm dev
  • Formulários: estado controlado, FormData não controlado e React Hook Form
  • Testes headless: pnpm test:e2e
  • Porta padrão: http://localhost:5173/

Uso 📚​

Exemplo​

import { BrButton } from '@govbr-ds/webcomponents-react';

export default function App() {
return (
<BrButton emphasis="primary" onClick={() => console.log('Ação solicitada')}>
Clique aqui
</BrButton>
);
}

Eventos nativos usam props React como onInput, onChange e onClick; leia o estado em event.currentTarget. Somente eventos customizados documentados, como onBrSelectSearch, usam event.detail.

ComponentesPropriedade controladaEvento de usuárioValor no state
input textual e textareavalueonInputstring
slider simplesvalueonInputnumber
datas simplesvalueonInputDate | null
select e radio groupvalueonChangeseleção
checkbox e switchcheckedonChangeboolean
uploadfilesonChangeFileList | null
tag selecionávelselectedonChangeseleção

Inclua name em todo campo que deve participar de FormData. Não tente controlar FileList: leia files por evento/ref e use o reset nativo para limpar o upload.

Em datas simples, passe uma instância válida de Date ou null para value e leia o mesmo tipo em event.currentTarget.value. FormData recebe a representação textual serializada pelo componente. Se o estado vier de localStorage ou de uma API, converta a string para Date antes de renderizar o campo.

Validação e Acessibilidade (React Hook Form)​

Use Controller para adaptar explicitamente a propriedade e o evento da tabela. Para sinalizar erros, atualize state, mostre um BrMessage textual e preserve o vínculo acessível do campo.

import { Controller, useForm } from 'react-hook-form';
import { BrButton, BrInput, BrMessage } from '@govbr-ds/webcomponents-react';

type LoginFormData = {
email: string;
};

function LoginForm() {
const initialValues: LoginFormData = { email: '' };
const {
control,
handleSubmit,
reset,
} = useForm<LoginFormData>({ defaultValues: initialValues, mode: 'onBlur' });

const onSubmit = (data: LoginFormData) => console.log(data);

return (
<form onSubmit={handleSubmit(onSubmit)} onReset={() => reset(initialValues)} noValidate>
<Controller
name="email"
control={control}
rules={{
required: 'E-mail é obrigatório.',
pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Informe um e-mail válido.' },
}}
render={({ field, fieldState: { error } }) => (
<>
<BrInput
name="email"
type="email"
label="E-mail"
value={field.value}
required
onInput={(event) => field.onChange(event.currentTarget.value)}
onBlur={field.onBlur}
state={error ? 'danger' : undefined}
aria-invalid={Boolean(error)}
/>
{error && <BrMessage state="danger" isFeedback message={error.message} />}
</>
)}
/>

<BrButton type="reset" emphasis="secondary">Limpar</BrButton>
<BrButton type="submit">Entrar</BrButton>
</form>
);
}

Em formulários controlados, o reset tem duas partes: o botão type="reset" restaura os controles associados e reset(initialValues) restaura o estado da biblioteca. Escritas programáticas em props não emitem eventos; atualize o estado React diretamente.

Dependências de Build 🛠️​

Este pacote é um wrapper gerado automaticamente e depende dos artefatos produzidos pelo núcleo de Web Components.

PacoteDependência de BuildMotivo
@govbr-ds/webcomponents-reactwebcomponents:buildNecessita dos proxies gerados em src/stencil-generated e do build de hydrate para suporte a SSR em ssr/stencil-generated.

Desenvolvimento 👨‍💻​

Estrutura do projeto​

├── 📁 src
│ ├── 📁 stencil-generated
│ └── 📄 index.ts
├── 📁 ssr
│ ├── 📁 stencil-generated
│ └── 📄 index.ts

[!WARNING] Tudo dentro de stencil-generated é sobrescrito ao gerar o build de Web Components.

Scripts/Build​

Gere os Web Components antes de compilar o wrapper:

nx build webcomponents
nx build react

SSR (Server-Side Rendering)​

O wrapper React possui suporte a SSR via o subpath ssr/. Essa entrada usa o Server Component assíncrono gerado pelo Stencil e deve ser usada em frameworks que suportem essa fronteira (por exemplo, Server Components do React 19):

import { BrButton } from '@govbr-ds/webcomponents-react/ssr';

Componentes importados pelo subpath ssr são renderizados de forma segura no servidor, sem dependência de APIs do navegador durante o build. Em React 18 com react-dom/server clássico, use a entrada principal; ela gera o custom element no HTML e o comportamento do componente é ativado quando o cliente carrega os Web Components.

Formatos do build 📦​

A tarefa nx build react compila o wrapper e gera a saída em dist/react/. Abaixo estão os artefatos produzidos e quando utilizá-los.

Estrutura do dist/react/​

dist/react/
├── src/
│ ├── index.js ← Entrada principal (ESM)
│ ├── index.d.ts ← Tipos TypeScript
│ └── stencil-generated/
│ └── components.js ← Componentes proxy (gerados pelo Stencil)
├── ssr/
│ ├── index.js ← Entrada SSR (ESM)
│ └── stencil-generated/
│ └── components.server.js ← Componentes SSR (hydrate)
├── package.json
└── README.md

Quando usar cada formato​

ArtefatoQuando usarObservações
src/index.jsAplicações React CSR (client-side)Importação padrão via @govbr-ds/webcomponents-react
ssr/index.jsServer Components/SSR assíncrono compatível com React 19Importação via @govbr-ds/webcomponents-react/ssr; usa dist/hydrate do pacote webcomponents
src/index.d.tsAutocomplete e tipagem TypeScriptResolvido automaticamente pelo campo types do package.json

CSR vs SSR​

  • CSR (Client-Side Rendering): importação padrão. Os componentes são registrados e renderizados no browser.
  • SSR (Server-Side Rendering): os componentes são pré-renderizados no servidor usando o script hydrate do pacote @govbr-ds/webcomponents. No cliente, o Stencil faz a hidratação do HTML pré-renderizado.
// CSR — uso padrão
import { BrButton } from '@govbr-ds/webcomponents-react';

// SSR assíncrono — Server Components/React 19
import { BrButton } from '@govbr-ds/webcomponents-react/ssr';

Para SSR clássico com React 18, mantenha a importação principal:

import { BrButton } from '@govbr-ds/webcomponents-react';

[!NOTE] O subpath ssr/ depende de @govbr-ds/webcomponents/dist/hydrate. Certifique-se de que o pacote @govbr-ds/webcomponents está instalado.

Documentações Complementares 📖​

Contribuindo 🤝​

Reportar Bugs/Problemas 🐛​

Abra uma issue: gitlab.com/.../issues/new

Commits 📝​

Padrões de branches e commits: gov.br/ds/wiki

Precisa de ajuda? 🆘​

Créditos 🎉​

Desenvolvido pelo SERPRO com a comunidade.

Comece aquiComponentesQuickstartsSobre o projetoRepositório GitLabVersõesDiscordGovBR-DSFAQWikiRedefinir cookies