# 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
```vue
Salvar
Cancelar
Excluir
Enviar
```
---
## 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 `` via `v-bind="$attrs"` (ex: `placeholder`, `type`, `autocomplete`).
### Exemplos
```vue
```
---
## 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
```vue
Ativo
Inativo
Admin
Padrão
```
---
## 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
```vue
```
---
## 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: ``); o slot padrão (`default`) recebe um texto complementar abaixo do valor.
### Exemplo
```vue
{{ stats.pendentes }} pendentes
```
---
## BaseIcon
**Arquivo:** `src/components/base/BaseIcon.vue`
Wrapper fino sobre ícones do [Lucide](https://lucide.dev/icons/) (`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
```vue
```
---
## 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
```vue
```
---
## 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
```vue
```
---
## 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
```vue
```
---
## 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.