Pular para o conteúdo
UIv1.0.0
CSS-first · Sem frameworks

Uma base visual.
Todos os componentes.

Construa interfaces com HTML nativo, vermelho VEXARO e uma API que acompanha seu projeto.

Começar agora Ver dashboard

Introdução

VEXARO UI é uma biblioteca CSS-first sem frameworks. A identidade padrão usa vermelho, preto e branco, com cantos retos em todos os componentes. Verde e âmbar comunicam sucesso e aviso.

Use HTML semântico, CSS nativo e JavaScript apenas para interações. A versão 1.0.0 entrega todos os componentes dos cards VEX-UI-001 a VEX-UI-018, incluindo controles avançados e integração opcional.

Compatibilidade alvo: versões atuais de Chrome, Firefox, Edge e Safari com CSS Grid, dialog.showModal(), inert e ES Modules. Datepicker usa o calendário nativo do navegador; a aparência e os atalhos variam por plataforma. Consulte o contrato público e as alterações.

Quick Start

Copie os dois arquivos de dist/ para o projeto. Eles são independentes dos fontes. Em um servidor estático, use:

<!doctype html>
<html lang="pt-BR" data-vx-theme="light">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="dist/vexaro.css">
  <script type="module" src="dist/vexaro.js"></script>
  <title>Meu projeto VEXARO</title>
</head>
<body>
  <main class="vx-container vx-py-8">
    <h1>Meu projeto</h1>
    <button class="vx-btn" type="button" data-vx-toggle="toast"
      data-vx-message="Tudo pronto!">Testar notificação</button>
  </main>
</body>
</html>

Para abrir diretamente por file://, ou integrar com scripts clássicos, substitua o script por:

<script defer src="dist/vexaro.global.js"></script>

A versão clássica expõe window.Vexaro. As duas versões inicializam os atributos data-vx-* automaticamente. Carregue apenas uma delas. Alternativamente, use css/vexaro.css e js/vexaro.js, preservando as pastas de origem.

O reset/reboot é global: normaliza box-sizing, margens, controles, tipografia e foco. Os componentes, utilitários e tokens têm prefixo vx-.

Design tokens

Tokens semânticos acompanham o tema. O vermelho primário é #b91c1c no claro e #ff3333 no escuro. Use --vx-color-primary em vez de fixar uma cor primitiva. Todos os raios de borda são 0 por padrão.

Cores primitivas

TokenValorPrévia
--vx-white#ffffff
--vx-black#000000
--vx-neutral-50#fafafa
--vx-neutral-100#f5f5f5
--vx-neutral-200#e5e5e5
--vx-neutral-400#a3a3a3
--vx-neutral-500#737373
--vx-neutral-600#525252
--vx-neutral-900#171717
--vx-red-400#f87171
--vx-red-500#ff3333
--vx-red-700#b91c1c
--vx-slate-50#f8fafc
--vx-slate-100#f1f5f9
--vx-slate-200#e2e8f0
--vx-slate-400#94a3b8
--vx-slate-500#64748b
--vx-slate-600#475569
--vx-slate-800#1e293b
--vx-slate-900#0f172a
--vx-blue-300#93c5fd
--vx-blue-700#1d4ed8
--vx-green-300#86efac
--vx-green-800#166534
--vx-amber-300#fcd34d
--vx-amber-900#78350f
--vx-red-300#fca5a5
--vx-red-800#991b1b

Espaçamento

TokenValorPrévia
--vx-space-00
--vx-space-10.25rem
--vx-space-20.5rem
--vx-space-30.75rem
--vx-space-41rem
--vx-space-51.25rem
--vx-space-61.5rem
--vx-space-82rem
--vx-space-102.5rem
--vx-space-123rem
--vx-space-164rem

Tipografia

TokenValorPrévia
--vx-font-sanssystem-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif
--vx-font-monoui-monospace, SFMono-Regular, Consolas, monospace
--vx-text-xs0.75rem
--vx-text-sm0.875rem
--vx-text-md1rem
--vx-text-lg1.125rem
--vx-text-xl1.25rem
--vx-text-2xl1.5rem
--vx-text-3xl2rem
--vx-text-4xl2.5rem
--vx-font-normal400
--vx-font-medium500
--vx-font-semibold600
--vx-font-bold700
--vx-leading-tight1.25
--vx-leading-normal1.5
--vx-leading-relaxed1.75

Bordas e foco

TokenValorPrévia
--vx-border-width1px
--vx-border-width-thick2px
--vx-radius-none0
--vx-radius-sm0
--vx-radius-md0
--vx-radius-lg0
--vx-radius-pill0
--vx-focus-width3px
--vx-focus-offset3px

