Padronizar o componente de input de CPF no design system elimina implementações inconsistentes entre equipes, centraliza a validação (sintática e via API) em um único lugar e garante que qualquer correção se propague automaticamente para todos os produtos da empresa. Um componente bem especificado inclui cinco estados visuais, suporte a validação via API e tokens de design para bordas e mensagens de erro.
Introdução
Em empresas com múltiplos produtos e equipes de desenvolvimento, o campo de CPF aparece em dezenas de formulários diferentes: cadastro de clientes, checkout, onboarding de funcionários, emissão de notas fiscais. Sem um componente padronizado, cada equipe implementa o campo à sua maneira -- com validações diferentes, máscaras inconsistentes e mensagens de erro que variam de um produto para outro.
Quando combinado com uma API como a CPFHub.io, o componente passa a fazer validação real dos dados cadastrais — nome e data de nascimento — além da validação sintática dos dígitos verificadores. Essa combinação elimina cadastros com CPFs inválidos ou pertencentes a terceiros.
Por que padronizar o input de CPF no design system
Um design system é uma coleção de componentes reutilizáveis, padrões e diretrizes que garantem consistência visual e funcional em todos os produtos de uma empresa. O input de CPF é um dos componentes mais importantes para empresas brasileiras, e padronizá-lo traz benefícios concretos:
-
Consistência de UX -- O usuário tem a mesma experiência ao informar o CPF em qualquer produto da empresa.
-
Manutenção centralizada -- Correções de bugs e melhorias são aplicadas uma vez e propagadas automaticamente.
-
Redução de retrabalho -- Equipes não precisam reimplementar validação, máscara e mensagens de erro.
-
Qualidade garantida -- Testes unitários e de acessibilidade são escritos uma vez para o componente compartilhado.
-
Integração padronizada -- A chamada à API de validação segue o mesmo padrão em todos os contextos.
Especificação do componente
Antes de codificar, documente a especificação do componente no design system.
Props (propriedades)
| Prop | Tipo | Default | Descrição |
|---|---|---|---|
| value | string | "" | Valor atual do campo |
| onChange | function | - | Callback quando o valor muda |
| onValidate | function | - | Callback quando a validação é concluída |
| validateOnBlur | boolean | true | Se deve validar ao sair do campo |
| validateViaAPI | boolean | false | Se deve consultar a API para validação real |
| apiKey | string | - | Chave da API (obrigatório se validateViaAPI=true) |
| disabled | boolean | false | Se o campo está desabilitado |
| helperText | string | "" | Texto auxiliar abaixo do campo |
| required | boolean | false | Se o campo é obrigatório |
Estados visuais
O componente deve suportar cinco estados visuais:
-
Default -- Campo vazio, borda neutra.
-
Focused -- Campo em foco, borda azul.
-
Loading -- Validação via API em andamento, ícone de loading.
-
Success -- CPF validado, borda verde com ícone de check.
-
Error -- Validação falhou, borda vermelha com mensagem de erro.
Implementação do componente em React
import { useState, useCallback } from 'react';
function InputCPF({
value = '',
onChange,
onValidate,
validateOnBlur = true,
validateViaAPI = false,
apiKey = '',
disabled = false,
helperText = '',
required = false,
}) {
const [status, setStatus] = useState('default');
const [mensagem, setMensagem] = useState('');
const aplicarMascara = (valor) => {
const numeros = valor.replace(/\D/g, '').slice(0, 11);
if (numeros.length <= 3) return numeros;
if (numeros.length <= 6) return `${numeros.slice(0, 3)}.${numeros.slice(3)}`;
if (numeros.length <= 9)
return `${numeros.slice(0, 3)}.${numeros.slice(3, 6)}.${numeros.slice(6)}`;
return `${numeros.slice(0, 3)}.${numeros.slice(3, 6)}.${numeros.slice(6, 9)}-${numeros.slice(9)}`;
};
const validarSintatico = (cpf) => {
const limpo = cpf.replace(/\D/g, '');
if (limpo.length !== 11) return { valido: false, erro: 'O CPF precisa ter 11 dígitos.' };
if (/^(\d)\1{10}$/.test(limpo)) return { valido: false, erro: 'CPF inválido.' };
let soma = 0;
for (let i = 0; i < 9; i++) soma += parseInt(limpo[i]) * (10 - i);
let resto = (soma * 10) % 11;
if (resto === 10) resto = 0;
if (resto !== parseInt(limpo[9])) return { valido: false, erro: 'Dígitos verificadores incorretos.' };
soma = 0;
for (let i = 0; i < 10; i++) soma += parseInt(limpo[i]) * (11 - i);
resto = (soma * 10) % 11;
if (resto === 10) resto = 0;
if (resto !== parseInt(limpo[10])) return { valido: false, erro: 'Dígitos verificadores incorretos.' };
return { valido: true };
};
const validarViaAPI = useCallback(async (cpf) => {
const limpo = cpf.replace(/\D/g, '');
setStatus('loading');
setMensagem('Verificando CPF...');
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000);
const response = await fetch(
`https://api.cpfhub.io/cpf/${limpo}`,
{
headers: {
'x-api-key': apiKey,
'Accept': 'application/json'
},
signal: controller.signal
}
);
clearTimeout(timeout);
const resultado = await response.json();
if (resultado.success) {
setStatus('success');
setMensagem('CPF verificado com sucesso.');
onValidate?.({ valido: true, dados: resultado.data });
} else {
setStatus('error');
setMensagem('CPF não encontrado na base.');
onValidate?.({ valido: false });
}
} catch {
setStatus('error');
setMensagem('Erro na verificação. Tente novamente.');
onValidate?.({ valido: false });
}
}, [apiKey, onValidate]);
const handleBlur = () => {
if (!validateOnBlur) return;
const resultado = validarSintatico(value);
if (!resultado.valido) {
setStatus('error');
setMensagem(resultado.erro);
onValidate?.({ valido: false });
return;
}
if (validateViaAPI) {
validarViaAPI(value);
} else {
setStatus('success');
setMensagem('Formato válido.');
onValidate?.({ valido: true });
}
};
return (
<div className={`input-cpf input-cpf--${status}`}>
<label className="input-cpf__label">
CPF {required && <span className="input-cpf__required">*</span>}
</label>
<input
type="text"
inputMode="numeric"
placeholder="000.000.000-00"
value={aplicarMascara(value)}
onChange={(e) => {
setStatus('default');
setMensagem('');
onChange?.(e.target.value.replace(/\D/g, ''));
}}
onBlur={handleBlur}
disabled={disabled}
aria-invalid={status === 'error'}
aria-describedby="cpf-helper"
/>
<span id="cpf-helper" className="input-cpf__helper">
{mensagem || helperText}
</span>
</div>
);
}
export default InputCPF;
Tokens de design para o componente
No design system, defina tokens específicos para cada estado visual do componente:
:root {
/* Cores de borda por estado */
--input-cpf-border-default: #d1d5db;
--input-cpf-border-focus: #3b82f6;
--input-cpf-border-success: #22c55e;
--input-cpf-border-error: #ef4444;
/* Cores de texto de mensagem */
--input-cpf-text-helper: #6b7280;
--input-cpf-text-success: #16a34a;
--input-cpf-text-error: #dc2626;
/* Espaçamentos */
--input-cpf-padding: 12px;
--input-cpf-gap: 4px;
--input-cpf-border-radius: 6px;
}
Esses tokens garantem que qualquer mudança visual (como atualização de cores da marca) se propague automaticamente para todos os inputs de CPF na empresa.
Documentação no design system
O componente deve ter uma página dedicada na documentação do design system com:
-
Exemplos interativos -- Demonstrações de cada estado visual.
-
Tabela de props -- Todas as propriedades com tipos, defaults e descrições.
-
Diretrizes de uso -- Quando usar validação local vs. validação via API.
-
Acessibilidade -- Checklist de requisitos ARIA e navegação por teclado. O guia WCAG do W3C define os critérios mínimos de acessibilidade para campos de formulário.
-
Código de exemplo -- Snippet para copiar e usar em cada framework suportado.
Testes do componente
Inclua testes unitários que cubram os cenários principais:
-
Máscara -- Verifica se o valor "12345678900" é exibido como "123.456.789-00".
-
Validação sintática -- Testa CPFs válidos e inválidos.
-
Validação via API -- Usa mocks para simular respostas de sucesso e erro.
-
Estados visuais -- Verifica se as classes CSS corretas são aplicadas em cada estado.
-
Acessibilidade -- Confirma que
aria-invalidearia-describedbyestão presentes.
Perguntas frequentes
Quando usar validação sintática versus validação via API no componente?
Use validação sintática (dígitos verificadores) no onChange ou onBlur para feedback imediato e sem custo de API. Ative validateViaAPI apenas em contextos críticos — como cadastro de conta ou checkout — onde é necessário confirmar que o CPF pertence a uma pessoa real e que o nome informado corresponde ao titular.
Como evitar chamadas desnecessárias à API quando o usuário ainda está digitando?
Ative a validação via API somente no evento onBlur (saída do campo), não no onChange. Isso garante que a chamada ocorra apenas quando o usuário terminar de digitar, economizando consultas e melhorando a experiência.
A API bloqueia requisições quando o limite de consultas é atingido?
Não. A API da CPFHub.io não retorna erro de bloqueio ao atingir o limite do plano. Quando o limite gratuito (50 consultas/mês) é superado, cada consulta adicional é cobrada a R$0,15 automaticamente. Para componentes com alto volume de validações, o plano Pro oferece 1.000 consultas mensais por R$149.
Como tratar a prop apiKey com segurança no componente React?
A apiKey nunca deve ser passada diretamente do front-end. O componente deve receber a chave via prop injetada por um backend (BFF ou API route), ou a chamada à API deve ser delegada a um endpoint server-side. Expor a chave no bundle JavaScript permite que qualquer usuário extraia e abuse dela.
Conclusão
Padronizar o componente de input de CPF no design system é um investimento que paga dividendos em consistência, qualidade e produtividade. Com um componente único e bem documentado, todas as equipes da empresa compartilham a mesma validação, a mesma experiência visual e a mesma integração com API.
A CPFHub.io oferece a API de validação cadastral que alimenta o componente — retornando nome, gênero e data de nascimento em tempo real, com plano gratuito sem cartão de crédito.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre validação real de CPF ao componente do seu design system.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



