components.md 8.6 KB

Design System — Componentes Base

Componentes em src/components/base/. São a base de toda a UI — sempre prefira esses componentes a elementos HTML nativos.


BaseButton

Arquivo: src/components/base/BaseButton.vue

Botão com suporte a variantes, tamanhos e estado de carregamento.

Props

Prop Tipo Padrão Valores aceitos
variant String "primary" "primary" · "secondary" · "ghost" · "danger"
size String "md" "sm" · "md" · "lg"
type String "button" "button" · "submit" · "reset"
disabled Boolean false
loading Boolean false Exibe spinner e bloqueia cliques

Variantes

Variante Uso
primary Ação principal da tela (submit, confirmar)
secondary Ação secundária, menos destaque
ghost Ação discreta, sem borda ou fundo visível
danger Ações destrutivas (excluir, revogar)

Exemplos

<BaseButton>Salvar</BaseButton>

<BaseButton variant="secondary" size="sm">Cancelar</BaseButton>

<BaseButton variant="danger" :loading="salvando" @click="excluir">
  Excluir
</BaseButton>

<BaseButton type="submit" :disabled="!formValido">Enviar</BaseButton>

BaseInput

Arquivo: src/components/base/BaseInput.vue

Campo de texto com suporte a label, hint e mensagem de erro. Compatível com v-model.

Props

Prop Tipo Padrão Descrição
modelValue String "" Valor do campo (use com v-model)
label String "" Rótulo exibido acima do input
hint String "" Texto de ajuda abaixo do campo
error String "" Mensagem de erro (substitui hint quando preenchida)
id String "" ID do input; gerado automaticamente se omitido

Aceita todos os atributos HTML nativos de <input> via v-bind="$attrs" (ex: placeholder, type, autocomplete).

Exemplos

<BaseInput v-model="nome" label="Nome completo" placeholder="Ex: João Silva" />

<BaseInput
  v-model="email"
  label="E-mail"
  type="email"
  hint="Usado para login no sistema"
  :error="erros.email"
/>

<BaseInput v-model="senha" label="Senha" type="password" />

BaseBadge

Arquivo: src/components/base/BaseBadge.vue

Chip/etiqueta para exibir status, categorias ou contadores.

Props

Prop Tipo Padrão Valores aceitos
variant String "default" "default" · "success" · "danger" · "info" · "warning" · "violet"

Variantes

Variante Cor Uso sugerido
default Cinza Status genérico, neutro
success Verde Ativo, aprovado, concluído
danger Vermelho Inativo, erro, bloqueado
info Azul Informação, em andamento
warning Âmbar Alerta, pendente
violet Violeta Destaque especial, admin

Exemplos

<BaseBadge variant="success">Ativo</BaseBadge>

<BaseBadge variant="danger">Inativo</BaseBadge>

<BaseBadge variant="violet">Admin</BaseBadge>

<BaseBadge>Padrão</BaseBadge>

BaseDropdown

Arquivo: src/components/base/BaseDropdown.vue

Select customizado (não nativo), acessível (role="listbox"/"option", aria-expanded/aria-haspopup), fecha ao clicar fora ou pressionar Esc. Compatível com v-model.

Props

Prop Tipo Padrão Descrição
modelValue String "" Valor selecionado (use com v-model)
rotulo String — (obrigatório) Texto exibido antes do valor selecionado
rotuloPadrao String — (obrigatório) Texto quando nenhuma opção está selecionada (ex: "todos")
opcoes Array [] Lista de { value, label }

Emite change além de update:modelValue, útil para disparar buscas ao selecionar.

Exemplo

<BaseDropdown
  v-model="filtroSetor"
  rotulo="Setor"
  rotulo-padrao="todos"
  :opcoes="setores.map((s) => ({ value: s.sigla, label: s.nome }))"
  @change="aplicarFiltros"
/>

StatCard

Arquivo: src/components/base/StatCard.vue

Cartão de métrica (KPI) com ícone, valor em destaque e texto complementar opcional.

Props