Sombras

TokenValorPrévia
--vx-shadow-nonenone
--vx-shadow-sm0 1px 3px rgb(0 0 0 / 0.12)
--vx-shadow-md0 4px 12px rgb(0 0 0 / 0.16)
--vx-shadow-lg0 12px 32px rgb(0 0 0 / 0.2)

Cores semânticas

TokenClaroEscuro
--vx-color-bgvar(--vx-white)var(--vx-black)
--vx-color-surfacevar(--vx-white)var(--vx-neutral-900)
--vx-color-surface-mutedvar(--vx-neutral-100)var(--vx-black)
--vx-color-textvar(--vx-black)var(--vx-white)
--vx-color-text-mutedvar(--vx-neutral-600)var(--vx-neutral-200)
--vx-color-bordervar(--vx-neutral-500)var(--vx-neutral-400)
--vx-color-primaryvar(--vx-red-700)var(--vx-red-500)
--vx-color-on-primaryvar(--vx-white)var(--vx-black)
--vx-color-successvar(--vx-green-800)var(--vx-green-300)
--vx-color-on-successvar(--vx-white)var(--vx-black)
--vx-color-warningvar(--vx-amber-900)var(--vx-amber-300)
--vx-color-on-warningvar(--vx-white)var(--vx-black)
--vx-color-dangervar(--vx-red-800)var(--vx-red-300)
--vx-color-on-dangervar(--vx-white)var(--vx-black)
--vx-color-focusvar(--vx-red-700)var(--vx-red-500)

Temas

O tema claro é padrão. Defina o atributo no HTML ou em um contêiner. Temas locais mantêm suas cores quando o tema da página muda.

JavaScript: não

Claro

Vermelho, preto e branco.

Escuro

Vermelho forte sobre preto.

<div class="vx-grid">
  <article class="vx-card vx-col-12 vx-col-md-6" data-vx-theme="light">
    <div class="vx-card-body"><h3>Claro</h3><p>Vermelho, preto e branco.</p><button class="vx-btn" type="button">Ação principal</button></div>
  </article>
  <article class="vx-card vx-col-12 vx-col-md-6" data-vx-theme="dark">
    <div class="vx-card-body"><h3>Escuro</h3><p>Vermelho forte sobre preto.</p><button class="vx-btn" type="button">Ação principal</button></div>
  </article>
</div>
Classe / atributoUso
data-vx-theme="light|dark"Tema global ou local; funciona sem JS.
data-vx-toggle="theme"Botão de alternância; requer JS.

Personalização

Carregue seu CSS depois da biblioteca e sobrescreva os pares de cor juntos. Temas explícitos redefinem cores no próprio escopo; personalize cada seletor necessário.

:root, [data-vx-theme="light"] {
  --vx-color-primary: #a31515;
  --vx-color-on-primary: #ffffff;
}
[data-vx-theme="dark"] {
  --vx-color-primary: #ff3333;
  --vx-color-on-primary: #000000;
}

As cores primitivas azuis e slate permanecem disponíveis por compatibilidade; a identidade padrão usa vermelho e neutros. Alterações de paleta exigem nova validação de contraste. Escalas em rem acompanham a fonte raiz.

Container e grid

CSS Grid para layouts bidimensionais. Comece com 12 colunas no mobile e sobrescreva spans em breakpoints maiores.

JavaScript: não

4 colunas no tablet
8 colunas no tablet
<div class="vx-container-fluid">
  <div class="vx-grid vx-gap-4">
    <div class="vx-card vx-col-12 vx-col-md-4 vx-p-4">4 colunas no tablet</div>
    <div class="vx-card vx-col-12 vx-col-md-8 vx-p-4">8 colunas no tablet</div>
  </div>
</div>
Classe / atributoUso
vx-container / vx-container-fluidLargura máxima responsiva / largura total, com padding lateral.
vx-grid / vx-grid-cols-12Grid de 12 colunas; gap padrão space-4.
vx-col-1 … vx-col-12Número de colunas ocupadas.
vx-col-{sm|md|lg|xl|xxl}-{1…12}Spans por breakpoint mínimo.
Breakpointssm 576px · md 768px · lg 992px · xl 1200px · xxl 1400px
Containers540 / 720 / 960 / 1140 / 1320px nos respectivos breakpoints.

Flexbox

Use Flexbox para barras de ações e alinhamentos em uma direção.

JavaScript: não

3 alterações salvas
<div class="vx-flex vx-flex-wrap vx-items-center vx-justify-between vx-gap-4 vx-w-full">
  <span class="vx-badge vx-badge-success">3 alterações salvas</span>
  <div class="vx-flex vx-gap-2"><button type="button" class="vx-btn vx-btn-secondary">Cancelar</button><button type="button" class="vx-btn">Salvar</button></div>
</div>
Classe / atributoUso
vx-flex / vx-flex-row / vx-flex-colExibição e direção.
vx-flex-wrap / vx-flex-nowrap / vx-flex-1 / vx-flex-noneQuebra e crescimento.
vx-justify-start|end|center|between|aroundAlinhamento principal.
vx-items-start|end|center|stretch / vx-self-centerAlinhamento cruzado.

Botões

Use button para ações e links para navegação. Rótulos visíveis explicam a ação.

JavaScript: não

<button class="vx-btn vx-btn-primary" type="button">Primário</button>
<button class="vx-btn vx-btn-secondary" type="button">Secundário</button>
<button class="vx-btn vx-btn-outline" type="button">Contorno</button>
<button class="vx-btn vx-btn-ghost" type="button">Ghost</button>
<button class="vx-btn vx-btn-success" type="button">Confirmar</button>
<button class="vx-btn vx-btn-danger" type="button">Excluir</button>
<button class="vx-btn vx-btn-sm" type="button">Pequeno</button>
<button class="vx-btn vx-btn-lg" type="button">Grande</button>
<button class="vx-btn" type="button" disabled>Indisponível</button>
<button class="vx-btn" type="button" aria-busy="true" disabled>Salvando…</button>
Classe / atributoUso
vx-btnBase; tamanho médio.
vx-btn-primary|secondary|outline|ghost|success|dangerVariantes semânticas.
vx-btn-sm / vx-btn-lgTamanhos.
disabled / aria-disabled="true"Bloqueio nativo / semântica. JS do VEXARO impede cliques em aria-disabled; sem JS, a aplicação deve impedir a ativação de links.
aria-busy="true"Indicador de carregamento. Use também disabled para bloquear ações repetidas.
--vx-color-primary / --vx-radius-mdCor principal e raio (0 por padrão).

Badges

Rótulos curtos para categorias e estados. A informação também aparece no texto.

JavaScript: não

Rascunho Em análise Publicado Pendente Falhou Contador: 12
<span class="vx-badge">Rascunho</span>
<span class="vx-badge vx-badge-primary">Em análise</span>
<span class="vx-badge vx-badge-success">Publicado</span>
<span class="vx-badge vx-badge-warning">Pendente</span>
<span class="vx-badge vx-badge-danger">Falhou</span>
<span class="vx-badge vx-badge-lg">Contador: 12</span>
Classe / atributoUso
vx-badgeBase neutra; estático.
vx-badge-primary|success|warning|dangerCor contextual.
vx-badge-lgTamanho maior.

Cards

Agrupe conteúdo com cabeçalho, corpo e rodapé opcionais.

JavaScript: não

Projeto VEXARO

Ativo

Uma base compartilhada entre aplicação e documentação.

<article class="vx-card vx-card-elevated">
  <header class="vx-card-header"><h3>Projeto VEXARO</h3></header>
  <div class="vx-card-body"><span class="vx-badge vx-badge-success">Ativo</span><p class="vx-mt-4">Uma base compartilhada entre aplicação e documentação.</p></div>
  <footer class="vx-card-footer"><a class="vx-btn" href="#quick-start">Começar projeto</a></footer>
</article>
Classe / atributoUso
vx-card / vx-card-header|body|footerSuperfície e estrutura.
vx-card-elevated / vx-card-borderless / vx-card-outlinedSombra, sem borda ou borda espessa.
--vx-color-surface / --vx-shadow-md / --vx-radius-lgTokens de aparência.

Alertas

Feedback estático não precisa de live region. Em atualizações dinâmicas, use role="status" para rotina e role="alert" somente para urgência.

JavaScript: não

Informação: sua sessão está ativa.
Sucesso: alterações salvas.
Atenção: revise os campos.
Erro: não foi possível salvar.
<div class="vx-alert vx-alert-info"><strong>Informação:</strong> sua sessão está ativa.</div>
<div class="vx-alert vx-alert-success"><strong>Sucesso:</strong> alterações salvas.</div>
<div class="vx-alert vx-alert-warning"><strong>Atenção:</strong> revise os campos.</div>
<div class="vx-alert vx-alert-danger"><strong>Erro:</strong> não foi possível salvar.</div>
Classe / atributoUso
vx-alertMensagem com padding e borda.
vx-alert-info|success|warning|dangerVariantes; combinam cor contextual e on-* correspondente.