Prop Tipo Padrão Valores aceitos
label String — (obrigatório) Rótulo da métrica
value String \| Number null Valor em destaque
suffix String "" Sufixo do valor (ex: " / 10")
variant String "default" "default" · "success" · "danger" · "info" · "warning" · "violet"

O slot #icon recebe o ícone (ideal: <BaseIcon>); o slot padrão (default) recebe um texto complementar abaixo do valor.

Exemplo

<StatCard label="Score médio" :value="stats.scoreMedio" suffix=" / 10" variant="info">
  <template #icon><BaseIcon :icon="Star" class="h-4 w-4" /></template>
  {{ stats.pendentes }} pendentes
</StatCard>

BaseIcon

Arquivo: src/components/base/BaseIcon.vue

Wrapper fino sobre ícones do Lucide (lucide-vue-next). Sempre prefira importar o ícone diretamente da lib (mantém tree-shaking) e passá-lo via prop icon, em vez de SVG inline copiado manualmente.

Props

Prop Tipo Padrão Descrição
icon Object \| Function — (obrigatório) Componente do ícone importado de lucide-vue-next
strokeWidth String \| Number 1.8 Espessura do traço

Tamanho e cor são controlados via class (ex: class="h-4 w-4 text-primary"), igual a um SVG comum.

Exemplo

<script setup>
import { Search } from "lucide-vue-next";
import BaseIcon from "@/components/base/BaseIcon.vue";
</script>

<template>
  <BaseIcon :icon="Search" class="h-4 w-4 text-muted-foreground" />
</template>

BaseModal

Arquivo: src/components/base/BaseModal.vue

Casca comum para modais: Teleport para body, backdrop, fecha com Esc ou clique fora, foco movido para dentro do modal ao abrir e preso nele (focus trap) enquanto aberto.

Props

Prop Tipo Padrão Descrição
title String "" Título exibido no cabeçalho padrão
maxWidth String "max-w-md" Classe Tailwind de largura máxima do painel
closeOnBackdrop Boolean true Fecha ao clicar fora do painel
closeDisabled Boolean false Bloqueia fechamento (ex: enquanto envia um formulário)
showClose Boolean true Exibe o botão "×" no cabeçalho

Slots

Slot Descrição
header Substitui o cabeçalho padrão (título + botão fechar)
default Conteúdo do corpo do modal
footer Rodapé opcional, com borda separadora

Exemplo

<BaseModal title="Editar usuário" :close-disabled="salvando" @close="fechar">
  <form class="grid gap-4 p-5" @submit.prevent="salvar">
    ...
  </form>
</BaseModal>

EmptyState

Arquivo: src/components/base/EmptyState.vue

Estado vazio padronizado (ícone tracejado + título + descrição), usado no lugar de cada view escrever seu próprio bloco "Nenhum item encontrado".

Props

Prop Tipo Padrão Descrição
icon Object \| Function null Ícone do Lucide exibido no topo
titulo String — (obrigatório) Texto principal
descricao String "" Texto secundário opcional
compacto Boolean false Reduz o padding vertical (para uso dentro de listas menores)

O slot padrão aceita uma ação (ex: um BaseButton) abaixo do texto.

Exemplo

<EmptyState
  :icon="History"
  titulo="Nenhuma conversa ainda"
  descricao="Suas conversas aparecerão aqui após a primeira mensagem."
/>

Spinner

Arquivo: src/components/base/Spinner.vue

Indicador de carregamento padronizado, para substituir o texto solto "Carregando..." repetido em várias views.

Props

Prop Tipo Padrão Valores aceitos
size String "md" "sm" · "md" · "lg"
label String "" Texto exibido ao lado do spinner
center Boolean false Centraliza horizontalmente com padding vertical (para loading de seção inteira)

Exemplo

<Spinner v-if="carregando" center label="Carregando avaliações..." />

Skeletons

Pasta: src/components/skeletons/

Componente Uso
SkeletonConversation.vue Placeholder de item de conversa na sidebar
SkeletonDocumentCard.vue Placeholder de card de documento na listagem

Exibidos durante o carregamento assíncrono, substituídos pelo conteúdo real quando os dados chegam.