Formulários

Controles nativos com labels e descrições associadas. A validação HTML5 continua funcionando sem JS.

JavaScript: não

Informe seu nome completo.
Preferências
Use um código com seis dígitos.
<form class="vx-w-full" data-docs-form>
  <div class="vx-field"><label class="vx-label" for="demo-name">Nome</label><input class="vx-input" id="demo-name" name="name" required autocomplete="name" aria-describedby="name-help"><span class="vx-help" id="name-help">Informe seu nome completo.</span></div>
  <div class="vx-field"><label class="vx-label" for="demo-email">E-mail</label><input class="vx-input" type="email" id="demo-email" name="email" required autocomplete="email"></div>
  <div class="vx-field"><label class="vx-label" for="demo-role">Perfil</label><select class="vx-select" id="demo-role" name="role"><option>Designer</option><option>Desenvolvedor</option></select></div>
  <div class="vx-field"><label class="vx-label" for="demo-message">Mensagem</label><textarea class="vx-textarea" id="demo-message" name="message"></textarea></div>
  <fieldset class="vx-p-4 vx-mb-4"><legend>Preferências</legend>
    <label class="vx-check"><input class="vx-checkbox" type="checkbox" name="news"> Receber novidades</label>
    <label class="vx-check"><input class="vx-radio" type="radio" name="plan" value="personal" checked> Pessoal</label>
    <label class="vx-check"><input class="vx-radio" type="radio" name="plan" value="team"> Equipe</label>
    <label class="vx-check"><input class="vx-switch" type="checkbox" role="switch" name="notifications"> Notificações</label>
  </fieldset>
  <div class="vx-field"><label class="vx-label" for="demo-invalid">Código com erro (exemplo estático)</label><input class="vx-input is-invalid" id="demo-invalid" value="ABC" aria-invalid="true" aria-describedby="code-error"><span class="vx-error" id="code-error">Use um código com seis dígitos.</span></div>
  <div class="vx-field"><label class="vx-label" for="demo-readonly">Identificador somente leitura</label><input class="vx-input" id="demo-readonly" value="VX-001" readonly></div>
  <div class="vx-field"><label class="vx-label" for="demo-disabled">Campo indisponível</label><input class="vx-input" id="demo-disabled" disabled value="Sem acesso"></div>
  <button class="vx-btn" type="submit">Validar formulário</button>
</form>
Classe / atributoUso
vx-field / vx-label / vx-help / vx-errorGrupo, rótulo, ajuda e erro.
vx-input / vx-textarea / vx-selectControles nativos.
vx-check / vx-checkbox / vx-radio / vx-switchSeleção e alternância.
:user-invalid / .is-invalid / .vx-validated :invalidErro após interação, explícito ou validação do formulário.
aria-invalid / aria-describedbyAssocie erro ao campo e atualize o estado na aplicação.

Tabelas

Use caption, cabeçalhos com scope e um wrapper focável quando houver rolagem horizontal.

JavaScript: não

Membros da equipe
NomePerfilStatus
AnaDesignAtiva
BrunoEngenhariaPendente
2 membros
<div class="vx-table-responsive" role="region" aria-label="Equipe" tabindex="0">
  <table class="vx-table vx-table-striped vx-table-bordered vx-table-hover vx-table-compact">
    <caption>Membros da equipe</caption><thead><tr><th scope="col">Nome</th><th scope="col">Perfil</th><th scope="col">Status</th></tr></thead>
    <tbody><tr><th scope="row">Ana</th><td>Design</td><td><span class="vx-badge vx-badge-success">Ativa</span></td></tr><tr><th scope="row">Bruno</th><td>Engenharia</td><td><span class="vx-badge vx-badge-warning">Pendente</span></td></tr></tbody>
    <tfoot><tr><td colspan="3">2 membros</td></tr></tfoot>
  </table>
</div>
Classe / atributoUso
vx-tableTabela base.
vx-table-striped|bordered|hover|compactVariantes combináveis.
vx-table-responsiveRolagem horizontal; tabindex=0 permite acesso por teclado.

Breadcrumb e paginação

Links reais representam destinos. A página atual usa aria-current="page"; itens indisponíveis não recebem href.

JavaScript: não

<nav aria-label="Trilha de navegação"><ol class="vx-breadcrumb"><li><a href="#inicio">Início</a></li><li><a href="#cards">Projetos</a></li><li aria-current="page">VEXARO UI</li></ol></nav>
<nav aria-label="Páginas de exemplo"><ol class="vx-pagination"><li><span aria-disabled="true">Anterior</span></li><li><a href="#contextual" aria-current="page">1</a></li><li><a href="#tabelas">2</a></li><li><a href="#tabelas">Próxima</a></li></ol></nav>
Classe / atributoUso
vx-breadcrumb / --vx-breadcrumb-separatorTrilha; separador padrão "/".
vx-paginationPaginação semântica.
aria-current="page" / aria-disabled="true"Página atual e item indisponível.
vx-tabs / vx-tab-item / vx-tab-link.is-activeAbas puramente visuais; use links para destinos e a versão JS para painéis.

Toast

Notificações dinâmicas com botão de descarte. O temporizador pausa com hover ou foco. Mensagens essenciais devem continuar disponíveis no conteúdo da página.

JavaScript: sim

<button class="vx-btn" type="button" data-vx-toggle="toast" data-vx-message="Projeto salvo com sucesso.">Mostrar notificação</button>
Classe / atributoUso
data-vx-toggle="toast" / data-vx-messageCria mensagem de texto com temporizador padrão de 5 segundos.
data-vx-toast / data-vx-targetPermite usar uma notificação existente.
data-vx-dismiss="toast"Descarte manual.
role="status" / role="alert"Anúncio de rotina / urgente.

API

const toast = Vexaro.Toast.show('Alterações salvas.', { duration: 5000 });
// duration: 0 mantém até descarte manual; urgent: true usa alert.
toast.close();
// Eventos: vx:toast:open, vx:toast:close

Tabs

Apenas uma aba participa da ordem de Tab. Setas alternam abas; Home e End vão à primeira e à última. Cada aba está associada ao próprio painel.

JavaScript: sim

Tudo pronto para começar.
<div class="vx-w-full">
  <div class="vx-tabs" role="tablist" aria-label="Detalhes do projeto" data-vx-tabs id="demo-tabs">
    <button class="vx-tab-link" role="tab" type="button" id="tab-overview" aria-controls="panel-overview" aria-selected="true">Visão geral</button>
    <button class="vx-tab-link" role="tab" type="button" id="tab-history" aria-controls="panel-history" aria-selected="false" tabindex="-1">Histórico</button>
  </div>
  <div class="vx-tab-panel" role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">Tudo pronto para começar.</div>
  <div class="vx-tab-panel" role="tabpanel" id="panel-history" aria-labelledby="tab-history" tabindex="0" hidden>Projeto criado hoje.</div>
</div>
Classe / atributoUso
data-vx-tabs / role="tablist"Grupo de abas.
vx-tab-link / role="tab" / aria-controlsBotão e painel associado.
vx-tab-panel / role="tabpanel" / aria-labelledbyPainel e título.
aria-orientation="vertical"Usa setas para cima e para baixo.

API

const tabs = Vexaro.getInstance('#demo-tabs');
tabs.select(1); // índice ou elemento de aba
// Evento: vx:tabs:change; detail.tab

Collapse e Accordion

A expansão anima a altura via CSS Grid. Conteúdo recolhido fica inert. Use single para manter apenas um item aberto; multiple permite vários.

JavaScript: sim

Não. Use HTML, CSS e JavaScript nativos.

Sim. Sobrescreva os tokens no seu CSS.

<div class="vx-accordion vx-w-full" data-vx-accordion="single">
  <h3 class="vx-accordion-heading"><button class="vx-btn vx-btn-secondary" type="button" data-vx-toggle="collapse" data-vx-target="#answer-one" aria-expanded="false" aria-controls="answer-one">Preciso de framework?</button></h3>
  <div class="vx-collapse" data-vx-collapse id="answer-one"><div class="vx-collapse-inner"><p class="vx-p-4">Não. Use HTML, CSS e JavaScript nativos.</p></div></div>
  <h3 class="vx-accordion-heading"><button class="vx-btn vx-btn-secondary" type="button" data-vx-toggle="collapse" data-vx-target="#answer-two" aria-expanded="false" aria-controls="answer-two">Posso personalizar?</button></h3>
  <div class="vx-collapse" data-vx-collapse id="answer-two"><div class="vx-collapse-inner"><p class="vx-p-4">Sim. Sobrescreva os tokens no seu CSS.</p></div></div>
</div>
Classe / atributoUso
data-vx-collapse / vx-collapse / vx-collapse-innerPainel e filho interno obrigatório.
data-vx-toggle="collapse" / data-vx-targetDisparador.
data-vx-accordion="single|multiple"Modo exclusivo ou múltiplo.
is-openEstado inicial aberto.

API

const collapse = Vexaro.getInstance('#answer-one');
collapse.open(); collapse.close(); collapse.toggle();
// Eventos: vx:collapse:open, vx:collapse:close

Tooltip

Informação complementar disponível ao focar e passar o mouse. Escape descarta. A dica aceita hover; conteúdo essencial deve continuar visível na página.

JavaScript: sim

<span class="vx-tooltip-wrap"><button class="vx-btn vx-btn-secondary" type="button" data-vx-toggle="tooltip" data-vx-target="#demo-tip">Ajuda sobre tokens</button><span class="vx-tooltip" id="demo-tip" role="tooltip" hidden>Tokens são variáveis CSS compartilhadas.</span></span>
Classe / atributoUso
vx-tooltip-wrap / vx-tooltipPosicionamento e conteúdo.
data-vx-toggle="tooltip" / data-vx-targetDisparador.
aria-describedbyPreserva descrições existentes e acrescenta a dica.

API

const tip = Vexaro.getInstance('[data-vx-toggle="tooltip"]');
tip.open(); tip.close();
// Eventos: vx:tooltip:open, vx:tooltip:close

Popover

Conteúdo complementar acionado por clique. Escape e clique externo fecham. O foco segue a ordem natural; o popover não é modal.

JavaScript: sim

<button class="vx-btn vx-btn-secondary" type="button" data-vx-toggle="popover" data-vx-target="#demo-popover" aria-controls="demo-popover" aria-expanded="false">Sobre a versão</button>
<div class="vx-popover" id="demo-popover" role="region" aria-labelledby="popover-title" hidden><h3 id="popover-title">VEXARO UI 1.0</h3><p>CSS-first, componentes nativos e API pública documentada.</p></div>
Classe / atributoUso
vx-popoverPainel fixo reposicionado no viewport.
data-vx-toggle="popover" / data-vx-targetDisparador.
aria-controls / aria-expandedAssociação e estado.

API

const popover = Vexaro.getInstance('[data-vx-toggle="popover"]');
popover.open(); popover.close(); popover.toggle();
// Eventos: vx:popover:open, vx:popover:close

Datepicker

Seleção de data nativa. O navegador fornece localização, navegação do calendário e teclado. O valor público usa YYYY-MM-DD; min, max e required seguem HTML5.

JavaScript: sim

Escolha uma data entre 2026 e 2030.
<div class="vx-field vx-w-full"><label class="vx-label" for="demo-date">Prazo</label><input class="vx-input" type="date" id="demo-date" data-vx-datepicker min="2026-01-01" max="2030-12-31" aria-describedby="date-help"><span class="vx-help" id="date-help">Escolha uma data entre 2026 e 2030.</span></div>
Classe / atributoUso
input[type="date"] / vx-input / data-vx-datepickerCalendário nativo com API opcional.
min / max / requiredRestrições nativas.
valueFormato ISO; valores fora dos limites lançam RangeError na API.

API

const date = Vexaro.getInstance('#demo-date');
date.value = '2026-12-01';
// date.open() deve ser chamado durante uma ação do usuário.
// Evento: vx:datepicker:change; detail.value

Autocomplete / Combobox

Lista filtrada por texto com foco mantido no campo. Setas navegam, Enter seleciona e Escape fecha. Aceita texto livre; valide opções obrigatórias na aplicação.

JavaScript: sim

Digite para filtrar e use as setas para selecionar.
<div class="vx-combobox vx-w-full" data-vx-combobox id="demo-combobox">
  <label class="vx-label" for="demo-city">Cidade</label><input class="vx-input" id="demo-city" aria-describedby="city-help">
  <span class="vx-help" id="city-help">Digite para filtrar e use as setas para selecionar.</span>
  <ul class="vx-combobox-list" role="listbox" aria-label="Cidades" id="city-options" hidden><li role="option">São Paulo</li><li role="option">Rio de Janeiro</li><li role="option">Belo Horizonte</li><li role="option">Curitiba</li></ul>
</div>
Classe / atributoUso
data-vx-combobox / vx-comboboxContêiner.
input / [role="listbox"] / [role="option"]Campo e opções de texto.
aria-expanded / aria-activedescendant / aria-selectedGerenciados pelo componente.

API

const combo = Vexaro.getInstance('#demo-combobox');
combo.open(); combo.close();
// Evento: vx:combobox:change; detail.value
// Em uma instância manual: new Vexaro.Combobox(element, { options: ['A', 'B'] })

Slider

Range nativo com valor visível sincronizado. Setas, Home e End são fornecidos pelo navegador.

JavaScript: sim

<div class="vx-field vx-w-full"><label class="vx-label" for="demo-range">Volume: <output id="range-value" for="demo-range">40</output>%</label><input class="vx-range" type="range" id="demo-range" min="0" max="100" step="5" value="40" data-vx-slider data-vx-output="#range-value"></div>
Classe / atributoUso
vx-range / input[type="range"] / data-vx-sliderControle nativo.
data-vx-outputSeletor de output associado.
min / max / stepLimites e incremento.

API

const slider = Vexaro.getInstance('#demo-range');
slider.value = 75;
// Evento: vx:slider:change; detail.value (número)

Tabela com ordenação e paginação

Ordenação local de linhas já carregadas. A paginação exibe uma faixa de linhas e anuncia a página atual; não realiza requisições ao servidor.

JavaScript: sim

Projetos — clique nos cabeçalhos para ordenar
VEXARO18
Atlas7
Norte12
Centro3
Sul9
<div class="vx-w-full">
  <div class="vx-table-responsive" role="region" aria-label="Projetos ordenáveis" tabindex="0"><table class="vx-table vx-table-striped" id="demo-data-table" data-vx-table data-vx-page-size="2" data-vx-pagination="#table-pages">
    <caption>Projetos — clique nos cabeçalhos para ordenar</caption><thead><tr><th scope="col"><button type="button" data-vx-sort="text">Projeto</button></th><th scope="col"><button type="button" data-vx-sort="number">Tarefas</button></th></tr></thead>
    <tbody><tr><th scope="row">VEXARO</th><td>18</td></tr><tr><th scope="row">Atlas</th><td>7</td></tr><tr><th scope="row">Norte</th><td>12</td></tr><tr><th scope="row">Centro</th><td>3</td></tr><tr><th scope="row">Sul</th><td>9</td></tr></tbody>
  </table></div>
  <nav class="vx-flex vx-flex-wrap vx-items-center vx-gap-3 vx-mt-4" id="table-pages" aria-label="Páginas dos projetos"><button type="button" class="vx-btn vx-btn-secondary vx-btn-sm" data-vx-page="prev">Anterior</button><span data-vx-page-status role="status"></span><button type="button" class="vx-btn vx-btn-secondary vx-btn-sm" data-vx-page="next">Próxima</button></nav>
</div>
Classe / atributoUso
data-vx-table / data-vx-page-size / data-vx-paginationTabela, tamanho da página e controles.
data-vx-sort="text|number"Botão de ordenação dentro de th.
data-vx-valueValor opcional na célula para ordenar números formatados.
data-vx-page="prev|next" / data-vx-page-statusControles e anúncio da paginação.

API

const table = Vexaro.getInstance('#demo-data-table');
table.sort(1, 'descending', 'number');
table.goTo(2);
// Eventos: vx:table:sort (column, direction), vx:table:page (page)

Utilities

Utilitários são opcionais e carregados depois dos componentes. A escala disponível é 0, 1, 2, 3, 4, 5, 6, 8, 10, 12 e 16, referenciando --vx-space-*.

Classe / atributoUso
vx-d-none|block|inline|inline-block|flex|gridDisplay; !important para sobrepor o display do componente.
vx-m-* / vx-p-* / vx-gap-*Margem, padding e gap.
vx-mx-* / vx-my-* / vx-px-* / vx-py-*Eixos inline e block.
vx-mt-* / vx-mb-* / vx-ms-* / vx-me-* / vx-pt-* / vx-pb-*Lados; ms/me seguem a direção de escrita.
vx-m-auto / vx-mx-auto / vx-ms-autoMargens automáticas.
vx-d-md-flex / vx-p-lg-8 / vx-gap-sm-4Responsivos: mesmo conjunto sm/md/lg/xl/xxl.
vx-flex-md-row / vx-flex-lg-colDireção responsiva.
vx-text-start|center|end / vx-text-muted / vx-w-fullTexto e largura.
vx-visible / vx-invisible / vx-sr-onlyVisibilidade e conteúdo somente para leitores de tela.
<div class="vx-d-none vx-d-md-flex vx-gap-4 vx-p-4 vx-p-lg-8">
  Visível a partir de 768px; padding maior a partir de 992px.
</div>

JavaScript e ciclo de vida

A entrada ESM exporta classes, versão e funções de ciclo de vida. A entrada global expõe os mesmos membros em Vexaro. Inicialização automática acontece uma vez ao carregar a página; para conteúdo adicionado depois, chame init novamente.

import { init, destroy, getInstance, Modal, Toast, setTheme } from './dist/vexaro.js';
const area = document.querySelector('#minha-area');
init(area); // idempotente: não duplica listeners ou instâncias
const modal = getInstance('#meu-modal');
modal.open();
modal.close();
Toast.show('Salvo.', { duration: 5000 });
setTheme('dark');
destroy(area); // remove listeners, temporizadores e referências antes de desmontar
// Ao voltar a montar: init(area)
// Instâncias manuais devem receber instance.destroy() explicitamente.
Classe / atributoUso
init(scope = document)Retorna as novas instâncias; inclui o próprio scope se corresponder.
getInstance(element|selector)Retorna instância auto-inicializada ou null.
destroy(scope = document)Destrói instâncias registradas dentro do escopo.
instance.destroy()Remove listeners e recursos de uma instância; não a reutilize após destroy.
setTheme("light"|"dark", element?)Atualiza tema e dispara vx:theme:change.
vx:init:errorErro de marcação: detail.error e registro no console.
Eventos vx:*CustomEvent com bubbles=true. Dados específicos em detail.

A API de cada componente está na respectiva seção. Apenas Modal deve prender o foco, enquanto estiver aberto. A biblioteca não injeta HTML de mensagens: textos de toast e combobox usam textContent.

Integrações e API estável

A API pública está congelada na versão 1.0.0 conforme API.md. Classes, tokens e métodos documentados só podem ser removidos ou mudar de significado em uma versão major. Adições compatíveis usam minor; correções usam patch.

Em React, Vue e Svelte, importe o CSS uma vez e inicialize os componentes após montar o DOM. Chame destroy antes de desmontar. Use getInstance para componentes auto-inicializados; não crie uma segunda instância manual no mesmo elemento. Consulte os exemplos por framework.

import { init, destroy } from './dist/vexaro.js';
// Após montar:
init(container);
// Antes de desmontar:
destroy(container);

Web Component opcional, sem Shadow DOM

import { registerVexaroElements } from './integrations/web-components.js';
registerVexaroElements();
<vx-components>
  <button class="vx-btn" type="button" data-vx-toggle="toast"
    data-vx-message="Integração pronta.">Testar</button>
</vx-components>

O adaptador observa conexão e desconexão. Para conteúdo inserido depois dentro do elemento, chame element.refresh(). Ele não é importado pelo núcleo e não exige framework ou Shadow DOM.

Acessibilidade e qualidade

Use uma ordem coerente de títulos, labels visíveis e descrições associadas. Tab e Shift+Tab percorrem controles; Enter e Espaço ativam botões. Setas controlam abas, dropdowns, combobox e ranges. Escape fecha modal, dropdown, tooltip e popover.

Os 38 pares de contraste dos tokens são verificados: texto e cores semânticas com no mínimo 4,5:1; bordas e foco sobre fundos fornecidos com 3:1. Estados desabilitados têm opacidade reduzida. Cores personalizadas, imagens e combinações arbitrárias exigem avaliação própria.

Movimento reduzido desativa animações. O modal usa dialog nativo e devolve o foco ao fechar; painéis recolhidos ficam inert. Datepicker e range usam semântica e teclado do navegador. A biblioteca não certifica automaticamente a conformidade WCAG de uma aplicação.

node scripts/build.mjs
npm test
node scripts/browser-check.mjs
# Após instalar dependências de desenvolvimento:
npm run test:browser
npm run test:visual:update

O teste de navegador local usa Chrome headless e CDP; a suíte Playwright cobre Chromium e Firefox, screenshots e axe-core. A revisão humana de leitor de tela, ampliação e conteúdo final permanece necessária.

Abrir dashboard de exemplo

Changelog / versão

1.0.0 · 26 de outubro de 2026

  • Fundação CSS completa: reset/reboot, grid, Flexbox, tokens e utilitários responsivos.
  • Formulários, tabelas, navegação e componentes visuais com cantos retos.
  • Modal, toast, dropdown, tabs, collapse, tooltip e popover com API e eventos públicos.
  • Datepicker e slider nativos, combobox filtrável, tabela ordenável e paginada.
  • Catálogo com busca, demos copiáveis, dashboard e distribuição ESM/global.
  • Contrato de API estável e integração opcional sem Shadow DOM.

Consulte CHANGELOG.md para o histórico e o board para o estado de revisão.

VEXARO UI · Construído com os próprios componentes da biblioteca.