# Componentes EletroDS — E-PROC

> Gerado do guide vivo em 2026-07-15. Fonte: `content/9.design-patterns/6.componentes/`. Não editar à mão — re-gerar.

## Introdução

_Visão geral dos Componentes do ME — o que esperar, como estão organizados, hierarquia EletroDS → Nuxt UI e links relacionados._

A aba Componentes é a lente micro: o componente em si — como se parece, suas variantes, tipos e estados, e quando usar cada um em tela. É conteúdo de Design (não referência de API): o detalhe de implementação fica no doc técnico do [EletroDS](https://eletro.design). O comportamento das telas vive em Padrões.

**Hierarquia (sempre nesta ordem):** EletroDS interno → Nuxt UI → Vue puro. Cada categoria lista primeiro os componentes do **EletroDS**; o Nuxt UI completa quando não há equivalente.

**O que você encontra aqui:**

- **Formulários** — campos de entrada, seleção e composição de filtros.
- **Navegação** — orientação e movimento entre telas e seções.
- **Visualização de dados** — tabelas, cabeçalhos e identificadores.
- **Ações** — botões e barras de ação.
- **Feedback & Overlays** — status, carregamento e camadas sobre a tela.

---

## Button

_Hierarquia, variantes e estados do botão no ME — o UButton do Nuxt UI, tematizado._

O botão dispara a ação de uma tela. O que importa não é qual cor existe, e sim a **hierarquia**: cada contexto tem **uma** ação principal, e o visual precisa deixar isso óbvio à primeira leitura.

## Hierarquia

O Nuxt UI expõe 7 cores × 6 variantes (42 combinações). O ME usa só este subconjunto — escolha pela **importância da ação**, não pela estética:

| Nível | Como | Quando — e por quê |
|-------|------|--------------------|
| **Primária** | `color="primary"` (solid) | A ação que a tela quer que você faça (CTA). **Uma só por contexto** — dois primários competindo diluem o foco e o usuário hesita. |
| **Secundária** | `color="neutral" variant="outline"` | Ação de apoio relevante. Presente e clicável, mas sem roubar a atenção do primário. |
| **Terciária** | `color="neutral" variant="ghost"` | Ação frequente de baixo peso (toolbar, só-ícone). Peso visual mínimo para não poluir áreas densas. |
| **Destrutiva** | `color="error"` | Excluir/remover. A cor sinaliza risco **antes** do clique; quando irreversível, exige confirmação (ver Excluir). |
| **Confirmação** | `color="success"` | Uso pontual, em confirmações positivas explícitas. Não é o CTA padrão — não substitui o primário. |

## Tamanhos & largura

| Quero… | Use | Por quê |
|--------|-----|---------|
| Densidade de tabela | `size="sm"` | Cabe na altura da linha sem quebrar o ritmo. |
| Padrão das telas | `size="md"` (default) | Tamanho de referência do produto. |
| Destaque / telas amplas | `size="lg"` · `xl` | CTA que precisa de presença. |
| Largura total | `block` | Só em **mobile** e **rodapé de modal** — alvo de toque maior e ação única em foco em telas estreitas. Evite no desktop (botão esticado perde a leitura de hierarquia). |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Ação disponível. |
| Hover / focus | **Foco sempre visível** (o teclado depende disso); acionável por `Enter`/`Espaço`. |
| `disabled` | Botão inerte — use quando a ação não se aplica ao contexto. Percebido **além da cor** (opacidade + `aria-disabled`). |
| `loading` / `loading-auto` | Spinner no botão e bloqueia o reclique; **mantém o rótulo** (não vira só ícone) e marca `aria-busy`. `loading-auto` liga sozinho enquanto a promise do `@click` resolve. |
| `square` + `icon` | Botão só-ícone — exige **nome acessível** (`aria-label`); o ícone não basta para leitor de tela. |

## Onde se aplica

## No código

É o **`UButton` do Nuxt UI**, tematizado pelo ME (não há componente EDS próprio). Props, eventos e tipos completos — para quem for implementar — ficam no doc técnico: [ui.nuxt.com/docs/components/button](https://ui.nuxt.com/docs/components/button). Aqui o foco é o uso em Design.

Para **fileiras de ações** (várias ações num header/toolbar), não enfileire botões soltos — use o ButtonBar.

## Acessibilidade

- Botão só-ícone (`square` + `icon`) precisa de **nome acessível** (`aria-label`) — o ícone não basta para leitores de tela.
- **Foco visível** sempre; ordem de foco coerente com a leitura. Acionável por `Enter`/`Espaço`.
- Alvo de toque **≥ 44px**; em densidade de tabela (`size="sm"`), garanta a área clicável.
- `disabled`/`loading` percebidos **além da cor** (`aria-disabled` / `aria-busy`).
- Hierarquia e risco nunca **só** pela cor — a destrutiva (`error`) vem com rótulo claro e, quando crítica, confirmação.

## Labeling

Rótulo de botão = **verbo + entidade explícita** ("Novo fornecedor", não só "Novo") — assim a ação se explica fora de contexto. A escolha do verbo (Novo / Adicionar / Gerar) segue Voz e conteúdo e o pattern Adicionar.

---

## ButtonBar

_A barra de ações do ME — botões com overflow "Mais ações", menu de opções e tooltips. O miolo do subheader._

O ButtonBar é uma fileira de botões de ação que colapsa o excedente em Mais ações conforme falta espaço. É o miolo do Subheader e a forma canônica de apresentar as ações de suporte de uma tela — nunca espalhe botões soltos.

## Uso em tela

Lê-se da esquerda pra direita, em ordem de importância. As ações que cabem ficam visíveis; o resto recolhe em Mais ações (overflow responsivo) — então a barra nunca "estoura" a largura. Ações pouco frequentes ou administrativas vão no menu Opções (à direita). Cada botão pode ter tooltip (`description`) para esclarecer um ícone sem texto.

Mantenha 2–3 ações visíveis no máximo; acima disso, deixe o overflow decidir. A ação primária da tela ("Novo X") não vive aqui — ela é o split do Subheader; o ButtonBar carrega as secundárias.

## Aplicação

A mesma barra aparece em vários níveis do produto:

| Onde | Ações típicas |
|------|---------------|
| **Subheader da index** | Editar · Duplicar · Arquivar · Mais ações |
| **Toolbar de documento** | Mover para projeto · Enviar follow up · Exportar |
| **Barra de seleção (massa)** | Exportar · Cancelar selecionados |
| **Cabeçalho de seção** | ações locais daquele bloco |

O comportamento (overflow, tooltip, opções) é idêntico em todos; muda só o conjunto de ações.

## Variantes

Escolha pelo cenário:

| Quero… | Use |
|--------|-----|
| Cor padrão de toda a barra | `color` na barra (`primary` · `neutral` · `error` · `success` · `warning`) |
| Cor só de um botão | `color` no objeto da ação (sobrepõe a barra) |
| Estilo dos botões | `variant` (`ghost` em toolbar, `outline` para destacar) |
| Densidade | `size` (`sm` em tabela densa · `md` padrão · `lg`) |
| Menu de ações secundárias | `options` (vira o menu **Opções**) |
| Conteúdo extra entre ações e opções | slot `default` (ex.: abas, filtros) |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Ações visíveis até caber; excedente em **Mais ações**. |
| `disabled` (por ação) | Botão inerte — use quando a ação não se aplica ao contexto atual. |
| `loading` (por ação) | Spinner no botão durante a operação. |
| Overflow responsivo | `visibleActions` fixa quantas ficam visíveis; `maxVisibleActions` limita o teto antes do overflow. |

## No código

`<MeButtonBar>` é um componente EletroDS. Props, eventos e tipos completos — para quem for implementar — ficam no doc técnico: [eletro.design/components/buttonbar](https://eletro.design/components/buttonbar). Aqui o foco é o uso em Design.

## Acessibilidade

Ações só com ícone exigem rótulo acessível (não dependa só do tooltip, que aparece no hover). O menu Mais ações e o Opções precisam ser alcançáveis e operáveis por teclado. Estados `disabled`/`loading` devem ser percebidos além da cor.

## Onde se aplica

---

## Subheader

_A faixa de controle no topo da index e do documento — CTA "Novo X", ButtonBar, busca, gráfico e view switcher. Três variantes._

O Subheader é a faixa de controle logo abaixo do header global. Ele monta numa peça só o que antes seriam vários elementos soltos: o toggle de sidebar, a ação primária ("Novo X", split com menu), a ButtonBar ao centro, a busca, o toggle de gráfico e o view switcher. É o ponto onde mora a hierarquia de ações de uma index.

## Uso em tela

Três regiões — esquerda · centro · direita. A esquerda traz o toggle de sidebar e a ação primária; o centro, a ButtonBar; a direita, busca, gráfico e a troca de visualização. Como tudo vem do bloco, a posição e o espaçamento já saem padronizados — você passa props, não recria layout.

A ação primária ("Novo X") fica sempre à esquerda e usa o split quando há mais de um tipo a criar (ex.: "Nova transação ▾"). As ações secundárias vão na ButtonBar; as de tela (busca, gráfico, view) ficam à direita.

## Aplicação

A variante muda conforme a tela:

| Tela | Variante | O que mostra |
|------|----------|--------------|
| **Index** (listagem) | `primary` | toggle sidebar · split "Novo X" · ButtonBar · busca · gráfico · view switcher |
| **Documento / formulário** | `secondary` | ButtonBar ao centro · **Voltar** e **Confirmar** à direita |
| **Toolbar embutida** (dentro de um bloco) | `tertiary` | só a ButtonBar — ignora CTA/busca/etc. |

## Variantes

| Quero… | Use |
|--------|-----|
| Topo de uma index | `variant="primary"` |
| Topo de um documento/edição com Voltar + Confirmar | `variant="secondary"` (props `back`, `confirm`) |
| Só uma fileira de ações, sem CTA | `variant="tertiary"` |

## Regiões (variante primary)

| Região | Prop | O que é |
|--------|------|---------|
| Toggle de sidebar | `toggleSidebar` | hambúrguer que abre/fecha a sidebar |
| Ação primária | `createActions` | botão "Novo X" + menu de tipos (split) |
| Ações de suporte | `buttonBar` | a ButtonBar central |
| Busca | `search` | campo de busca da listagem |
| Gráfico | `toggleChart` | alterna a visão de gráfico (com chip de notificação) |
| View switcher | `gridMode` | troca Tabela · Lista · Cards · Preview |

## Subheader de documento

No documento o subheader tem regiões fixas: à **esquerda**, as ações do status (até 3 aparentes + **"Mais ações"** no overflow); à **direita**, **"Opções"** (configurações da tela). As ações mudam conforme o status/fase — ver Ações por status. Quando o documento aparece em **preview** (master-detail da index), surge um ícone **"abrir em outra janela"** à direita de "Opções" — atalho para a página única.

## Responsividade

Segue a régua geral em Foundations › Breakpoints; o que é próprio do subheader:

| Largura | Comportamento |
|---------|---------------|
| **Desktop** · ≥ 1024px | Layout completo — título, todas as CTAs e ações secundárias visíveis. |
| **Tablet** · 640–1024px | Título + CTA primária + no máximo 1 secundária; as demais recolhem em "Mais ações". |
| **Mobile** · < 640px | No mobile o subheader **perde** o hambúrguer (vai pro **header**), o "Novo X" (vira **FAB**) e a busca (vai pro **header**) — sobram só as **ações em massa** + gráfico/view. As secundárias **colapsam em "Mais ações"** (nunca rolam na horizontal nem quebram em linhas). |

## Overflow das ações (ResizeObserver)

O `MeSubheader` observa a largura da ButtonBar (**ResizeObserver**): as ações que não cabem **colapsam progressivamente** num **"Mais ações"** (ícone + label + chevron). **Nunca** scroll horizontal, **nunca** quebra de linha. Ordene por frequência de uso; separe a ação destrutiva por um divisor. Não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.

## Gotchas de montagem (verificados na index real)

- **Altura 56px** (`h-14`). O `MeSubheader` é **flush** → dê `w-full h-full` + wrapper `items-stretch`, senão o gap vira **linha dupla** na borda inferior.
- **`inheritAttrs: false`**: a `class`/`style` que você passa vão pro inner, não pro root — para esticar o root, estilize o wrapper.
- **Busca é gatilho:** abre o painel de busca, **não** busca inline no campo.

## No código

`<MeSubheader>` é um bloco EletroDS. Props, eventos e tipos completos — para quem for implementar — ficam no doc técnico: [eletro.design/blocks/subheader](https://eletro.design/blocks/subheader). Aqui o foco é o uso em Design.

## Acessibilidade

O toggle de sidebar e os botões só-ícone (gráfico, view) precisam de rótulo acessível. A ação primária split deve abrir o menu por teclado. Garanta ordem de foco coerente com a leitura (esquerda → centro → direita).

## Onde se aplica

---

## DropdownMenu

_Menu de ações disparado por clique (Nuxt UI) — o "mais ações" (kebab) de cada linha._

O DropdownMenu é o menu de ações aberto por clique. Na index, é o menu de mais ações por linha (gatilho `ellipsis-vertical`); também é o menu Opções da ButtonBar e o **menu de interação de uma entidade** (clicar no nome de um Fornecedor, Comprador ou Responsável abre Ver detalhes · Enviar para o Genius · Enviar mensagem).

## Uso em tela

Itens com ícone + rótulo, separadores por grupo e a ação destrutiva isolada ao fim (após divisor). Convenção do ME: `ellipsis-vertical` = menu individual da linha; `ellipsis` (horizontal) = "Mais ações" da tela — não troque um pelo outro. O comportamento de cada item vive no padrão correspondente (Editar, Excluir, Fixar…).

## Aplicação

O mesmo menu aparece em papéis distintos — muda o gatilho e o conjunto de itens; o comportamento (abrir por clique, teclado, foco) é idêntico:

| Onde | Gatilho | Itens típicos |
|------|---------|---------------|
| **Ações por linha** (index/lista) | kebab `⋮` (`ellipsis-vertical`) | Ver · Editar · Duplicar · Excluir (destrutiva isolada) |
| **Opções** da ButtonBar | "Opções" (`ellipsis` + rótulo) | Imprimir · Exportar PDF · Histórico de versões · Configurações de exibição |
| **Interação de entidade** (documento) | nome da entidade + chevron | Ver detalhes · Enviar para o Genius · Enviar mensagem |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Fechado | Só o gatilho; o chevron aponta para baixo. |
| Aberto (ativo) | O gatilho fica **realçado** (estado selecionado) e o chevron gira; o menu ancora ao gatilho. |
| Item destrutivo | Isolado após um divisor, cor `error`. |
| Item desabilitado | Inerte, percebido além da cor (`aria-disabled`); tooltip quando o motivo ajudar. |

## No código

`UDropdownMenu` — doc técnica em [ui.nuxt.com/docs/components/dropdown-menu](https://ui.nuxt.com/docs/components/dropdown-menu).

## Acessibilidade

- Trigger só-ícone (kebab) precisa de **nome acessível** (ex.: `aria-label="Mais ações"`) e `aria-expanded`.
- **Teclado completo:** abre por `Enter`/`Espaço`, navega com setas, fecha com `Esc` e por clique fora — **sem disparar** nenhuma ação ao fechar.
- Ao fechar, o **foco volta ao trigger**.
- Item desabilitado: percebido além da cor (`aria-disabled`) e, quando útil, tooltip explicando o motivo.
- Ações destrutivas isoladas após divisor (ver Mais ações).

## Onde se aplica

---

## FAB

_Botão de ação flutuante — o que a ação primária da tela vira no mobile, fixo acima da NavBar._

## Uso em tela

Um botão circular fixo no **canto inferior direito**, **acima da NavBar**, com a cor primária e um ícone (em geral `+`). Aparece **só no mobile**: no desktop/tablet a ação primária vive no Subheader. Use **um único** FAB por tela — ele carrega a ação mais esperada do contexto (criar/adicionar). Ações secundárias **não** viram FAB: ficam no Subheader (rolando) ou em "Mais ações".

Quando a ação primária abre tipos (split "Novo X"), o FAB abre um **modal-sheet** com as opções — não um menu solto.

## Responsividade

Segue a régua geral em Foundations › Breakpoints:

| Largura | Comportamento |
|---------|---------------|
| **Desktop / Tablet** · ≥ 640px | Sem FAB — a ação primária fica no Subheader. |
| **Mobile** · < 640px | A ação primária vira FAB (inferior direito, fixo acima da NavBar). |

## Acessibilidade

- O FAB precisa de **rótulo acessível** (`aria-label`) — é um botão só com ícone.
- Alvo de toque confortável (≥ 44px) e **contraste** suficiente sobre o conteúdo.
- Não deve **cobrir** conteúdo essencial nem a NavBar; fica acima dela, com folga.

## No código

Não é um componente próprio: é um **botão posicionado** (UButton `rounded-full`, cor primária, `position: fixed`/`absolute` no canto inferior direito) — ver Button.

## Onde se aplica

---

## CriterionInput

_O critério ativo da Filter Bar (campo · operador · valor) — props, variantes, estados e API real do EletroDS._

O CriterionInput representa um critério de filtro — uma peça segmentada campo · operador · valor, com remoção opcional. É a unidade que compõe e edita os filtros na Filter Bar. O *comportamento* de filtragem (como o critério é criado, editado e aplicado) vive no padrão Filtrar; aqui está a ficha do componente.

## Uso em tela

Aparece na Filter Bar, um por critério ativo. Lê-se da esquerda pra direita — campo · operador · valor — e cada segmento é clicável para editar aquele passo; o × remove na hora, sem confirmação. Use sempre que houver um filtro aplicado visível; nunca recrie um "chip de filtro" à mão.

> **Alinhamento (verificado na index real):** na Filter Bar o `MeCriterionInput` roda com **`size="sm"` + `deletable`**, e os **controles de filtro ao lado** (Selects/filtros rápidos) usam **o MESMO `size`** — mesma altura. Size divergente entre eles = barra desalinhada (bug recorrente).

## Aplicação

O mesmo critério reaparece em três momentos do filtro de uma index:

| Onde | O critério representa |
|------|-----------------------|
| **Filtros aplicados** (Filter Bar) | um filtro ativo e editável (ex.: `Status = Em análise`) |
| **Filter Search** (criar critério) | o resultado dos 3 passos campo · operador · valor |
| **Seleção em massa** | os critérios ficam `disabled` enquanto a seleção está ativa — ver Ações em massa |

## Variantes

A apresentação muda por modo e por tipo do campo — escolha pelo cenário:

| Quero… | Use |
|--------|-----|
| Critério padrão, editável e removível | `deletable` |
| Critério dentro de uma barra densa (tabela/index) | `compact` *(ignora `deletable`)* |
| Critério somente-leitura (ex.: filtros desabilitados durante seleção em massa) | `disabled` |
| Esconder a troca de campo/operador (critério fixo) | `hideField` / `hideOperator` |
| Ajustar densidade | `size="sm" \| "md" \| "lg"` *(padrão `md`)* |

O valor se adapta ao `field.type`: `object` → lista de opções (estática via `field.options.items` ou assíncrona via função que retorna `Promise`); `date` → seletor de data; `number` → numérico; `string` → texto; `boolean` → alternância. Operadores inativos não aparecem por padrão — para incluí-los, liste-os em `operators` (ex.: `['equal', 'different', 'empty']`).

## Valor múltiplo (vários valores num critério)

Alguns operadores aceitam **mais de um valor** no mesmo critério — o campo de valor vira uma entrada múltipla (várias etiquetas/opções, não um único valor):

- **Texto múltiplo** (`string`) — operadores `contain_and` · `contain_or` · `not_contain_and` · `not_contain_or`: digita-se vários termos separados por um **delimitador**. Controle por `criterion.options`: **`delimiter`** (string ou RegExp que separa os valores) e **`maxLength`** (máximo de valores).
- **Data múltipla** (`date`) — `between` (intervalo início–fim) e os relativos `after`/`before`/`next`/`last`. Para várias datas soltas ou vários intervalos, use o componente InputDateMultiple.
- **Seleção múltipla** (`object`) — as opções vêm de `field.options.items` (estáticas ou `Promise`); combina com os operadores de conjunto (`contain_*`).

```ts
// criterion.options — para operadores de valor múltiplo
{ maxLength?: number, delimiter?: string | RegExp, items?: any[] /* opções do tipo 'object' */ }
```

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Editável: campo, operador e valor reabrem o passo correspondente. |
| `deletable` | Exibe o botão de remover (emite `remove`). |
| `disabled` | Impede edição — usado quando a filter-bar é desativada por outro modo (ver Ações em massa). |
| `compact` | Layout condensado para barras densas; sem botão de remover. |

## Responsividade

O critério adapta-se por **densidade**, não por colapso — quem lida com a falta de espaço é a barra que o contém, com scroll horizontal (ver Filter Bar). No próprio CriterionInput:

| Recurso | Efeito |
|---------|--------|
| `size` — `sm` · `md` · `lg` | Ajusta altura e densidade ao contexto (`sm` em tabelas/barras densas, `md` padrão). |
| `compact` | Layout condensado para barras cheias; o botão de remover não aparece (o `deletable` não tem efeito). |
| Valor longo | Trunca no segmento de valor, preservando campo · operador legíveis; quem some primeiro é o valor, nunca o campo. |

## No código

`<MeCriterionInput>` é um componente EletroDS. Props, eventos e tipos completos — para quem for implementar — ficam no doc técnico do EletroDS: [eletro.design/components/criterioninput](https://eletro.design/components/criterioninput). Aqui o foco é o uso em Design; o detalhe de implementação vive lá.

## Acessibilidade

Cada segmento é um alvo clicável — garanta rótulo acessível para campo, operador, valor e remover. O estado `disabled` precisa ser percebido além da cor (opacidade + `aria-disabled`); não dependa só do tom para sinalizar "filtro inativo".

## Onde se aplica

---

## InputNumber

_Valor numérico com stepper (− / +) — quantidade, preço. Respeita min, max e step._

O InputNumber é o campo de valor numérico com stepper (− / +): quantidade de itens, preço, prazo em dias. Garante limites (`min`/`max`) e incremento (`step`). Vive dentro de um FormField.

## Variantes

| Quero… | Use |
|--------|-----|
| Limitar faixa | `min` / `max` |
| Incremento por clique | `step` |
| Densidade | `size` |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Valor editável por digitação ou pelo stepper (− / +). |
| No limite (`min`/`max`) | O stepper desabilita a direção que estouraria a faixa; valor fora do limite é corrigido e avisado por texto (não só cor). |
| Desabilitado | Campo e steppers inertes quando o valor não se aplica ao contexto. |

## No código

`UInputNumber` — doc técnica em [ui.nuxt.com/docs/components/input-number](https://ui.nuxt.com/docs/components/input-number).

## Acessibilidade

- Permita **digitação direta** além dos botões de stepper; cada botão (+/−) com **nome acessível**.
- Semântica de spinbutton: `aria-valuenow`/`aria-valuemin`/`aria-valuemax`; **setas** ↑/↓ ajustam o valor.
- **Foco visível**; alvo ≥ 44px nos steppers.
- Erro/limite anunciado por texto, não só por cor.

---

## InputMultiple

_Múltiplos valores como tags, com overflow e contador. Estende o UInputTags._

O InputMultiple captura vários valores num campo só, como tags removíveis, com overflow + contador quando passam da largura (ex.: categorias, e-mails). Para montar um subconjunto a partir de um catálogo grande movendo itens entre listas, use o DualList. Vive dentro de um FormField.

## Variantes

| Quero… | Use |
|--------|-----|
| Contador de excedentes | `counter` (ex.: "+2") |
| Separador ao digitar | `delimiter` (vírgula, Enter) |
| Densidade | `size` |

## No código

`<MeInputMultiple>` é um componente EletroDS. Doc técnica em [eletro.design/components/inputmultiple](https://eletro.design/components/inputmultiple). Aqui o foco é o uso em Design.

## Acessibilidade

- Cada tag removível **por teclado**; o botão de remover (×) tem nome acessível (ex.: "Remover {valor}").
- Adição/remoção de valores anunciada (`aria-live`); o contador de overflow ("+N") também acessível.
- Rótulo do campo associado (FormField); **foco visível** ao navegar entre tags.
- Valor inválido/duplicado sinalizado por texto, não só por cor.

---

## Form

_Orquestra os campos — validação, schema e submit. Agrupa os FormFields de uma tela._

O Form é o container que orquestra um formulário: agrupa os FormFields, valida (por schema), reúne o estado e dispara o submit. É o que transforma campos soltos numa tela de cadastro/edição coerente.

## Variantes

| Quero… | Use |
|--------|-----|
| Validar por schema | `schema` (Zod/Valibot/Yup) + `state` |
| Quando validar | `validate-on` (`input` · `blur` · `submit`) |
| Erro por campo | propaga para o `error` de cada FormField |

## Onde se aplica

## No código

`UForm` — doc técnica em [ui.nuxt.com/docs/components/form](https://ui.nuxt.com/docs/components/form).

## Acessibilidade

Submeter por Enter; ao falhar a validação, focar o primeiro campo com erro e anunciá-lo. As ações (Salvar/Cancelar) ficam no rodapé (ver gabarito de Formulário).

---

## InputDate

_Input de data do EletroDS (MeInputDate) — digitação, calendário, intervalo e dias desabilitados; props, variantes e estados._

## Uso em tela

Um único campo de data: digita-se a data (`dd/mm/aaaa`) ou, com `datepicker`, escolhe-se num calendário. O valor é controlado por `v-model`. Vive dentro de um FormField (rótulo, ajuda, erro) como qualquer campo.

## Variantes

Escolha pelo cenário:

| Quero… | Use |
|--------|-----|
| Só digitar a data | padrão (sem `datepicker`) |
| Escolher num calendário | `datepicker` |
| Selecionar um período (de–até) | `datepicker` + `range` |
| Bloquear dias úteis / fins de semana | `disabledWeekdays` / `disabledWeekends` |
| Ajustar aparência | `color` · `size` · `variant` · `highlight` |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Editável por digitação; abre o calendário quando `datepicker`. |
| `disabled` | Impede edição e abertura do calendário. |
| `highlight` | Realça o campo com a cor atual (semelhante ao foco) — útil para erro/validação. |
| Erro (via FormField) | A mensagem e o `required` vêm do FormField que o envolve. |

## Múltiplas datas — `MeInputDateMultiple`

Quando o campo precisa de **várias datas** (não uma só), use o componente irmão **`MeInputDateMultiple`**. Cada data escolhida vira uma **tag** no campo; o `v-model` é um **array** de `CalendarDate`.

| Quero… | Use |
|--------|-----|
| Várias datas soltas | padrão (`v-model` = array de `CalendarDate`) |
| Escolher no calendário | `datepicker` |
| Vários **intervalos** (início–fim) | `range` → `v-model` vira array de `{ start, end }` |
| Bloquear dias úteis / fins de semana | `disabledWeekdays` / `disabledWeekends` |
| Manter em 1 linha (tags que sobram viram contador) | `counter` *(sem ele, cresce até 2 linhas + scroll)* |
| Aparência | `color` · `size` · `variant` · `highlight` |

Emite `addTag` / `removeTag` (ao adicionar/remover uma data) e `invalid` (data inválida), além de `focus`/`blur`. Funciona dentro de um FormField como o `MeInputDate`. É também o valor de um critério de filtro com **data múltipla** — ver CriterionInput › Valor múltiplo.

## No código

`<MeInputDate>` é um componente EletroDS que estende o `InputDate` do Nuxt UI: aceita todas as props dele mais `datepicker`, `range`, `disabledWeekdays` e `disabledWeekends`. Emite `update:modelValue`, `update:placeholder`, `change`, `blur` e `focus`. Ficha técnica em [eletro.design/components/inputdate](https://eletro.design/components/inputdate); a base, em [ui.nuxt.com/docs/components/input-date](https://ui.nuxt.com/docs/components/input-date). A variante múltipla é o **`MeInputDateMultiple`** ([eletro.design/components/inputdatemultiple](https://eletro.design/components/inputdatemultiple)).

## Acessibilidade

Navegação por teclado no calendário (setas + `Enter`); o campo aceita digitação além do clique. O formato esperado (`dd/mm/aaaa`) deve estar na ajuda do FormField, não só implícito. O estado `disabled` precisa ser percebido além da cor.

---

## Filter Bar

_A barra persistente de filtros da index — visões salvas, critérios ativos e ações. Sempre visível, nunca overlay; abre o Filter Search para compor critérios._

A Filter Bar é a faixa **persistente** entre a toolbar e a listagem. **Nunca abre overlay — é sempre visível** e reflete em tempo real os critérios ativos. Tem CRUD inline sobre os critérios: clicar num critério edita-o direto na barra; o Filter Search só **adiciona** novos. O **comportamento** de filtrar (criar, editar, aplicar, salvar) vive no padrão Filtrar; aqui está como a barra se monta e se adapta.

## Anatomia

Lê-se da esquerda para a direita, sobre o mesmo fundo da toolbar e separada da tabela por uma borda inferior. Só a área de critérios rola horizontalmente quando excede a largura.

| Zona | O que contém |
|------|--------------|
| **LeadingSlot** | Visões salvas — recortes prontos da listagem (ex.: "Todos os processos", "Todo período") como dropdowns de contexto; **não** criam critérios. |
| **CriterionArea** | Os critérios ativos, um CriterionInput por filtro (campo · operador · valor). Scroll horizontal quando excede a largura. |
| **ActionButtonsArea** | As ações da barra — **+** (abre o Filter Search) · **Salvar** a combinação atual · **Limpar** — montadas com a ButtonBar. |

## Relação com o Filter Search

A barra **mostra e edita**; o Filter Search **compõe**. São peças distintas que trabalham juntas:

- O **+** (ou a busca) abre o Filter Search — o overlay com base no CommandPalette — para **adicionar** um critério.
- Cada critério confirmado no Filter Search vira um CriterionInput na CriterionArea.
- **Editar** um critério existente é **inline** na barra: clicar num segmento (campo, operador ou valor) abre a edição ali mesmo — **sem** reabrir o Filter Search.

## Responsividade

A barra é **persistente em qualquer largura** — não vira overlay (quem abre é o Filter Search). A régua geral está em Foundations › Breakpoints; o que é próprio da barra:

| Largura | Comportamento |
|---------|---------------|
| **Desktop** · ≥ 1024px | Tudo inline: visões salvas no início, critérios como chips editáveis e as ações à direita. |
| **Tablet** · 640–1024px | Inline; os critérios excedentes recolhem num **+N** que abre o restante em popover. |
| **Mobile** · < 640px | A barra **continua visível**; a CriterionArea ganha scroll horizontal e o **+** abre o Filter Search como bottom-sheet. A barra em si não colapsa em modal. |

## No código

Enquanto não há um `<MeFilterBar>` internalizado, a barra é uma faixa persistente que compõe CriterionInput (um por critério) e ButtonBar (ações) sobre o layout da toolbar, e dispara o Filter Search para compor/editar critérios.

## Acessibilidade

A barra deve manter cada critério como alvo editável com rótulo acessível e anunciar mudanças nos critérios ativos (`aria-live`) já que a listagem atualiza em tempo real. Como é sempre visível, não há foco a gerenciar na própria barra — o foco gerenciado pertence ao Filter Search quando abre.

## Onde se aplica

---

## Filter Search

_O overlay de busca e composição de filtros (base CommandPalette) — busca direta, filtros salvos e construção de critério em 3 passos._

O Filter Search é o **overlay** que abre a partir da Filter Bar (pelo **+** ou pela busca) para **adicionar** critérios — editar um critério já aplicado acontece inline na barra, sem este overlay. Unifica três intenções num só campo:

1. **Busca direta** — encontrar um registro em qualquer lista digitando o termo.
2. **Filtros salvos** — aplicar uma combinação pronta num clique.
3. **Construir um critério** — em três passos: **Critério → Operador → Valor**.

## Anatomia

| Zona | O que contém |
|------|--------------|
| **Campo de busca** | "Busca direta ou encontre um filtro", com `Enter` para confirmar e **×** para fechar. Ícone de busca à esquerda. |
| **Filtros salvos** | Chips de combinações prontas (ex.: "Pré-Pedido", "Meus processos", "Em 22/03/2026") logo abaixo do campo. |
| **Lista de Critério** | Os campos disponíveis (ex.: Aprovado por, Categoria, Criado por), cada um com chevron que faz o drill-down para operador e valor. |

## Base CommandPalette

A árvore `groups → items → children` modela os três passos do critério, e a busca fuzzy (Fuse.js) acha campo ou registro por texto sem rolar a lista inteira.

| Recurso do CommandPalette | Papel no Filter Search |
|---------------------------|------------------------|
| Busca fuzzy (`fuse`) + `icon` de busca | Busca direta de registro **e** localização do campo por nome. |
| `groups` / `items` | Os **campos** disponíveis (grupo "Critério") e os filtros salvos. |
| `children` + botão `back` | Drill-down **Critério → Operador → Valor**; voltar um passo sem fechar. |
| `multiple` | Valores múltiplos num mesmo critério (ex.: Status em N estados). |
| `loading` | Opções de valor assíncronas (lista que vem da API). |
| `close` | Fecha o overlay (**×** ou `Esc`). |

## Responsividade

Por ser overlay, ancora-se no contexto e segue a régua de Foundations › Breakpoints:

| Largura | Comportamento |
|---------|---------------|
| **Desktop** · ≥ 1024px | Overlay ancorado abaixo da barra (popover/modal centrado), largura contida. |
| **Tablet** · 640–1024px | Igual ao desktop, largura adaptada. |
| **Mobile** · < 640px | Abre como **bottom-sheet** ocupando a largura da tela; aplicar fecha a folha e devolve ao contexto. |

## No código

Parte do `<UCommandPalette>` do Nuxt UI; a ficha técnica (props/slots/emits) está em [ui.nuxt.com/docs/components/command-palette](https://ui.nuxt.com/docs/components/command-palette). A Filter Bar dispara o overlay e recebe de volta o critério composto.

## Acessibilidade

Como overlay, precisa de **foco gerenciado**: ao abrir, o foco vai para o campo de busca; ao fechar (× ou `Esc`), volta ao gatilho na barra. O drill-down precisa do botão **voltar** (`back`) audível e navegação por teclado (setas + `Enter`). Anuncie o passo atual (Critério/Operador/Valor) para leitores de tela.

## Onde se aplica

---

## LoginForm

_O formulário de login completo do ME — e-mail/senha, idioma, lembrar, reCAPTCHA e links de rodapé._

O LoginForm é a tela de entrada do produto, pronta: campos de e-mail e senha com validação, seletor de idioma opcional, "lembrar-me" + "esqueci a senha" na mesma linha, um espaço para o reCAPTCHA e o rodapé com cadastro/ajuda. Combina com o block [Login](https://eletro.design/blocks/login) (layout dividido imagem + formulário).

## Quando usar

- Na **tela de autenticação** — não monte campos de login soltos em outra estrutura.
- Quando o acesso é multilíngue, ligue o seletor de idioma (ver i18n abaixo).

## Configuração

| Prop | Papel |
|------|-------|
| `title` · `description` | Cabeçalho do formulário (ou use os slots de mesmo nome). |
| `show-locale-select` · `locales` · `locale-placeholder` | Seletor de idioma (oculto por padrão; popule `locales`). |
| `remember-me-label` | Rótulo do "lembrar-me". |
| `forgot-password-label` · `forgot-password-href` | Link de recuperação de senha. |
| `sign-up-href` · `help-href` | Links do rodapé (cadastro · ajuda). |
| `show-recaptcha-placeholder` | Mostra o placeholder quando não há reCAPTCHA via slot. |
| `loading` | Desabilita o formulário e indica carregamento no botão. |

Slots: `title`, `description`, `recaptcha` (injeta o widget real), `footer`, `signup-text`, `help-text`. Eventos: `submit` (`{ email, password, rememberMe? }`), `forgotPassword`, `signUp`, `help`.

## Idioma e i18n

O seletor de idioma alimenta a estratégia multilíngue do ME — ver Voz e conteúdo › Idioma e i18n. Os rótulos são chaves de i18n, não strings cravadas.

## No código

`MeLoginForm` (componente EletroDS) — API e preview ao vivo em [eletro.design/components/loginform](https://eletro.design/components/loginform).

## Acessibilidade

- Cada campo tem **rótulo associado** e erro por validação inline; o foco vai para o primeiro campo inválido no `submit`.
- O reCAPTCHA recebe **nome acessível**; o estado `loading` é anunciado no botão.
- Contraste e foco visível seguem Foundations › Acessibilidade.

---

## SelectMultiple

_Seleção múltipla com busca e autocomplete — escolher vários itens de uma lista, como tags._

O SelectMultiple deixa o usuário escolher **vários itens** de uma lista, com busca e autocomplete; os selecionados viram tags no campo. Use quando a escolha é múltipla e a lista é média/grande (com filtragem por digitação).

## Quando usar

- **Vários valores** de um conjunto — ex.: categorias de um fornecedor, responsáveis de uma cotação.
- Para **uma** escolha, use o Select. Para **mover/ordenar** itens entre duas listas (ex.: editar colunas), use o DualList. Para **digitar** valores livres como tags, o InputMultiple.

## Configuração

| Prop | Papel |
|------|-------|
| `v-model` (`modelValue`) | Itens selecionados. |
| `items` | Opções disponíveis (`InputMenuItem[]`). |
| `placeholder` | Texto do campo vazio. |
| `disabled` · `loading` · `loading-icon` | Desabilitado / carregando (com ícone opcional). |
| `color` · `variant` · `size` | Aparência (variante padrão `outline`, tamanho `md`). |
| `highlight` | Realça como foco (ex.: indicar erro/atenção). |
| `open-on-click` · `open-on-focus` | Quando abrir o dropdown. |
| `counter` | Mantém o campo em **uma linha só**: as tags que não cabem colapsam num **badge de contagem** clicável, que abre um popover listando as demais. (Sem `counter`, as tags quebram livremente em várias linhas.) |
| `tag-max-width-class` | Largura máxima de cada tag (padrão `max-w-[30%]`) — passe uma classe `max-w-*`. |

**Tags:** cada tag **trunca** quando o rótulo passa da largura máxima e mostra o texto completo em **tooltip** no hover — mantém rótulos longos legíveis sem quebrar o layout.

Eventos: `update:modelValue`, `change`, `focus`, `blur`.

## No código

`MeSelectMultiple` (componente EletroDS) — API e preview ao vivo em [eletro.design/components/selectmultiple](https://eletro.design/components/selectmultiple).

## Acessibilidade

- O campo tem **rótulo** (FormField); a lista é navegável por teclado (setas, Enter, Esc).
- Cada item selecionado (tag) é **removível por teclado** e a contagem/seleção é anunciada.
- `loading` e estado vazio têm texto, não só ícone.

---

## DualList

_O transfer-list do ME (inativas ↔ ativas) — peça por trás do "Editar colunas" da index e de escolher itens entre duas listas._

O DualList move itens entre duas colunas — disponíveis (esquerda) e selecionados (direita). É a peça por trás do Editar colunas da index (colunas inativas ↔ ativas) e de qualquer cenário "escolher alguns itens de um catálogo". O *comportamento* de configurar colunas vive em Estrutura de Index; aqui está a ficha do componente.

## Uso em tela

Aparece dentro de um modal (ex.: "Editar colunas") ou embutido num formulário. Lê-se da esquerda pra direita: à esquerda o que está fora, à direita o que está ativo, com setas no meio reforçando a transferência. Cada lado tem busca própria; move-se item a item (ícone + / ×) ou em massa (Selecionar todas / Remover todas).

Para poucas opções (2–3, binárias), um grupo de checkboxes resolve melhor. O DualList ganha quando a lista é grande, a busca ajuda a achar, e o usuário precisa revisar de relance o que ficou ativo — nunca empilhe checkboxes soltos para isso.

## Aplicação

O mesmo componente reaparece sempre que se monta um subconjunto a partir de um catálogo — reconhecê-lo evita reinventar a interação:

| Onde | O que se move |
|------|---------------|
| **Editar colunas** da index | colunas disponíveis → exibidas (e a ordem das exibidas, arrastando) |
| **Convidar / enviar follow-up** | contatos disponíveis → destinatários |
| **Permissões de um perfil** | permissões disponíveis → atribuídas |
| **Cotação / catálogo** | fornecedores ou categorias → selecionados |

A mecânica é idêntica nos quatro; muda só o rótulo dos lados (`left-box-label` / `right-box-label`) e o catálogo de itens.

## Variantes

Escolha pelo cenário:

| Quero… | Use |
|--------|-----|
| Reordenar os selecionados arrastando | `draggable` *(handle nos dois lados; a reordenação pausa enquanto há busca ativa)* |
| Rotular cada lado | `left-box-label` / `right-box-label` |
| Descrição ou ajuda por lado | `left-box-description` · `right-box-help` (e os pares à direita) |
| Mensagem de lista vazia | `left-box-empty-text` / `right-box-empty-text` |
| Itens que são objetos (não texto) | `value-key` (id estável) + `value-label` (texto exibido) |
| Conteúdo extra por item selecionado | slots `input`, `icons-left`, `icons-right` |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Move item a item (+ / ×) ou em massa (Selecionar/Remover todas). |
| `required` | Marca os dois lados como obrigatórios no formulário. |
| `disabled` | Desativa as duas colunas e as ações em massa; as ações por item também ficam inertes. |
| Vazio | Mostra o texto de vazio do lado (ex.: "Não encontramos nada aqui"). |
| Erro por lado | `left-error` / `right-error` exibem a mensagem (ex.: "selecione ao menos uma coluna"). |
| Busca ativa | Filtra aquele lado; mover entre listas continua, mas reordenar (draggable) pausa. |

## No código

`<MeDualList>` é um componente EletroDS. Props, eventos e tipos completos — para quem for implementar — ficam no doc técnico: [eletro.design/components/duallist](https://eletro.design/components/duallist). Aqui o foco é o uso em Design.

## Acessibilidade

Cada lista é uma região de formulário: rotule os dois lados (`left-box-label` / `right-box-label`). As ações por item (+ / ×) e as de massa precisam de rótulo acessível, não só ícone. O estado `disabled` deve ser percebido além da cor (opacidade + `aria-disabled`). Garanta mover por teclado, não só arrastando — `draggable` é um reforço, não o único caminho.

## Onde se aplica

---

## Checkbox

_Caixa de seleção (Nuxt UI) — seleção de linha na index e múltipla escolha em formulários._

O Checkbox é a caixa marcada/desmarcada. Na index, é a coluna de seleção de linha; em formulários, a escolha múltipla.

## Uso em tela

Na index, o checkbox do cabeçalho seleciona/limpa a página inteira e usa o estado `indeterminate` quando só parte está selecionada — a seleção é o que dispara as Ações em massa. Em formulário, use `UCheckboxGroup` para listas curtas. Para escolher itens entre duas listas (ex.: editar colunas), use o DualList — não uma pilha de checkboxes.

## Estados

| Estado | Comportamento |
|--------|---------------|
| Marcado / desmarcado | Seleção binária; o rótulo ao lado é sempre clicável junto da caixa. |
| Indeterminado | Cabeçalho da tabela quando só parte da página está selecionada (`aria-checked="mixed"`) — sinal além do visual. |
| Desabilitado | Inerte quando a opção não se aplica ao contexto; percebido além da cor. |

## No código

`UCheckbox` — doc técnica em [ui.nuxt.com/docs/components/checkbox](https://ui.nuxt.com/docs/components/checkbox).

## Acessibilidade

- Use o checkbox nativo (`role`/`checked`) — não recrie com `div`; rótulo **associado** e clicável.
- Estado **indeterminate** anunciado (`aria-checked="mixed"`), não só visual.
- **Foco visível** e acionável por teclado (`Espaço`); alvo de toque ≥ 44px mesmo em densidade de tabela.
- Em seleção de linha (index), a marcação/contagem deve ser anunciada (`aria-live`).

---

## FormField

_O esqueleto de todo campo — rótulo, obrigatório, texto de ajuda e erro. Tudo que é input vive dentro dele._

O FormField é a moldura de qualquer campo de formulário: rótulo, marca de obrigatório, texto de ajuda e mensagem de erro. Não é o input em si — é o que dá contexto e acessibilidade a ele. Todo campo do ME (Input, Select, Textarea…) vive dentro de um FormField.

## Variantes

| Quero… | Use |
|--------|-----|
| Marcar como obrigatório | `required` (mostra `*` no rótulo) |
| Texto de ajuda sob o campo | `hint` / `description` |
| Mensagem de erro | `error` (string) — pinta a borda e anuncia |
| Ajustar densidade | `size` (`sm` em formulários densos) |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Rótulo + controle + ajuda opcional. |
| `required` | `*` no rótulo; validação exige preenchimento. |
| Erro | **Ícone + mensagem + borda** de erro (nunca só a cor); substitui a ajuda enquanto ativa. |
| `disabled` | Campo inteiro inerte (rótulo esmaecido). |

## No código

`UFormField` — doc técnica em [ui.nuxt.com/docs/components/form-field](https://ui.nuxt.com/docs/components/form-field).

## Acessibilidade

O rótulo é associado ao controle (`for`/`id`) — clicar nele foca o campo. O erro é reforçado por **ícone + texto** (não só cor) e anunciado (`aria-describedby` + `aria-invalid`). "Obrigatório" precisa de reforço além do `*` (ex.: `aria-required`). Ao submeter com erro, **foque e anuncie o primeiro campo inválido**.

## Onde se aplica

---

## Input

_Campo de texto canônico do ME — estende o UInput com máscara (telefone, CNPJ, data)._

O Input é o campo de texto do ME. O diferencial sobre o `UInput` puro é a máscara: telefone, CNPJ, CEP, data — o valor é formatado enquanto se digita. Vive sempre dentro de um FormField, que dá rótulo, ajuda e erro.

## Variantes

| Quero… | Use |
|--------|-----|
| Formatar enquanto digita | `mask` (ex.: telefone, CNPJ, data) — o diferencial do ME |
| Ícone à esquerda/direita | `icon` / `trailing` (ex.: busca, limpar) |
| Valor numérico com stepper | número (− / +) para quantidade/valor |
| Ajustar densidade | `size` (`sm` em formulários densos) |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Vazio com placeholder, ou preenchido. |
| Focus | Anel de foco visível. |
| `disabled` | Inerte, esmaecido. |
| Erro | Borda de erro + mensagem (via FormField). |

## No código

`<MeInput>` é um componente EletroDS. Doc técnica em [eletro.design/components/input](https://eletro.design/components/input). Aqui o foco é o uso em Design.

## Acessibilidade

O rótulo vem do FormField — placeholder não substitui rótulo. Máscara não pode impedir colar/editar; o formato esperado deve estar na ajuda, não só implícito na máscara.

## Onde se aplica

---

## Select

_Seleção em lista — USelect para listas curtas, USelectMenu para busca e múltipla escolha._

O Select escolhe um valor (ou vários) de uma lista. Use USelect para listas curtas e fixas; USelectMenu quando precisar de busca, criação de item ou seleção múltipla. Vive dentro de um FormField.

## Variantes

| Quero… | Use |
|--------|-----|
| Lista curta e fixa | `USelect` |
| Busca, criar item ou múltipla seleção | `USelectMenu` |
| Muitos itens para mover entre listas | use o DualList, não um select |
| Ajustar densidade | `size` |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Placeholder "Selecione". |
| Aberto | Lista de opções; opção ativa destacada. |
| `disabled` | Inerte, esmaecido. |
| Erro | Borda de erro + mensagem (via FormField). |

## No código

`USelect` / `USelectMenu` — doc técnica em [ui.nuxt.com/docs/components/select-menu](https://ui.nuxt.com/docs/components/select-menu).

## Acessibilidade

Navegação por teclado (setas + Enter), opção ativa anunciada. Em múltipla seleção, o número de selecionados precisa ser percebido além da cor.

## Onde se aplica

---

## Textarea

_Texto longo — observações, justificativas. Vive dentro de um FormField._

O Textarea é o campo de texto longo (observações, justificativa de aprovação, descrição). Para uma linha, use o Input. Vive dentro de um FormField.

## Variantes

| Quero… | Use |
|--------|-----|
| Crescer conforme o texto | `autoresize` |
| Altura inicial fixa | `rows` |
| Densidade | `size` |

## No código

`UTextarea` — doc técnica em [ui.nuxt.com/docs/components/textarea](https://ui.nuxt.com/docs/components/textarea).

## Acessibilidade

- Rótulo **associado** via FormField — **placeholder não é rótulo**.
- Se houver contador/`maxlength`, anuncie o limite e o restante (`aria-describedby`), não só visualmente.
- **Foco visível**; redimensionamento permitido (não trave `resize` sem necessidade).
- Erro com ícone + texto + borda (não só cor) e ligado por `aria-describedby`.

---

## Radio

_Escolha única entre poucas opções visíveis. Para muitas, use Select._

O Radio é a escolha única entre opções todas visíveis — bom para 2–5 alternativas que valem a pena mostrar de uma vez (ex.: tipo de frete). Acima disso, a lista fica longa: use o Select. Vive dentro de um FormField.

## Variantes

| Quero… | Use |
|--------|-----|
| Empilhar vertical | `orientation="vertical"` (padrão) |
| Em linha | `orientation="horizontal"` |
| Densidade | `size` |

## No código

`URadioGroup` — doc técnica em [ui.nuxt.com/docs/components/radio-group](https://ui.nuxt.com/docs/components/radio-group).

## Acessibilidade

- Agrupe as opções com **`fieldset` + `legend`** (ou `role="radiogroup"` com rótulo) — o grupo tem um nome único.
- **Teclado:** setas navegam e selecionam entre as opções; `Tab` entra/sai do grupo.
- Rótulo de cada opção associado e clicável; **foco visível**; alvo ≥ 44px.
- Estado selecionado percebido além da cor.

---

## Switch

_Liga/desliga uma configuração com efeito imediato — sem precisar salvar._

O Switch alterna uma configuração com efeito imediato (notificações, visibilidade) — não espera um "Salvar". Quando a escolha booleana só vale no submit de um formulário, use o Checkbox.

## Variantes

| Quero… | Use |
|--------|-----|
| Densidade | `size` |
| Bloquear | `disabled` |
| Estado de carregamento | `loading` (enquanto persiste a mudança) |

## No código

`USwitch` — doc técnica em [ui.nuxt.com/docs/components/switch](https://ui.nuxt.com/docs/components/switch).

## Acessibilidade

- Semântica de **`role="switch"` + `aria-checked`**; rótulo associado que diz o que liga/desliga.
- Estado on/off percebido **além da cor** (posição do thumb + rótulo).
- **Foco visível**; acionável por `Espaço`/`Enter`; alvo ≥ 44px.
- Como o efeito é imediato, em falha de persistência **reverta o estado** e anuncie o erro (não deixe o switch mentindo).

---

## NavBar

_Barra de navegação inferior em telas menores — atalhos para as áreas principais._

Barra de navegação fixada no rodapé em telas menores (`MeNavBar`), com atalhos para as áreas principais do produto. É o equivalente mobile do Layout: no desktop a navegação principal fica **horizontal na app bar azul do topo** (Header); em telas estreitas, desce para o rodapé, ao alcance do polegar.

## Quando usar

- Em telas estreitas, para dar acesso de um toque às áreas principais (Dashboard, Transações, Fornecedores, Catálogos).
- No máximo **quatro itens** visíveis — acima disso, o excedente vai pro mapa do site (mais itens competindo viram ruído e erram o alvo no toque).

## Itens de navegação

Até **quatro atalhos** para as áreas principais. O item ativo é destacado **automaticamente** pela rota atual — o usuário sempre sabe onde está sem reler os rótulos. Cada item é ícone + rótulo de texto + destino.

## Mapa do site

Para ir além dos quatro atalhos, o NavBar abre o **mapa do site** — a mesma árvore de áreas e seções do Header, agrupando cada área e seus filhos. Mantém o acesso completo sem lotar a barra.

## Cor

Segue o contrato de marca do Header: sem cor definida, usa o primário com texto invertido. No ME, use a cor da marca via tokens — nunca HEX cru.

## Onde se aplica

## No código

Componente EletroDS (`MeNavBar`) — API, props e preview ao vivo no doc técnico: [eletro.design/components/navbar](https://eletro.design/components/navbar). Aqui o foco é o uso em Design.

## Acessibilidade

- É um **landmark de navegação** (`<nav>` com nome, ex.: "Navegação principal").
- Item ativo marcado com **`aria-current="page"`** — não só pela cor.
- Cada item tem **rótulo de texto** (não dependa só do ícone) e **alvo ≥ 44px** (navegação por toque/polegar).
- **Foco visível** e ordem de tabulação coerente.

---

## Tabs

_Segmenta seções de uma tela ou documento sem trocar de rota — Dados, Itens, Histórico._

As Tabs quebram uma tela densa em seções dentro da mesma rota — típico do documento (Dados gerais · Itens · Histórico) ou de um detalhe. Use quando o conteúdo é do mesmo registro e cabe num único contexto; para navegar entre telas, use a navegação global, não tabs.

## Variantes

| Quero… | Use |
|--------|-----|
| Abas de documento (sublinhado) | `variant` underline (padrão no ME) |
| Segmento compacto (pills) | `variant="pill"` |
| Empilhar na vertical | `orientation="vertical"` |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Ativa | Sublinhado/realce primário; painel correspondente visível. |
| Hover | Realce sutil. |
| `disabled` | Aba inerte (seção indisponível no status atual). |

## No código

`UTabs` — doc técnica em [ui.nuxt.com/docs/components/tabs](https://ui.nuxt.com/docs/components/tabs).

## Acessibilidade

Estrutura `tablist` / `tab` / `tabpanel`; navegação por setas do teclado; o painel é associado à aba (`aria-controls`). A aba ativa precisa ser perceptível além da cor.

## Onde se aplica

---

## Layout

_O shell da página — header (app bar azul, navegação horizontal), rails laterais opcionais, toolbar, main e footer._

O Layout é o shell que envolve qualquer tela do ME: o **header** (app bar azul me-brand, com a **navegação principal HORIZONTAL** no topo), o **nav rail** lateral opcional (5.5rem — atalhos, não o menu de áreas), os rails esquerdo/direito (sidebar de escopos, painéis — redimensionáveis e colapsáveis), a toolbar (onde mora o Subheader), o main e o footer. Em telas pequenas, os rails viram slideover.

## Composição

| Zona | O que é |
|------|---------|
| **Header** | App bar azul me-brand full-width: marca "me." à esquerda, **navegação principal horizontal** (áreas) no topo, transversais + avatar à direita. É aqui que fica o menu de áreas. |
| **Nav rail** | Rail lateral estreito **opcional** (5.5rem) — atalhos por etapa/rodada. **Não** é o menu de áreas (esse é horizontal, no header). |
| **Rail esquerdo** | Sidebar de escopos/filtros da entidade (colapsável). |
| **Toolbar / main** | Subheader no topo + a área de conteúdo da tela. |
| **Rail direito** | Painéis contextuais (Genius, detalhes, preview). |
| **Footer** | Rodapé global (só tablet/mobile). |

## Variantes & responsivo

Os rails laterais são **redimensionáveis e colapsáveis** — o usuário ajusta o espaço de trabalho sem perder conteúdo. Em telas pequenas, os rails deixam de ocupar coluna e abrem como **slideover** sobre o conteúdo (foco entra no painel, `Esc` fecha) — assim o `main` continua legível no mobile.

## Onde se aplica

## No código

`<MeLayout>` é um bloco EletroDS. Doc técnica em [eletro.design/blocks/layout](https://eletro.design/blocks/layout). Aqui o foco é o uso em Design.

**Slots (mapa das zonas):** `#header` (app bar) · `#nav-area` (nav rail opcional) · `#toolbar` (Subheader) · `#left-area` (sidebar de escopos) · `#default` (conteúdo) · `#right-area` (transversais: Mensagens/Genius/Carrinho — só desktop; no mobile viram drawer da direita) · `#footer` (nav bar inferior, só tablet/mobile). Preencha **só** os slots que a tela usa.

**Gotchas (verificados na index real):** o `MeLayout` usa `h-screen` — dentro de um preview/embed com altura própria, force `:deep(.me-layout){ height:100% !important }`. O header do MeLayout fica em `z-[10000]` → overlays/drawers contidos precisam ficar acima (ex.: `10001`).

## Acessibilidade

- Cada zona é um **landmark** semântico: `header`, `nav`, `main`, `aside` (rails) e `footer` — um `main` por tela.
- **Skip-link** "Pular para o conteúdo" como primeiro foco, levando ao `main`.
- Rails que abrem como **slideover** (mobile/contexto) gerenciam foco: foco entra no painel, `Esc` fecha e devolve o foco ao gatilho.
- Ordem de leitura/tabulação coerente com a hierarquia visual; nada de navegação só por cor.

---

## Phases

_Navegador das fases de um documento de processo — RFQ/RFP/RFI e suas rodadas, lotes de um leilão._

O **Phases** é o rail que estrutura um documento de **processo** (Cotação/RFQ, Leilão): lista as fases do processo — o arquivo inicial e suas rodadas, RFP, RFI — e deixa o usuário navegar entre elas sem sair do documento. É próprio das telas full-page de processo, à esquerda do conteúdo; não aparece em documentos simples (Pedido, Requisição…).

## Anatomia

| Parte | O que é |
|-------|---------|
| Cabeçalho | Título ("Phases") + ação **Criar novo** (adiciona uma fase). |
| Nó pai | Tile de ícone + nome da fase + badge **"N rodadas/passos"** + subtítulo (ex.: "Arquivo inicial"). O nó selecionado fica em destaque (tile sólido + texto primary). |
| Filhos | As rodadas/etapas da fase, ligadas ao pai por um **conector em árvore** (espinha vertical + ramo em L). Cada filho tem tile claro + nome + subtítulo. |

## Quando usar

| Quero… | Use |
|--------|-----|
| Navegar entre as fases de uma Cotação (rodadas, RFP, RFI) | **Phases** no documento de processo |
| Navegar entre lotes/rodadas de um Leilão | **Phases** |
| Trocar de seção dentro do **mesmo** documento (Itens, Histórico) | Tabs — não o Phases |
| Documento simples sem fases (Pedido, Requisição) | Sem rail — a tela é full-page direta |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Fase selecionada | Tile sólido primary + texto primary + fundo de realce; o conteúdo à direita reflete a fase. |
| Fase não selecionada | Tile claro (primary/10), texto neutro. |
| Fase **concluída** | Ícone de check no tile + tom de concluído — **sinal redundante à cor**. |
| Fase **em andamento (atual)** | Indicador de fase ativa do processo (não confundir com "selecionada", que é só a navegação). |
| Fase **futura / pendente** | Tom esmaecido; ainda não iniciada. |
| Com rodadas | Expande os filhos sob o conector em árvore. |

## Onde se aplica

## No código

Organism do EletroDS em **Design Labs** (Snow Flakes) — ainda sem entrada estável no catálogo. Confira o comportamento em [eletro.design](https://eletro.design) antes de usar; a API ainda pode mudar.

## Acessibilidade

- O rail é um **landmark de navegação** (lista/árvore); a fase **atual** é marcada com **`aria-current="step"`**.
- Os estados (concluída / atual / futura) têm **sinal redundante à cor** (ícone/texto + `aria-*`), nunca só o tom.
- **Teclado:** navegar as fases e rodadas por setas; `Enter` seleciona; foco visível em cada nó.
- O conector em árvore é decorativo (`aria-hidden`) — a relação pai/filho é exposta pela semântica da lista.

---

## Header

_A casca global do produto — marca, navegação, transversais e perfil. O block que ancora toda tela do ME._

O Header é a **app bar AZUL me-brand** global no topo de toda tela do produto: a marca "me." (branca) à esquerda, a **navegação principal HORIZONTAL** (áreas) no centro/topo, os serviços transversais (Mensagens, Genius, Carrinho) e o avatar/perfil à direita. O menu de áreas fica AQUI, no topo — nunca num rail/sidebar de ícones à esquerda. É a moldura que ancora o Layout e o Subheader — no mobile, vira uma barra compacta (menu + busca + carrinho) e a navegação desce para a NavBar no rodapé.

## Quando usar

- Em **toda tela autenticada** do produto — é a casca padrão, não um componente opcional.
- Para o estado **não autenticado** (ex.: login), troque o avatar/perfil por `action-items` (ex.: um botão "Entrar").

## Anatomia

| Zona | Prop | Papel |
|------|------|-------|
| Marca | `brand` | Logo + link (com `logoMobile` e cor de ícone). |
| Navegação | `navigation-items` | Itens (ícone + rótulo + `badge`); `separator` agrupa; `siteMap: true` abre o mapa do site. As transversais (Mensagens/Genius) entram aqui como itens com destino próprio. |
| Mapa do site | `site-map-items` | Áreas e seções da navegação expandida ("Mais"). |
| Perfil | `profile-items` · `user` | Avatar + menu (trocar conta, idioma, substituição, sair). |
| Não logado | `action-items` | Botões no lugar do avatar (ex.: "Entrar"). |
| Mobile | `cart-badge` · `hide-options` | Badge do carrinho; oculta carrinho/menu/busca. Emite `toggle-mobile-menu`, `cart`, `search`. |

A navegação cai para o layout mobile compacto quando os itens não cabem; `disable-mobile-layout` mantém o desktop sempre.

No **mobile** o app bar vira **BRANCO** (`bg-default`, logo ME **azul** — não a marca branca, que sumiria no fundo claro) e passa a **concentrar** os gatilhos: **hambúrguer** (abre o drawer da sidebar — ele SAI do subheader e vem pro header), **busca**, **transversais** e **avatar**. A navegação principal desce para a NavBar inferior (azul) e o CTA primário vira FAB. (Header claro no **desktop** = erro; no **mobile** = correto.)

## Marca e cor

No ME o Header é a **app bar AZUL me-brand** (cor primária = me-brand). A cor vem sempre dos tokens via `brand` (logo + `iconColor` + `background`) — nunca HEX cru no componente. **Header neutro/claro/verde = me-brand não aplicado (erro)** — normalmente falta a paleta `me-brand` mapeada em `--ui-primary` (tokens da suite me-foundations).

## No código

`MeHeader` (block EletroDS) — `user`, `brand`, `navigation-items`, `profile-items`, `site-map-items`, `action-items`, `cart-badge`, `hide-options`, `disable-mobile-layout`. Slots `#brand` e `#navigation-item`; eventos `cart` · `toggle-mobile-menu` · `search`. API e preview ao vivo em [eletro.design/blocks/header](https://eletro.design/blocks/header).

**Gotchas (verificados na index real):** o **divisor antes dos transversais** depende de `brand.iconColor` (ex.: `#FFFFFF`) — sem ele o separador **some**. O clique de um item da navegação dispara por **`item.click`** (não `onSelect`/`onClick`). Com muitos itens use `disable-mobile-layout` pra não compactar e sumir o divisor no desktop.

## Acessibilidade

- É o **landmark de cabeçalho** (`banner`) com a navegação principal (`nav` nomeado).
- Item ativo marcado com **`aria-current="page"`** — não só pela cor.
- Ícones de ação (carrinho/busca/menu) têm **rótulo acessível**; badges de contagem são anunciados.
- No mobile, o alvo de toque dos itens respeita **≥ 44px** e a ordem de tabulação é coerente.

---

## Collapsible

_Seção sanfonada (abrir/fechar) para agrupar conteúdo dentro de um documento — o disclosure do EDS sobre o Nuxt UI._

O Collapsible mostra/esconde um bloco de conteúdo por um cabeçalho clicável. No ME é a forma de agrupar seções dentro de um **documento** sem virar aba (regra: seção de 2–3 campos ou bloco complementar = collapsible, não aba). Usado em dois níveis hierárquicos.

## Dois níveis (XL × MD)

O ME usa dois estilos de collapsible, por profundidade:

| Nível | Quando | Header | Visual |
|-------|--------|--------|--------|
| **XL · outline** | seção de topo do corpo (Impostos, Exceções, Embalagem, Fabricantes, Anexos, Histórico de aprovações) | **label `text-lg font-semibold` à ESQUERDA** (`flex-1`) + **chevron à DIREITA** | box com borda (`rounded-lg border border-default`); conteúdo com **padding interno 16px** (`p-4`) |
| **MD · soft** | cards DENTRO de um XL (cada Exceção de ICMS/IPI) | **label `text-base font-medium`** + **badge** (Ativo/Inativo) + **chevron** — ordem `label → badge → chevron` | sem `bg` próprio (herda o fundo); **divider** entre os cards (`divide-y`); header com `hover:bg-elevated` |

- **Chevron:** fechado = **para baixo**; aberto = **para cima** — base `i-lucide-chevron-down` + `group-data-[state=open]:rotate-180`.
- Quando o painel pai tem fundo `bg-elevated`, os collapsibles internos **não** levam `bg-default` (ficam na mesma cor do fundo).

## Usage

```vue
<template>
  <!-- XL · outline · chevron à direita -->
  <UCollapsible :default-open="true" class="overflow-hidden rounded-lg border border-default">
    <button type="button" class="group flex w-full items-center gap-3 px-4 py-3 text-left">
      <span class="min-w-0 flex-1 text-lg font-semibold text-default">Impostos</span>
      <UIcon name="i-lucide-chevron-down" class="size-5 shrink-0 text-muted transition-transform group-data-[state=open]:rotate-180" />
    </button>
    <template #content>
      <div class="border-t border-default p-4"><!-- conteúdo (16px) --></div>
    </template>
  </UCollapsible>
</template>
```

## API

### Props
| Prop | Default | Type |
|------|---------|------|
| `default-open` | `false` | `boolean` <br> Estado inicial (não controlado). |
| `open` | - | `boolean` <br> Estado controlado (`v-model:open`). |
| `disabled` | `false` | `boolean` <br> Impede interação. |
| `unmount-on-hide` | `true` | `boolean` <br> Desmonta o conteúdo quando fechado. |
| `ui` | - | `{ root?, content? }` <br> Slots de classe. |

### Slots
| Slot | Type |
|------|------|
| `default` | `{}` — o gatilho (header custom). |
| `content` | `{}` — o conteúdo que abre/fecha. |

### Emits
| Event | Type |
|-------|------|
| `update:open` | `[value: boolean]` |

## Acessibilidade

- O gatilho é um `button` real, focável e acionável por teclado; expõe o estado (`aria-expanded`).
- O ícone de chevron é reforço visual — o estado não depende só dele.
- Contraste do label/borda via token (`text-default`/`text-muted`/`border-default`), sem HEX cru.

## Linguagem

- Título da seção = substantivo do conteúdo ("Impostos", "Anexos", "Exceções de ICMS"), não verbo.
- Badge do card interno reflete o estado do registro (Ativo/Inativo), com rótulo textual além da cor.

## Onde se aplica

---

## Forehead

_Cabeçalho de documento — banner, título, status, progresso e ações. O Subheader do documento._

O Forehead é o cabeçalho de uma tela de documento (cotação, pedido, contrato): reúne a identidade (banner + título + código), o status, o progresso (prazo/saldo) e a barra de ações do registro. É o equivalente, no documento, ao Subheader na index.

## Variantes por tipo

Cada tipo de registro tem a sua variação — muda o badge de identidade (DocumentBadge ou imagem), o título, as etiquetas, os dados e as ações. A **anatomia é a mesma** (Banner / Leading / Trailing); o que muda é o conteúdo do registro.

### Documentos (transações)

Cotação, Pedido, Pré-Pedido, Contrato, Requisição, FRS e Nota Fiscal: o **DocumentBadge** (tipo + número, com copiar), o título, a classificação, o valor e o status. O progresso (UProgress) aparece quando há prazo ou saldo.

### Produto (catálogo)

No catálogo o registro é um **produto**: o badge vira um **espaço de imagem**; ao lado, o nome com **etiquetas de tipo** (ex.: Material · Normal) e uma **descrição** curta. No trailing entra a **área de carrinho** — preço por unidade (`BRL (un)`) e **Baseline** lado a lado, o seletor de quantidade (InputNumber) e o botão **Adicionar ao carrinho**. É o que permite comprar direto da listagem. Ver Estrutura de Index › Catálogo.

### Fornecedor

O fornecedor traz o **logo** no lugar do badge, a **razão social** (com código) e etiquetas de relacionamento e situação — **Meu fornecedor**, o **status** (Liberado · Em homologação · Bloqueado) e o **tempo de relação** (ex.: 3 anos). Os dados de contato — CNPJ, endereço (com `+N` para mais endereços), telefones, e-mail e site — ficam no leading. No trailing, o selo **Visível para o marketplace** / **Privado** sinaliza a exposição do cadastro. Ver Estrutura de Index › Fornecedores.

### Item "novo"

Quando o registro acabou de ser criado ou adicionado, uma **barra azul à esquerda** marca o item como novo — a pessoa localiza na hora o que mudou na lista.

### Na listagem

Na index, o mesmo registro vira a linha da view **Lista**: o **mesmo Forehead empilhado**, entidade-aware — documentos mostram o cabeçalho do documento; produtos, a versão com carrinho; fornecedores, a ficha. Mantém a leitura numa varredura, sem abrir o registro. Ver Views.

## Composição

| Zona | O que traz |
|------|-----------|
| **Banner** | Identidade do tipo: **DocumentBadge** (tipo + número) nos documentos, ou **imagem / logo** em produto e fornecedor (`bannerVariant`: text · icon · image · user). |
| **Leading** | Título + código + etiquetas (UBadge: status, tipo, relacionamento) + meta (dados do registro / contatos) + progresso (UProgress). |
| **Trailing** | Valor, ou **área de carrinho** (produto), ou selo **Visível para o marketplace** (fornecedor); `MeForeheadActionBar` — ações neutras (favoritar, mensagens, Genius, mais) + **"Ver mais"**. |

## Variantes

| Quero… | Use |
|--------|-----|
| Identificar por ícone / imagem / avatar | `bannerVariant="icon" \| "image" \| "user"` |
| Mostrar prazo / saldo | progresso via `UProgress` no leading |
| Comprar da listagem (qtd + preço + CTA) | área de carrinho (`MeForeheadCartArea`) — produto / catálogo |
| Sinalizar exposição no marketplace | selo **Visível para o marketplace** / **Privado** — fornecedor |
| Marcar item recém-criado | barra **"novo"** à esquerda |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Por status | O status (UBadge) e as **ações disponíveis** mudam conforme o fluxo do documento. |
| Drawer | "Ver mais" expande indicadores / ações secundárias sem sair da tela. |
| Selecionável | Na view Lista, o item ganha **checkbox** de seleção e entra nas ações em massa. |

## Responsividade

No **mobile**, o Forehead empilha as zonas: a **imagem / badge ocupa a largura toda** no topo, o **checkbox de seleção fica sobreposto** ao canto superior-esquerdo do badge, e os **botões do trailing alinham na horizontal** (em vez de empilhados). No desktop, as zonas ficam lado a lado.

## No código

`<MeForehead>` é um componente EletroDS. Doc técnica em [eletro.design/components/forehead](https://eletro.design/components/forehead). Aqui o foco é o uso em Design.

## Acessibilidade

O título do documento é o heading da tela (h1). Ações só-ícone da action bar precisam de rótulo acessível. O status não pode depender só da cor — o rótulo textual no badge é o que garante a leitura.

## Onde se aplica

---

## Estados (carregando, vazio, erro)

_Como montar loading/skeleton, empty state e erro — e a ordem de prioridade entre eles._

Todo conteúdo que depende de dados tem **3 estados** além do normal: **carregando**, **vazio** e **erro**. Não improvise — use os componentes do EDS.

## Ordem de prioridade

No Widget: **erro → carregando → vazio → conteúdo**. Resolve um por vez; nunca empilha.

## Carregando (loading / skeleton)

- **Skeleton, não spinner**: a ilustração de carregamento respeita as dimensões do container que vai preencher e sinaliza estado ocupado para leitores de tela. Evita o "pulo" de layout quando o dado chega.
- **No chart**: o estado de carregamento substitui o desenho por um esqueleto do gráfico, mantendo a mesma área.
- **No bloco de analytics**: o carregamento desenha um skeleton no corpo. Use só para uma troca de nível superior (ex.: mudar o período de todo o bloco), não para cada chart interno.
- **No widget**: o carregamento é repassado ao bloco/chart de dentro — não monte um loading próprio por cima.

## Vazio (empty state)

Dois níveis:

**1. Dentro de um chart/card** — vazio "fino": ícone discreto (caixa vazia) mais um texto curto ("Sem dados"). Ocupa só a área do chart, sem chamar atenção indevida.

**2. Painel / página inteira** — vazio "rico": **título + descrição + ação primária**, com ilustração opcional. É o estado do painel recém-criado, que precisa convidar o usuário a começar (ex.: "Seu painel está em branco" / "Crie um novo ou copie widgets de outros painéis para começar." + botão "Novo gráfico").

Regras do empty:
- **Sempre uma saída**: uma ação primária que resolve o vazio ("Novo gráfico", "Criar…").
- **Texto orientado a ação** (o que fazer), não só "nada aqui".
- Em zonas de drop (sidebar de fixados), o vazio vira **dica de arraste** e, durante o arraste, um **alvo grande** ("Solte aqui para fixar").

## Erro

- **No chart/widget**: o erro vira um aviso ativo (anunciado a leitores de tela) com ícone de alerta e uma mensagem curta ("Erro ao carregar"). Sempre que possível, ofereça uma forma de **tentar de novo**.
- **Cor error** (ver Cores semânticas).
- **Erro ≠ vazio**: falha de busca é **erro**; resposta bem-sucedida sem registros é **vazio**. Não troque um pelo outro — a saída de cada um é diferente (tentar de novo × criar/ajustar filtro).

## Herança (não duplicar)

O **bloco de analytics herda** carregando/vazio/erro do **chart filho** — não duplique o estado nos dois níveis. O carregamento do bloco é só para um skeleton de nível superior (a troca do bloco inteiro).

### Quando não usar

- **Não use spinner** no lugar do skeleton em busca de dados — o skeleton preserva o layout; para spinner pontual, prefira o feedback inline do próprio controle.
- **Não mostre loading em interação direta** (drag, fixar, reordenar) — vá direto ao resultado; veja Toasts.

Props e slots de cada estado (loading/empty/error) ficam na referência técnica: [API completa no EletroDS](https://eletro.design/components/empty).

## Veja também

- Widgets · Analytics Block · Tabelas · Toasts · Cores semânticas

---

## Visão geral

_Visão geral dos charts do EDS — quando usar cada tipo, estados, legenda interativa e acessibilidade._

Os charts do EletroDS são componentes prontos para dashboards e telas analíticas. Cada tipo vive dentro de um `Card`, usa a paleta de tokens de chart (light/dark automático), legenda clicável no rodapé e tooltip no hover. A API é orientada aos dados do produto — você passa o dataset e as chaves, não opções brutas do motor de render.

## Quando usar cada tipo

Escolha pela pergunta que o gráfico responde, não pela aparência. Cada família tem página própria com variantes e exemplos.

| Tipo | Use quando | Quando NÃO usar | Doc |
|------|------------|------------------|-----|
| **Area** | Evolução temporal de uma métrica, com ênfase no volume sob a linha | Comparar categorias não temporais → use **Bar** | Area Charts |
| **Line** | Tendência ao longo do tempo, uma ou mais séries comparáveis | Poucos pontos sem continuidade temporal → use **Bar** | Line Charts |
| **Bar** / **Horizontal Bar** | Comparar categorias discretas; horizontal quando os rótulos são longos ou há muitas categorias | Mostrar partes de um todo → use **Pie/Donut** | Bar Charts |
| **Pie / Donut** | Partes de um todo, 2 a 6 categorias com proporções claras; donut quando há um valor agregado central | Muitas fatias finas → use **Bar** ou top N + "Outros" | Pie & Donut |
| **Radar** | Comparar várias dimensões de um mesmo item (perfil multidimensional) | Tendência ou ranking → use **Line** ou **Bar** | Radar Charts |
| **Radial** | Progresso (gauge `value`/`max`), multi-anel ou gauge stacked | Comparar séries entre si → use **Bar** | Radial Charts |
| **Analytics** (`KpiCard`, `TagCloud`) | Indicador único de destaque e nuvem de tags | Séries com eixos → use os tipos XY acima | Analytics |

A grade acima mostra um exemplo de cada tipo. Os charts XY (Area, Line, Bar, Horizontal Bar) compartilham a mesma base de props e comportamento; pie, donut, radar e radial recebem dados no formato `{ label, value }` ou séries específicas — os detalhes ficam nas páginas das famílias.

## Variantes de estilo e comportamento

- **Modo de exibição:** o modo padrão mostra título, eixos, legenda e tooltip. O modo compacto suprime tudo isso e deixa só o desenho — ideal para o gráfico viver dentro de um KPI ou widget pequeno.
- **Sem card:** o modo "bare" renderiza apenas o gráfico, sem `Card` nem título, para reuso dentro de um Widget que já traz a moldura.
- **Empilhamento:** barras aceitam séries empilhadas (stacked) quando o total da categoria importa tanto quanto a composição.
- **Tooltip e cores:** ver as seções **Tooltips** e **Cores das séries** abaixo.

## Legenda interativa

Todos os charts (exceto o radial sem rótulo) trazem a legenda no rodapé. Clicar num item oculta ou exibe a série correspondente — útil para isolar uma métrica sem recarregar dados. A série não-selecionada perde opacidade em vez de sumir, mantendo o contexto.

## Estados — loading, vazio e erro

Todos os charts e o `KpiCard` têm três estados, com prioridade `loading → erro → vazio → gráfico`. O skeleton e as mensagens respeitam as dimensões do container.

- **Loading:** skeleton no lugar do desenho enquanto a requisição do squad está em andamento.
- **Vazio:** mensagem padrão do EDS quando `data` chega vazio; pode ser personalizada por texto ou pelo slot de vazio (ex.: "Configure um filtro para ver os dados").
- **Erro:** alerta padrão quando a carga falha, também personalizável.

Os componentes não fazem fetch: `loading` e `error` são controlados pelo squad consumidor a partir do estado da própria requisição.

## Acessibilidade

Cada chart expõe `role="img"` + `aria-label` no desenho e renderiza uma tabela `sr-only` (invisível, lida por leitores de tela) com os dados como alternativa textual — gerada automaticamente a partir dos dados. Nada a configurar.

O `aria-label` é montado do título mais a descrição — ex.: título "Vendas" + descrição "Últimos 6 meses" vira *"Gráfico de linhas: Vendas — Últimos 6 meses"*. Por isso, sempre informe título e descrição com sentido completo.

## Responsividade

Cada chart observa o tamanho do pai e re-renderiza ao redimensionar, preenchendo a altura disponível. Em grids ou dashboards, garanta uma altura mínima no card (ex.: `min-h-[280px]`) para o desenho não colapsar.

## Importação e tipos

Os charts, o `KpiCard` e os widgets são a entrega "UI Blocks" do EDS, no pacote `@mercadoeletronico/eds-next` (o PDD os chama de `@eds/ui-blocks` — nome conceitual, não um pacote npm separado). Props, eventos e tipos têm contrato estável com os squads consumidores. Caminhos de import, nomes de tipo e assinatura de eventos (`update:activeIndex`, compatível com `v-model`) estão na [API completa no EletroDS](https://eletro.design/components/charts).

## Tooltips

Todos os charts exibem tooltip no hover por padrão (fundo do tema, borda, sombra, Roboto) — ajuste só indicador, rótulos e valores.

- **Indicador** — *Dot* (padrão, quadrado colorido por série), *Line* (linha vertical sólida), *Dashed* (tracejada, p/ série prevista) ou *Sem indicador* (valor único). Escolha pela leitura.
- **Ocultar o título** — a linha superior repete o valor do eixo X; oculte quando já é óbvio pela posição do cursor.
- **Formatters** — traduzem o dado cru para a linguagem do usuário (moeda pt-BR, datas localizadas) sem alterar a fonte; aplicam-se ao título e ao valor de cada série.
- **Customizado** — para mini-comparação, ícone de tendência ou múltiplas métricas, substitua por um componente próprio mantendo a mesma casca visual.
- **Por tipo** — linha/área/barra usam crosshair (reúne as séries no ponto X); pizza/rosca/radial mostram a fatia sob o cursor; radar, os vértices do eixo. No radial o trilho vazio não dispara tooltip.

## Cores das séries

As séries usam a **paleta de charts** — 10 cores categóricas e **não-semânticas** (cor de série só diferencia séries; status usa as cores semânticas). A atribuição é **automática**: cada série recebe `--chart-1`, `--chart-2`… em ordem, alternando quente/frio. Definição completa, valores light/dark e acessibilidade em **Tokens › Charts**.

**Acima de ~10 séries** o olho não diferencia as cores — prefira **Top N + "Outros"**, **small multiples** ou isolar a série por hover/legenda.

---

## Raiz única

_A fonte única que transforma configuração e dados em props de gráfico — o mesmo cálculo alimenta preview, index, sidebar e dashboard._

A **raiz única** é a função que pega a **configuração** de um gráfico (tipo + coluna + opções) somada aos **dados** e devolve as **props reais** que o componente de chart consome. É o ponto que garante coerência absoluta no produto.

## Por que existe

O preview do **Chart Wizard**, a **index**, a **sidebar** de fixados e o **dashboard** mostram **exatamente o mesmo gráfico** porque todos derivam daqui. Qualquer comportamento configurado (estilo, ordenação, limite, split, rótulo, período…) reflete em **todos** os lugares sem reimplementar o mapeamento à mão.

Em analogia de design system, a raiz única é o **token** do gráfico. O Wizard, a index e o dashboard são apenas **instâncias** que consomem o mesmo valor — ninguém redesenha a peça, todos referenciam a mesma definição.

## Da configuração às props

A raiz recebe o **tipo** do gráfico, a **coluna** do eixo X (dimensão de agrupamento), o **título**, as **opções** do wizard, os **dados** e o **schema de colunas**. A partir disso resolve, em ordem:

- **medida** — como o valor é calculado: contagem (padrão), distintos, soma, média, máximo, mínimo ou percentual.
- **ordenação** — nenhuma (padrão), crescente ou decrescente.
- **limite** — **Top 10 por padrão** (regra do produto); "todos" só quando explícito.
- **colunas derivadas** do schema — a numérica, a de data e a distinta. Quando o eixo X é uma **data**, a raiz cria um **balde** com o grão escolhido (dia/semana/mês/ano).
- **split** ("Separar por") — no modo de visualização **Simples** o split é ignorado.

### Quando o período entra

Tanto a montagem de props quanto os stats de cabeçalho filtram as linhas pelo **período antes de qualquer agregação**. A data de referência é a maior data do dataset (garante que o filtro relativo sempre mostre dados), e a janela varia por período (7d/30d = N dias; ytd = início do ano). Sem período ("todos") ou sem coluna de data, usa as linhas originais.

## O que muda por tipo de gráfico

A mesma raiz devolve a forma que cada tipo precisa, sem que o consumidor saiba do cálculo:

- **Pizza/Donut empilhada** (split) — vira **sunburst**: anel interno = coluna, externo = split.
- **Multi-série** (split em xy/radar) — dados **pivotados** por dimensão, uma categoria por segmento.
- **KPI** — rótulo + valor único agregado + ícone.
- **Tag cloud** — lista de tags com peso.
- **Radial gauge** — valor, máximo e valor central.
- **Radial multi-anel** — uma série por anel.
- **Série única** (pizza/donut/barra/linha/área/radar) — grupos diretos por dimensão.

Na série única de barra/linha/área a raiz ainda aplica regras finas de leitura: colore por categoria quando a barra liga a legenda, e usa um **rótulo contextual** na legenda (nunca o valor cru).

## Tipo salvo vs. tipo de render

A orientação é só uma opção: uma barra configurada como horizontal **renderiza** horizontal, mas o tipo **salvo** continua "barra". Por isso a configuração permanece estável e portátil — alternar orientação não troca o tipo do widget.

## Stats do cabeçalho de conteúdo

Quando o estilo **Interativa** liga o cabeçalho de conteúdo (o "2º header"), a raiz calcula os destaques exibidos ali. Cada stat traz **valor no período**, **tendência vs. período anterior** e o **índice** da categoria:

- O índice reaproveita o resultado da raiz, então a posição **bate** com a ordem das barras/fatias/eixo X — é o que viabiliza o **cross-highlight**.
- A tendência compara a janela atual com a anterior de mesmo tamanho. **Sem coluna de data, não há comparação.**
- Os destaques são até **2 dados fixados** ou, na ausência deles, o **Top 2** por valor. O cabeçalho exibe 1 ou 2 conforme a largura.

A tradução de cada controle do wizard para a prop final do componente também é fonte única, e a API completa de cada tipo de gráfico vive na doc técnica do EDS: [API completa no EletroDS](https://eletro.design/components/chart).

---

## Line Charts

_Linhas para tendência e comparação de séries no tempo — quando usar basic, step, multiple, dots, labels e interativo._

A família **Line Chart** liga pontos por linhas — ideal para **tendência e comparação de séries** ao longo de um eixo contínuo (tempo). Diferente da Area, não preenche a área: foca na **direção e na inclinação** da curva.

Visão geral: Charts. Tooltips: Chart Tooltips. Paleta: Chart Colors.

## Quando usar cada variante

- **Basic** — uma série, curva suave. O caso padrão para tendência de um único indicador.
- **Linear / Step** — linear conecta pontos em reta (sem suavização); **step** desenha a mudança em saltos, ideal para grandezas que mudam de patamar de forma discreta (preço fixo por faixa, status, estoque por lote).
- **Multiple** — várias séries no mesmo plano para comparação direta. Use legenda e mantenha poucas séries; acima de 4–5 linhas a leitura sofre.
- **Dots / Custom Dots / Dots Colors** — pontos nos vértices destacam observações individuais (úteis quando há poucos pontos ou quando cada ponto é um evento). O marcador *hollow* ou *custom* ajuda a distinguir séries sobrepostas.
- **Label** — valores ou rótulos sobre os pontos. Reserve para gráficos pequenos e poucos pontos; com muitos dados os rótulos colidem e poluem.
- **Interactive** — legenda clicável (liga/desliga séries) e tooltip por hover com crosshair. É o comportamento esperado quando o usuário precisa inspecionar valores exatos ou isolar uma série.

## Guia rápido

| Objetivo | Variante |
|----------|----------|
| Tendência de uma série | Basic |
| Mudança em saltos / patamares | Step |
| Comparar séries | Multiple |
| Destacar pontos individuais | Dots |
| Anotar valores na curva | Label |
| Inspecionar valores exatos | Interactive |

## Estados e acessibilidade

Loading exibe skeleton, vazio mostra mensagem e erro exibe um alerta — todos respeitam o container do gráfico. Uma tabela `sr-only` acompanha o desenho com a série completa, para leitores de tela.

## Performance — séries densas

Acima de **1000 pontos** o gráfico reamostra a série com **LTTB** (Largest-Triangle-Three-Buckets): preserva a *forma* da curva (picos e vales) e descarta o excesso, mantendo o desenho fluido. O primeiro e o último ponto são sempre mantidos; a tabela acessível continua usando a série completa, e uma nota discreta indica quando houve reamostragem (ex.: *"Exibindo 1000 de 5000 pontos"*). O limite é configurável e pode ser desligado.

## Quando não usar

---

## Bar Charts

_Barras verticais e horizontais — quando usar basic, grouped, stacked, horizontal, negative e a versão interativa._

A família **Bar Chart** mostra valores categóricos como barras retangulares — verticais ou horizontais. Use barras quando o foco é **comparar grandezas** entre categorias discretas (meses, produtos, regiões…).

Visão geral de todos os charts: Charts. Tooltip e formatters: Chart Tooltips. Paleta de cores: Chart Colors.

Todas as variantes usam a paleta `--chart-N` do EDS (cores adaptam light/dark automaticamente), a fonte **Roboto**, ficam dentro de um `Card` e têm **legenda clicável** no rodapé.

Dois componentes cobrem a família: **`BarChart`** (vertical) e **`HorizontalBarChart`** (horizontal). As variantes abaixo são combinações de props — empilhar, colorir por sinal/categoria, exibir valores ou habilitar seleção. Props, eventos e API completa estão no doc técnico:

[API completa no EletroDS](https://eletro.design/components/bar-chart)

Em qualquer variante, os estados de **loading**, **vazio** e **erro** são suportados nativamente — sempre prefira esses estados a esconder o gráfico, para manter o layout estável e dar feedback claro de carregamento ou falha.

---

## Basic

Barras verticais, **série única**. Compare um indicador entre categorias discretas (ex.: vendas mensais).

**Quando usar:** 6–12 categorias, ordem natural (tempo) ou ordenadas por valor.

**Quando NÃO usar:** mais de 15 categorias com rótulos longos (prefira **Horizontal**); partes de um todo 100% (prefira `PieChart` ou `DonutChart`).

---

## Multiple (Grouped)

Duas ou mais séries **lado a lado** em cada categoria.

**Quando usar:** comparar 2–4 métricas na mesma categoria (real vs meta, ano atual vs anterior).

**Quando NÃO usar:** composição de um total 100% (prefira **Stacked**); mais de 4 séries agrupadas (fica denso — considere small multiples).

---

## Stacked

Séries **empilhadas** no mesmo eixo — a altura total representa a soma. `HorizontalBarChart` também empilha horizontalmente.

**Quando usar:** mostrar total + composição (vendas por região, tráfego por canal).

**Quando NÃO usar:** comparar magnitudes absolutas entre séries de tamanhos muito diferentes (prefira **Multiple**); leitura precisa de cada fatia com muitas séries (prefira `PieChart` ou tabela).

---

## Horizontal

Barras horizontais — ideais para **rótulos longos** ou **muitas categorias** (rankings, produtos).

**Quando usar:** rankings, listas de produtos/regiões, mais de 8 categorias com nomes extensos.

**Quando NÃO usar:** eixo temporal curto com poucas categorias (barras verticais leem melhor a progressão no tempo).

---

## Mixed

Barras **horizontais** com **cor distinta por categoria**, sem eixo de valores — ideal para rankings visuais (ex.: share de browsers).

**Quando usar:** comparar categorias independentes onde cada barra pode ter cor própria.

**Quando NÃO usar:** comparar séries relacionadas na mesma escala (prefira **Multiple** ou **Stacked**).

---

## Negative

Valores **negativos** numa **série única** — barras acima e abaixo do zero, com cor por sinal. O nome de cada categoria pode ficar na ponta da barra: **acima** quando o valor é positivo e **abaixo** quando é negativo, mantendo o eixo zero limpo.

**Quando usar:** variação com sinal (ganho/perda, delta acima/abaixo de uma baseline).

**Quando NÃO usar:** duas métricas separadas positivas/negativas agrupadas (considere **Multiple** com séries distintas).

---

## Interactive

Todos os bar charts incluem **legenda interativa** e **tooltip no hover** por padrão.

- **Legenda:** clique em um item para ocultar/exibir a série — útil para focar uma métrica sem alterar o dataset.
- **Tooltip:** passe o mouse sobre uma barra para ver todas as séries ativas naquele ponto. A customização de conteúdo e formatação está em Chart Tooltips.
- **Crosshair:** linha-guia + ponto no hover. No `HorizontalBarChart` a guia é **horizontal** (acompanha a categoria sob o cursor), espelhando o comportamento vertical do `BarChart`.

---

## Active (seleção)

Destaca uma barra com **contorno tracejado**. Quando a seleção está habilitada, clicar numa barra a ativa e clicar de novo a desativa (seleção única + toggle). A barra ativa pode ser sincronizada com o estado do app, conectando a leitura do gráfico a filtros ou detalhes em outra área da tela.

---

## Label (valores nas barras)

Exibe valores **sobre barras verticais** ou **ao final de barras horizontais**. Em horizontal, o rótulo da categoria pode ficar dentro da própria barra.

> **Barras pequenas:** quando o nome não cabe dentro da barra (valor muito baixo), o rótulo da categoria — e o valor — saem automaticamente para **fora** da barra, na cor de texto normal, garantindo legibilidade.

---

## Guia rápido de escolha

| Objetivo | Variante |
|----------|----------|
| Uma métrica, poucas categorias | **Basic** |
| Comparar 2–4 métricas na mesma categoria | **Multiple** |
| Total + composição empilhada | **Stacked** |
| Muitas categorias ou rótulos longos | **Horizontal** |
| Valores positivos e negativos | **Negative** |
| Cor distinta por categoria (ranking) | **Mixed** |
| Destaque/seleção em uma barra | **Active** |
| Valores visíveis nas barras | **Label** |

---

## Area Charts

_Áreas preenchidas — quando usar cada variante (smooth, step, stacked, expanded, gradient) e estados._

A família **Area Chart** mostra a evolução de valores ao longo de um eixo (tempo) com a **área sob a linha preenchida**. Use quando o foco é **volume/tendência acumulada** — e, com várias séries, a **composição** ao longo do tempo.

Todas as variantes usam a paleta `--chart-N` (light/dark automático), ficam num `Card`, têm **linha forte no topo** da série, área translúcida e **gridlines** sutis. Múltiplas séries **empilham** (stacked) por padrão.

## Quando usar

Prefira Area Chart quando o que importa é a **massa acumulada** ou a **tendência** de uma métrica contínua no tempo, não o valor pontual de categorias soltas.

**Quando NÃO usar:** para comparar categorias discretas (ex.: vendas por região), use Bar Charts. Para acompanhar valores exatos sem ênfase em volume, prefira Line Charts.

## Variantes

### Basic

Série única, curva suave. A escolha padrão para a evolução de **um** indicador no tempo.

### Linear / Step

Muda só a interpolação da curva: `linear` traça segmentos retos entre pontos; `step` desenha patamares — ideal para valores que mudam em **saltos discretos** (preço de tabela, estoque), em que interpolar suavemente daria uma falsa sensação de transição contínua.

### Stacked

Duas ou mais séries empilhadas: a altura total é a **soma** das séries. Use para ver, ao mesmo tempo, o total e quanto cada série contribui para ele.

### Stacked Expanded

O empilhado **normalizado para 100%**. Some a magnitude absoluta e foque na **proporção** de cada série ao longo do tempo — bom para responder "qual a participação de cada parte" em vez de "quanto cresceu".

### Gradient

Preenchimento em **gradiente vertical** (forte no topo → transparente na base), com a linha do topo sólida. Puramente estético: melhora a leitura quando há sobreposição de séries, sem alterar os dados.

### Legend / Icons

Ative a **legenda** quando houver mais de uma série, para identificar e isolar séries no clique. Os ícones por série reforçam a identificação quando a cor sozinha não basta (acessibilidade, impressão).

### Axes

Exibe a **escala numérica do eixo Y** à esquerda. Use quando o leitor precisa ler valores aproximados, não só a forma da tendência.

### Interactive

Série densa (granularidade diária) ocupando a largura toda, com legenda e **tooltip no hover**. Indicado para dashboards onde o usuário explora pontos específicos — veja a customização em Chart Tooltips.

## Estados

Como nos demais charts, o componente trata **loading** (skeleton), **error** e **empty** (sem dados) com textos padrão do EDS — sempre prefira esses estados a esconder o gráfico.

## Guia rápido

| Objetivo | Variante |
|----------|----------|
| Tendência de uma métrica | **Basic** |
| Saltos discretos | **Step** |
| Total + composição no tempo | **Stacked** |
| Proporção (100%) | **Stacked Expanded** |
| Visual com fade | **Gradient** |
| Mostrar escala Y | **Axes** |

---

## Pie & Donut Charts

_Partes de um todo — pie, donut, label, list, legend, active, interactive e sunburst._

A família **Pie / Donut** mostra **partes de um todo** (composição percentual). O componente é o `PieChart`; com `arcWidth > 0` vira **donut** (anel). Use para 2–6 categorias que somam 100%.

Visão geral: Charts. Paleta: Chart Colors.

## Quando usar

Use o pie/donut para **2–6 categorias que somam um todo** — distribuição de gastos por centro de custo, participação por fornecedor, status de uma carteira. Acima de 6 fatias, ou quando os valores são próximos demais para distinguir pela área, a leitura fica imprecisa: prefira barras.

O **donut** (anel) libera o miolo para um número-âncora — o total ou o item em foco — e por isso é a forma preferida em dashboards. A **pizza cheia** funciona quando não há um valor central a destacar e a composição é o único recado.

## Pie / Separator / Labels

A pizza tem três ajustes de leitura que se acumulam conforme o número de fatias e o espaço disponível: o **separador** (stroke entre fatias) ajuda a distinguir cores vizinhas; os **rótulos externos** com risquinho nomeiam cada fatia sem poluir o centro; e o **label list** move os nomes para um painel lateral, indicado quando há muitos rótulos ou pouco espaço angular.

## Donut + text

O miolo do donut carrega um rótulo e um valor central — em geral o total da composição. É a variante de referência quando o número agregado importa tanto quanto a distribuição.

## Active

Clique numa fatia e ela cresce o raio externo e persiste em destaque; o centro passa a mostrar o item ativo. Use quando o usuário precisa **fixar** uma categoria para comparar ou inspecionar — a seleção fica até ele trocar.

## Interactive

A fatia sob o cursor cresce e ganha uma faixa externa, e o centro mostra o item; ao tirar o cursor, volta ao estado neutro. É exploração **passageira** (hover), oposta à seleção persistente da Active — bom para varrer rapidamente sem fixar nada.

## Sunburst (stacked)

Hierarquia em anéis concêntricos: o anel interno é a categoria-pai e o externo são os filhos (em tons do pai), alinhados dentro da fatia do pai. Use para mostrar **categoria → subcategoria** num só desenho — navegador → versões, departamento → centros de custo. Acima de dois níveis a leitura satura; aí prefira uma tabela ou drill-down.

---

## Guia rápido

| Objetivo | Variante |
|----------|----------|
| Composição simples | **Pie** |
| Com valor central | **Donut + Text** |
| Destacar uma fatia (clique) | **Active** (`selectable`) |
| Explorar no hover | **Interactive** (`growOnHover`) |
| Hierarquia (categoria → sub) | **Sunburst** (`hierarchy`) |

**Quando NÃO usar:** muitas categorias (>6) ou valores próximos — prefira Bar.

---

## Radar Charts

_Comparação multidimensional — dots, multiple, lines only, custom label, radius axis, grid e icons._

A família **Radar Chart** compara **várias dimensões** num mesmo polígono. Cada linha do dataset vira um **eixo** (dimensão); cada série vira um **polígono**. Use para perfis comparáveis (skills, meses, métricas).

Visão geral: Charts. Paleta: Chart Colors.

Quando o eixo é numérico (escala radial), mostre o **Radius Axis** para dar referência de magnitude; sem ele, o radar comunica **proporção/forma** entre dimensões, não valores absolutos. A legenda é clicável para isolar uma série, e o hover abre tooltip por vértice (detalhes em Chart Tooltips). Estados de carregamento, vazio e erro são tratados pelo próprio componente. A acessibilidade (`role="img"` + tabela equivalente para leitor de tela) é automática.

---

## Variantes

Comece pelo perfil único (área preenchida). Acrescente **Dots** quando os vértices precisam ser lidos individualmente; use **Multiple** para sobrepor perfis comparáveis; troque para **Lines Only** quando o preenchimento de várias séries gera ruído visual; e ative **Radius Axis** quando os valores forem numéricos e a escala importar.

### Grade

A grade é a "régua" do radar. Polígono (padrão) acompanha o número de eixos; **Grid Circle** suaviza para anéis circulares. **Grid Filled** preenche as faixas no tom da série para reforçar a leitura por nível, **Grid Custom** reduz os anéis ao mínimo para um visual mais limpo, e **Grid None** remove a grade quando a forma já basta (útil combinado com Dots).

### Custom Label / Icons

Use **Custom Label** para enriquecer o rótulo do eixo (ex.: incluir o valor de cada série junto ao nome da dimensão) e **Icons** para associar um ícone a cada série na legenda, facilitando a identificação rápida quando as cores não bastam.

---

## Guia rápido

| Objetivo | Variante |
|----------|----------|
| Perfil único | **base** |
| Comparar perfis | **Multiple** |
| Sem preenchimento | **Lines Only** |
| Mostrar escala | **Radius Axis** |
| Grade circular | **Grid Circle** |

**Quando NÃO usar:** muitos eixos (>8) ou séries (>3) — fica ilegível.

---

## Radial Charts

_Progresso e composição em arcos circulares — multi-anel, gauge de valor único e empilhado._

A família **Radial Chart** representa valores em **arcos circulares** — de gauges de progresso a múltiplos anéis concêntricos. Dois modos: **multi-anel** (uma série por anel) e **gauge** (valor único ou empilhado).

Visão geral: Charts. Paleta: Chart Colors.

[API completa no EletroDS](https://eletro.design/components/radial-charts)

## Quando usar cada variante

| Objetivo | Variante |
|----------|----------|
| Comparar várias séries em paralelo | Multi-anel (base / Label / Grid) |
| Progresso de um valor frente a um máximo | Text (gauge) |
| Indicador ou faixa de um único valor | Shape (gauge) |
| Composição de partes em meia-lua | Stacked (semicírculo) |

Prefira o radial quando o foco é **proporção em relação a um limite** (quanto do todo já foi atingido), não comparação livre de magnitudes — para isso, use Bar Charts.

## Multi-anel (base / Label / Grid)

Uma série por anel concêntrico — o arco preenchido corresponde a `valor / máximo`, com cantos retos. Use para **comparar poucas séries** lado a lado mantendo um referencial comum. Três acabamentos do mesmo gráfico:

- **Base** — apenas os anéis. Leitura mais limpa quando os rótulos vivem na legenda.
- **Label** — rótulo de texto dentro de cada anel; útil quando há espaço e poucos anéis.
- **Grid** — grade polar (teia) ao fundo, para reforçar a escala em apresentações.

## Text (gauge de progresso)

Arco que cresce a partir do topo sobre uma trilha de fundo, com número grande no centro e cantos arredondados. É a escolha para **progresso vs. máximo** (visitantes, metas, ocupação) onde o valor exato importa tanto quanto a proporção.

## Shape (gauge sem arredondar)

Mesmo gauge, com **cantos retos** — o valor aparece como uma faixa angular sólida. Prefira-o a *Text* quando o número for grande (não percentual) ou quando o visual reto combinar melhor com o resto do dashboard.

## Stacked (semicírculo)

Séries **empilhadas em meia-lua**, com o total no centro e os nomes na base. Use para mostrar a **composição de um total** quando há espaço vertical limitado — o semicírculo ocupa metade da altura de um anel completo.

## Quando não usar

---

## Analytics

_Blocos de métrica — KpiCard (indicador único) e TagCloud (nuvem de tags por peso) para dashboards._

A camada **Analytics** reúne blocos que comunicam **um número/destaque** — não são gráficos geométricos. Compõem dashboards ao lado das famílias de Charts.

## KpiCard

Indicador-chave: um número grande com rótulo, ícone em círculo tonalizado e uma variação opcional. Use quando a tela precisa destacar **uma métrica isolada** (conversões, total, ticket médio) em vez de uma série comparável.

A variação (`trend`) ganha um pill colorido por sinal: positivo em verde (`--ui-success`), negativo em vermelho (`--ui-error`) — tokens semânticos do EDS, ver Cores. Mostre a variação só quando ela ajuda a leitura; um KPI sem contexto temporal pode dispensá-la.

### Escala no compact (Sidebar)

No tamanho **padrão e maiores** o KpiCard mantém suas dimensões. Em **`compact`** (Sidebar), onde a altura vem do card estreito, o conteúdo **escala em proporção à altura disponível** (ícone, label, valor e trend) para não cortar nem ficar ilegível. No corpo (body) nada muda.

### Estados & acessibilidade

Cubra os três estados de dado: **carregando** (skeleton no lugar do conteúdo), **erro** (alerta com texto de falha) e **vazio** (quando não há valor). O card expõe `role="group"` + `aria-label` resumindo label, valor e variação, para que leitores de tela anunciem o indicador como uma unidade.

## TagCloud

Nuvem de tags onde **tamanho e cor variam com o peso** (maior peso = maior e mais "quente": cinza → teal → azul → laranja → vermelho). As posições são livres — não agrupa por peso.

**Quando usar:** distribuição de status/termos por frequência, quando o objetivo é dar a sensação do que pesa mais. **Quando NÃO usar:** valores precisos e comparáveis — prefira Bar.

---

## Timeline

_Sequência de eventos com data, título e ícone — a linha do tempo de aprovações/estados do documento (Nuxt UI)._

A Timeline mostra uma sequência de eventos (data · título · ícone). No ME aparece no **documento** para o histórico de aprovações/estados (Enviado → Rejeitado → Aprovado) e nas Rodadas/Históricos da cotação.

## Uso no ME (só o último nó colorido)

Convenção do ME: a linha é **horizontal** (`orientation="horizontal"`), `size="xs"`, `color="primary"`, e **apenas o último nó** fica colorido — os anteriores ficam **cinza**. Como `color="primary"` pinta os nós concluídos de azul, o cinza precisa de `!` para vencer:

```vue
<script setup>
const items = [
  { date: 'Mar 15 2025', title: 'Status: Enviado', icon: 'i-lucide-check', ui: { indicator: '!bg-[var(--ui-text-dimmed)] text-inverted' } },
  { date: 'Mar 22 2025', title: 'Status: Rejeitado', icon: 'i-lucide-x', ui: { indicator: '!bg-[var(--ui-text-dimmed)] text-inverted' } },
  { date: 'Mar 29 2025', title: 'Status: Aprovado', icon: 'i-lucide-check', ui: { indicator: '!bg-success text-inverted' } },
]
</script>
<template>
  <UTimeline orientation="horizontal" size="xs" color="primary" :items="items" :default-value="2" class="w-full" />
</template>
```

- `:default-value` marca o nó ativo (último). O `!bg-[var(--ui-text-dimmed)]` é `eds-allow` (token via var, não é HEX cru).
- Clicável quando precisa navegar entre etapas (evento `select`).

## API

### Props
| Prop | Default | Type |
|------|---------|------|
| `items` | - | `T[]` <br> `{ date?, title?, description?, icon?, value?, ui? }`. |
| `orientation` | `'vertical'` | `'horizontal' \| 'vertical'` |
| `size` | - | `'3xs'…'3xl'` |
| `color` | - | `'primary' \| 'success' \| 'error' \| ...` |
| `default-value` | - | `string \| number` <br> Nó ativo inicial. |
| `value-key` | `'value'` | `string` |
| `reverse` | `false` | `boolean` |
| `ui` | - | `{ root?, item?, indicator?, separator?, date?, title?, description?, ... }` |

### Slots
| Slot | Type |
|------|------|
| `indicator` · `date` · `title` · `description` · `wrapper` | `{}` |

### Emits
| Event | Type |
|-------|------|
| `select` | `[event: Event, item: T]` |
| `update:modelValue` | `[value: string \| number \| undefined]` |

## Acessibilidade

- Cada evento tem rótulo textual (data + título) — o estado não depende só do ícone/cor.
- Navegável por teclado quando os nós são clicáveis; foco visível.
- Cor do nó via token (`--ui-*`), com reforço por ícone (check/x).

## Onde se aplica

---

## Carousel

_Trilho horizontal navegável por setas — usado para os cards de "Itens relacionados" do documento (Nuxt UI, Embla)._

O Carousel exibe itens num trilho horizontal com navegação por **setas** (arraste opcional). No ME aparece no **documento de Produto › Itens relacionados**, com os **mesmos cards do Card View** dentro.

## Uso no ME (1 card por slide)

Cada slide é **um `MeCardView` com um item** (o mesmo card do grid), não um card custom — assim o carrossel e o modo grid ficam idênticos.

```vue
<template>
  <UCarousel
    v-slot="{ item: card }"
    :items="relCards"
    arrows
    prev-icon="i-lucide-chevron-left"
    next-icon="i-lucide-chevron-right"
    :ui="{ item: 'basis-80', container: 'gap-4', prev: 'start-1 sm:start-1', next: 'end-1 sm:end-1' }"
  >
    <MeCardView :data="[card]" selectable favorite>
      <template #card-extra-content><!-- fornecedor + tags --></template>
    </MeCardView>
  </UCarousel>
</template>
```

- **Setas dentro do trilho:** o default `-start-12/-end-12` joga as setas **para fora da tela** → sobrescreva `prev`/`next` no `:ui` (`start-1`/`end-1`).
- **Largura do slide:** `:ui="{ item: 'basis-80' }"` (≈320px) pra caber o card com stepper + carrinho.
- Esconder o header de select-all do bloco por slide via CSS (`:deep(.size-full) > :first-child { display: none }`). Ver `docs/documento-anatomia-me.md` §9.

## API

### Props
| Prop | Default | Type |
|------|---------|------|
| `items` | - | `T[]` <br> Itens do trilho (render no slot default). |
| `arrows` | `false` | `boolean` <br> Mostra setas prev/next. |
| `dots` | `false` | `boolean` <br> Mostra os pontos de navegação. |
| `orientation` | `'horizontal'` | `'horizontal' \| 'vertical'` |
| `prev` / `next` | - | `ButtonProps` <br> Config dos botões de seta. |
| `prev-icon` / `next-icon` | `arrow-left/right` | `string` |
| `loop` · `autoplay` · `auto-scroll` · `dragFree` | `false` | plugins Embla. |
| `ui` | - | `{ root?, viewport?, container?, item?, controls?, arrows?, prev?, next?, dots?, dot? }` |

### Slots
| Slot | Type |
|------|------|
| `default` | `{ item, index }` — cada slide. |

### Emits
| Event | Type |
|-------|------|
| `select` | `[selectedIndex: number]` |

## Acessibilidade

- Setas são `button` com nome acessível (Anterior/Próximo), focáveis; foco visível; alvo ≥ 44px.
- Conteúdo do slide (o card) mantém sua própria semântica (título como heading, ações rotuladas).
- Não usar autoplay em conteúdo essencial sem controle de pausa.

## Onde se aplica

---

## Colunas — redimensionar, reordenar e fixar

_Comportamento das colunas nas tabelas ME — a pessoa ajusta largura, ordem e congela colunas à esquerda; como o guide implementa isso por baixo._

Nas tabelas ME a pessoa **ajusta as colunas ao próprio trabalho**, sem sair da tela: muda a largura, troca a ordem e congela as importantes à esquerda. Mesma lógica de "Editar colunas" e do menu do cabeçalho.

## Comportamento (o que a pessoa faz)

| Ação | Como | Resultado |
| --- | --- | --- |
| **Redimensionar** | Arrasta a **borda direita** de um cabeçalho (cursor vira ↔). | A coluna muda de largura (mínimo = o nome do cabeçalho por extenso). A tabela rola na horizontal quando a soma passa da largura visível. |
| **Reordenar** | Arrasta o **corpo do cabeçalho** para outra posição. | Cabeçalho **e** coluna do corpo se movem juntos. Clique simples (sem arrastar) abre o menu de ordenar. |
| **Fixar (pin)** | Menu do cabeçalho → **Fixar coluna**. | A coluna **congela na esquerda** (logo após a caixa de seleção) e **fica visível** enquanto a tabela rola na horizontal — igual "congelar painel". Desfixar solta. |

*Por quê:* tabela larga com muitas colunas fica utilizável — a pessoa vê a coluna importante inteira, esconde ruído e mantém âncoras (nº, nome) fixas ao explorar o resto.

## Regras

- **Cabeçalho nunca trunca:** a coluna tem largura mínima igual ao nome por extenso.
- **Conteúdo trunca com "…"**, exceto quando "linhas por registro = **ajustar ao texto**" (aí quebra em várias linhas).
- **Fixar = congelar à esquerda**, não só reagrupar: a coluna (e a caixa de seleção) grudam na borda esquerda no scroll horizontal, com uma sombra marcando a divisa.
- **Reordenar por arraste** vale para as colunas; **ordenar/esconder/fixar** ficam no menu do cabeçalho.

## Onde se aplica

- **Index (listagem):** redimensionar + reordenar + fixar + ordenar/esconder.
- **Tabelas de documento** (Itens, Históricos, Endereços, Contatos…): redimensionar + reordenar.

---

## Views

_As três formas de uma index renderizar os mesmos registros — Cards, Lista e Preview. Trocadas pelo view switcher do subheader._

A index renderiza os mesmos registros de formas diferentes. A Tabela (block `TableView`) é o modo denso padrão; estes três blocks são as alternativas ricas, e a troca acontece no view switcher do Subheader (`gridMode`). *Qual* view cada entidade usa por padrão é decisão de produto — isso vive em Estrutura de Index; aqui estão os blocks.

## Uso em tela

Escolha a view pela natureza do registro, não por gosto: tabela quando o que importa é comparar colunas; os blocs abaixo quando a linha precisa de mais que células. Um único view switcher alterna entre elas — nunca recrie grid, lista ou painel à mão.

## Cards

Grid de cards visuais — imagem, título, badges e ações no card (selecionar, favoritar, carrinho). Ganha quando o item é reconhecido pelo visual e a compra é por descoberta (Catálogo). Suporta estados de seleção/favorito (`v-model`), loading e empty.

## Lista

Linhas altas e ricas — cada linha é o **Forehead do tipo de registro**, empilhado. A Lista é **entidade-aware**: a mesma view renderiza o forehead da entidade — **transações** mostram o cabeçalho do documento (tipo · número · status · valor); **produtos**, a versão com imagem + descrição + **área de carrinho** (comprar da listagem); **fornecedores**, a ficha (logo · razão social · CNPJ / contatos · status · marketplace). Ganha quando a linha precisa de mais que colunas. Traz paginação, seleção e linha ativa.

> **Seleção na Lista:** o `MeListView` mostra **avatar** por padrão; no hover vira checkbox; selecionado = check ativo — **só funciona se a linha tiver o campo `avatar`**. O checkbox de "selecionar todos" vive na Filter Bar (`show-select`), não no cabeçalho da lista.

## Preview

Master-detail: a lista à esquerda, o detalhe do selecionado à direita (iframe ou conteúdo próprio). Ganha para triagem — abrir e comparar vários registros sem sair da listagem. Exige altura definida no container. No subheader do detalhe, ao lado de **"Opções"**, um ícone **"abrir em outra janela"** leva à página única do documento. No mobile o painel de detalhe some e tocar no item abre o documento (modal-sheet).

Sem linha selecionada, o painel de detalhe mostra um **empty state** (título + descrição + 2 botões: "Abrir documento" / "Perguntar ao Genius"). Com linha ativa, o detalhe traz código-nome + badge, tipo · criado em/por, status badge + valor.

## Estados (por view)

As três views têm props nativas **`empty`** (`{ title, description, actions, src }` + slot `empty`) e **`loading`** (skeleton nativo; ListView aceita `loadingColor`/`loadingAnimation`). O estado de **erro NÃO é nativo** → trate com estado próprio (mensagem + "Tentar novamente"), no mesmo padrão do empty. Index vazia = título + descrição + ação ("Criar {entidade}").

## Gotchas de montagem (verificados na index real)

- **Cabeçalho/rodapé nativos "fantasma":** `MeListView` (select-all) e `MeCardView` trazem um `thead`/`tfoot` de TABELA que rende uma faixa vazia/faded quando não usados → **esconda** (`display:none` sob a classe da view). O `#header` nativo do MeListView é cabeçalho de 2 `<th>` (fica fracionado) → monte a barra do card **por fora** e esconda o thead.
- **Lista precisa de `avatar` na linha** para a seleção (avatar↔checkbox) funcionar.
- Trocar de view **preserva seleção e foco**; o botão de gráficos do subheader só existe no modo **tabela** (some ao trocar de view).

## No código

Blocks EletroDS. Doc técnico: [blocks/cardview](https://eletro.design/blocks/cardview) · [blocks/listview](https://eletro.design/blocks/listview) · [blocks/preview](https://eletro.design/blocks/preview). Aqui o foco é o uso em Design.

## Acessibilidade

Trocar de view deve preservar a seleção e o foco. Em Cards, a ação primária do card precisa de rótulo acessível (não só ícone). Em Lista, a linha rica precisa de estrutura semântica — não um amontoado de spans. Em Preview, o painel de detalhe deve ser anunciado ao abrir e alcançável por teclado.

## Onde se aplica

## Quando NÃO usar tabela

Para poucos atributos por item com forte componente visual (logo, miniatura, status em destaque), prefira **cards** em grade. A tabela é para **comparar muitas linhas pelos mesmos campos**; quando o foco é varredura rápida com pouca informação por item, use **lista**.

---

## Table

_A área de dados em tabela da index — o block TableView (MeTableView) do EletroDS, com colunas, ordenação, seleção e paginação prontos._

A Table é a área de dados em tabela da index — o view mode padrão (denso). O block `MeTableView` entrega colunas, ordenação por cabeçalho, seleção de linha (checkbox), busca e paginação; o `UTable` (Nuxt UI) é a base interna. Personalize colunas pelos slots `#<id>-cell` / `#<id>-header`.

## Uso em tela

Cabeçalho fixo (sticky), checkbox de seleção à esquerda, ações por linha (menu de mais ações) à direita e paginação no rodapé. O status de cada linha é um Badge com cor semântica, nunca texto solto. Quando a linha precisa de mais do que colunas comparáveis, troque pela Lista.

## Densidade e altura da linha

A altura da linha vem da **densidade** + **linhas por registro** (ambas no menu de ações):

| Densidade | Altura base |
|-----------|-------------|
| Compacto | **40px** |
| Regular (padrão) | **48px** |
| Espaçoso | **64px** |

**Linhas por registro**: `1` (padrão) · `2` (+20px) · `3` (+40px) · **Ajustar ao texto**. A altura efetiva = densidade + acréscimo das linhas.

## Paginação

- **Quando aparece:** só quando há **mais linhas do que cabem** na página (`linhas > página`). Se tudo cabe, **sem rodapé** (sem buraco).
- **Tamanho da página:** por padrão **preenche a área disponível** (auto-fill pela altura); o usuário pode fixar **10 / 20 / 50 / 100 itens**.
- **Como é:** rodapé colado à tabela com **`Exibindo X–Y de N`** + a paginação. Atalhos **Primeira / Última** no menu.
- **Seleção em massa NÃO fica no rodapé:** quando há itens marcados, a contagem vira **badge "N selecionados" na Filter Bar** (que desabilita os filtros enquanto a seleção está ativa) — não o padrão "N de M linha(s) selecionada(s)".

## Cabeçalho da coluna (menu + arrastar)

**Toda coluna** é um **button** (`color=neutral`, `size=md`) com o **ícone de sort à ESQUERDA, sem chevron**, em `text-muted` — e é **arrastável** (`draggable`) para **reposicionar** a coluna. Clicar abre o **dropdown** da coluna:

- **Ordenar** — pelo maior / pelo menor (`arrow-down-wide-narrow`); sem ordem = `arrow-up-down`.
- **Fixar / Desafixar coluna** (`pin`).
- **Ocultar coluna** (`eye-off`).
- **[só coluna chartable]** Criar gráfico (7 tipos) + Criar métrica (contador / distintos) — ver abaixo. O identificador único (Número) **não** é chartable: tem ordenar/fixar/ocultar, mas **sem** o grupo de widget.

## Editar colunas · resize

- **Editar colunas** (no menu ⋮ da tabela) → **modal com MeDualList** (inativas ↔ ativas, `draggable` → define a ordem; ativa/oculta = visibilidade).
- **Resize:** handle na borda do header — a coluna **atualiza ao arrastar** (sem confirmar). A largura **persiste** na sessão; colunas sem largura custom se ajustam para **preencher** a área (auto-fill), sem espaço vazio à direita.

## Tipos de célula

Cada coluna escolhe como apresentar o dado:

| Tipo | Quando usar | Comportamento |
|------|-------------|---------------|
| **select** | seleção em massa | checkbox no header (página inteira, com parcial) + um por linha |
| **nome** | item principal da linha | avatar/ícone + link para o detalhe |
| **pessoa** (owner) | responsável | avatar + texto |
| **status** | estado da linha | Badge semântico — cor pelo significado |
| **texto** (caminho, data, tamanho) | dado de apoio | texto secundário, sem destaque |
| **ações** | ações por linha | favoritar (★) + ⋮ "Ações da linha" |

## Gerar gráfico ou métrica a partir da coluna

O **menu do header** também cria visualizações daquela coluna:

- **Criar Gráfico** → tipos geométricos (Barras, Linhas, Área, Pizza, Radar, Radial…). Gera via raiz única e edita no ChartWizard.
- **Criar Métrica** → **Contador**, **Distintos** ou **Tag Cloud**.

O gráfico gerado entra no corpo e pode ser **fixado na sidebar** — ver Widgets e Gráficos.

## Ações da tabela (ao lado da busca)

Na Filter Bar (com `show-table-actions` + `table-more-menu`), ao lado da busca: **⋮ Mais ações** (Exportar · Editar colunas · densidade · linhas por registro · paginação · redefinir tabela), **"+"** (adicionar filtro / abrir o Wizard) e os **chips** de filtro/processo/período. A personalização de coluna acontece em **dois lugares**: por **coluna** (dropdown do cabeçalho: ordenar/fixar/ocultar + resize por arraste) e **em lote** (⋮ → Editar colunas → modal MeDualList).

> **⋮ "Mais ações" só existe na TABELA** (prop `more-actions`). Lista e Card não têm densidade nem paginação (rolam por scroll infinito).

> Listas de domínio (Fornecedores/Usuários/Catálogos) **não montam a tabela à mão**: usam o composable [`useFilterSearchPage`](https://eletro.design/composables/use-filter-search-page) + a Filter Search, que já integram busca, filtros e paginação.

## Responsividade

Segue a régua geral em Foundations › Breakpoints; o que é próprio da tabela:

| Largura | Comportamento |
|---------|---------------|
| **Desktop** · ≥ 1024px | Todas as colunas configuradas; scroll interno da área de conteúdo, não da página. |
| **Tablet** · 640–1024px | Scroll horizontal; colunas opcionais ocultadas automaticamente pelo breakpoint. |
| **Mobile** · < 640px | Scroll horizontal só com as colunas obrigatórias; a Lista ou os Cards são preferenciais quando disponíveis. |

## Estados

| Estado | Comportamento |
|--------|---------------|
| **Carregando** | Skeleton com a forma da tabela (linhas/colunas), evitando salto de layout — não uma tela em branco. |
| **Vazio** (sem registros) | Empty state curto + CTA para criar o primeiro item da entidade. |
| **Sem resultados** (filtro/busca) | Mensagem com o termo + ação de limpar filtros — distinto do vazio. |
| **Ordenação** | A coluna ordenável indica a direção (asc/desc) por ícone, não só por realce. |

## Acessibilidade

- Cabeçalhos com **`th scope="col"`** (e `scope="row"` quando houver coluna-rótulo); a tabela tem nome (`caption`/`aria-label`).
- Coluna ordenável expõe **`aria-sort`** e é acionável por teclado (`Enter`); a mudança de ordenação é anunciada (`aria-live`).
- Seleção (checkbox) anunciada — quantos itens marcados (`aria-live`); o recarregar/paginar também.
- Status da linha via Badge com **rótulo textual** (não só cor).

## Gotchas de montagem (verificados na index real)

Aprendidos montando a index de verdade com o `MeTableView` — reproduza, não reinterprete:

- **Altura & padding do corpo:** a área de dados **não colapsa a zero** só se houver um ancestral com altura definida (`h-full` + `flex flex-col` + `min-h-0`); o `#default` do `MeLayout` já rola. O padding lateral vem do **`#header` nativo** do MeTableView — **não** some outro `px-3` (vira 24).
- **Altura das células:** o table-header é **`h-12` (48px)**; `height` em `<th>`/`<td>` é **mínimo** → zere o padding vertical (`!py-0`) senão o conteúdo estoura. `ui.th`/`ui.td` **apendam** às classes base → use `!important` para vencer.
- **Checkbox líder** (célula de seleção do cabeçalho) casa a largura da coluna de seleção das linhas: **lista `w-9` (36px)**, **preview `w-11` (44px)**.
- **Scrollbar** da área de dados = a scrollbar padrão ME (fina, thumb `var(--ui-border-accented)`, track transparente).
- **Full-bleed:** a tabela encosta nas bordas do conteúdo — **sem** padding externo, borda externa ou `border-radius` próprios (o padding vem das células). Cards/lista mantêm o padding do grid.

## No código

`MeTableView` (block EletroDS) — `:data` + `:columns` (ColumnDef do TanStack); `:search="false"` esconde a busca, `showHeader: false` esconde a barra; slots `#<id>-cell` / `#<id>-header` para customizar colunas. Base interna: `UTable` ([ui.nuxt.com/docs/components/table](https://ui.nuxt.com/docs/components/table)).

## No documento (tabela HTML)

Nas telas de **documento** (Pedido, Fornecedor, Produto…) as tabelas internas **não** usam `MeTableView` — são **`<table>` HTML cru** (empilhar vários MeTableView travava o browser). Mesmo assim seguem o **mesmo padrão visual** — reproduza, não reinterprete:

- **Cabeçalho** (`thead th`): classe **`DOC_TH = 'px-3 !py-0 !h-10 align-middle'`** (40px). O rótulo é um **`UButton`** `color="neutral" variant="ghost" size="md"` com `-mx-2 font-semibold` e `:ui="{ label: '!text-muted', leadingIcon: '!text-muted' }"`, envolvido por **`UDropdownMenu`** (menu da coluna) — igual à index, mas sem resize/drag.
- **Menu da coluna** (`colMenu`): `[[Ordenar crescente, Ordenar decrescente], [Criar gráfico → tipos, Criar métrica → Contador/Distintos]]`. Ícone de sort: sem sort `arrow-up-down`; asc `arrow-up-narrow-wide`; desc `arrow-down-wide-narrow`.
- **Células** (`tbody td`): classe de densidade **`tdCls`** = `` `px-3 !py-0 align-middle ${DENSITY_TD[dens]}` `` (Compacto `!h-10` / Regular `!h-12` / Espaçoso `!h-16`).
- **Toolbar** acima da tabela: busca (`UInput`) + botão **gráfico** (`chart-column`, alterna o painel "Meus widgets") + **`VibeTableMoreMenu`** (mais ações: densidade/linhas/itens + exportar/paginação/editar colunas/restaurar). Sem paginação inline nem troca de visão a menos que a tela peça.
- **Widgets**: cada tabela tem sua instância (`makeWidgets()` → `{state, gerarGrafico, gerarMetrica, remover, limpar}`) — **vidas apartadas** (gerar num não abre no outro).
- **Rodapé de paginação** (quando usa): esquerda `"0 of 20 row(s) selected."` + direita Pagination (`UPagination` show-edges).
- **Scroll-x**: wrapper `.vibe-galscroll overflow-x-auto` + `<table class="w-full min-w-[NNNpx]">` (eds-allow no `min-w`).
- Detalhe fino completo: `docs/documento-anatomia-me.md` §6.

## Onde se aplica

---

## Badge

_Etiqueta de status ou categoria (Nuxt UI) — cor semântica. O status de toda linha da index._

O Badge é a etiqueta curta de status e categoria. Na index, todo status é um badge com cor semântica — nunca texto solto — para que a leitura seja a mesma em qualquer tela.

## Uso em tela

A cor carrega o significado e é fixa: success (concluído/ok), warning (aguardando/atenção), error (bloqueado/cancelado), neutral (rascunho/neutro), info (informativo/em curso). Em tabela, prefira `variant="subtle"` ou `soft` (menos peso). Reforce além da cor — o rótulo textual é o que garante acessibilidade. Mantenha o rótulo **curto (1–2 palavras)** — ex.: "Pendente", "Em análise"; o detalhe vai na descrição/tooltip, não no rótulo. A taxonomia completa por entidade vive em Estrutura de Index.

## Onde se aplica

## No código

`UBadge` — doc técnica em [ui.nuxt.com/docs/components/badge](https://ui.nuxt.com/docs/components/badge).

## Acessibilidade

- A cor **nunca sozinha**: o badge sempre traz **rótulo textual** (e, quando útil, ícone) — daltônicos e leitores de tela dependem do texto.
- Garanta **contraste AA** do texto sobre o fundo da variante (ver Foundations › Acessibilidade).
- Badge puramente informativo é estático; se for **interativo** (filtro/remover), precisa de nome acessível e foco.

---

## Pagination

_Navegação entre páginas de dados (Nuxt UI) — prev/next e páginas. O rodapé da index._

O Pagination navega entre páginas de um conjunto grande de registros. Aparece no rodapé da index, junto do range ("1–50 de 31.686") e do refresh — que são layout adjacente (toolbar), não parte do componente.

## Uso em tela

Botões de anterior/próxima e de página, com bordas (`showEdges`) para o início/fim quando há muitas páginas. O range e o refresh ficam ao lado, à esquerda ou à direita. Mantenha a página atual e o tamanho de página persistidos ao trocar de view ou aplicar filtro — o usuário não deve perder o lugar.

## No documento

Nas tabelas internas do **documento** (Históricos, Detalhes do item, Manuais…) o rodapé é: à **esquerda** o texto `"0 of 20 row(s) selected."` e à **direita** a paginação `UPagination` com **`show-edges`** + **`:sibling-count="1"`** (« ‹ 1 … 4 **5** 6 … 10 › »), `size="sm"`, `v-model:page`. Config típica: `:total="200" :items-per-page="20"`. Ver `docs/documento-anatomia-me.md` §6.

## No código

`UPagination` — doc técnica em [ui.nuxt.com/docs/components/pagination](https://ui.nuxt.com/docs/components/pagination). Props usadas: `v-model:page`, `total`, `items-per-page`, `sibling-count`, `show-edges`, `size`.

## Acessibilidade

- Está num **landmark de navegação** (`<nav aria-label="Paginação">`); a página atual usa **`aria-current="page"`** — não só a cor.
- Botões anterior/próxima e de página com **nome acessível** (ex.: "Página 4", "Próxima página").
- O range ("1–50 de 31.686") é anunciado por `aria-live` ao mudar de página.
- **Teclado:** todos os controles focáveis e acionáveis; **foco visível**; alvo ≥ 44px.

---

## Card

_Container de conteúdo agrupado (header/body/footer) — a unidade do dashboard (KPI e widgets)._

O Card agrupa conteúdo relacionado (header · body · footer) numa superfície com borda. Ele aparece em **dois papéis** no ME — não confunda:

- **Card (conteúdo)** — um **item em modo de visualização**: catálogo e listas renderizadas como cards. Mostra um **registro** (imagem/avatar, título, atributos, status, ações).
- **Widget** — a **unidade do dashboard**: um **KPI com número** ou um gráfico, com header, período e menu ⋮. É um card especializado, documentado em Widgets.

O Card também agrupa blocos em telas de detalhe e formulário.

## Card × Widget

Mesma base (superfície com borda), papéis distintos: o **Card** apresenta um **item**; o **Widget** apresenta uma **métrica/gráfico**.

## Variantes

| Quero… | Use |
|--------|-----|
| **Widget** KPI (número + variação) | Card especializado: rótulo + número grande + delta + ⋮ — ver Widgets |
| Widget de gráfico | Card como **moldura**: o gráfico é um **slot** (lib externa) — não há componente de chart no DS/Nuxt UI |
| **Card** de conteúdo (modo view) | Imagem/avatar + título + atributos + status + ações (catálogo, listas em card) |
| Agrupar um bloco de formulário/detalhe | Card com `header` (título do bloco) + body |
| Densidade da borda | `variant` (outline padrão) |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Default | Header opcional + body + footer opcional. |
| Loading | Skeleton no body enquanto carrega o dado do widget. |
| Vazio | Empty state dentro do card quando não há dado. |

## No código

`UCard` — doc técnica em [ui.nuxt.com/docs/components/card](https://ui.nuxt.com/docs/components/card).

## Card View (bloco) e carrossel — no documento

O **modo cards** de uma tabela e o **carrossel de itens** usam o **block `MeCardView`** (EletroDS) — não o `UCard` cru. Ele renderiza um **grid de cards** a partir de `:data` (`CardViewItemData`): `{ id, title, description, image, badges[{icon,color,description}], cart:{modelValue,min,onClick} }`, com props `selectable`/`favorite` (v-model `card-selection`/`card-favorite`), `card-height` (default **448px**) e slots `#header`, `#card-header`, `#card-image`, `#card-default`, `#card-extra-content` (ex.: "Por: fornecedor" + tags), `#card-footer`.

- **Catálogo do fornecedor**: MeCardView **sem** cart/select/favorite (só leitura); header/footer do card removidos.
- **Itens com contrato / Itens relacionados**: MeCardView **com** select + favoritar + cart (stepper + carrinho).
- **Carrossel** (Produto › Itens relacionados): `UCarousel` (Nuxt UI, Embla) com **1 `MeCardView` por slide** (mesmo card). Setas via `:ui="{ prev:'start-1', next:'end-1' }"` (o default sai da tela). Ver Carousel e `docs/documento-anatomia-me.md` §9.

## Acessibilidade

O título do card deve ser um heading real (não texto solto), para navegação por leitor de tela. Card puramente decorativo não deve capturar foco.

## Onde se aplica

---

## Analytics Block

_Container de contexto — envolve qualquer chart do EDS com header, período, status e ações._

O **AnalyticsBlock** é a camada de **contexto** do sistema de visualização do EDS. Ele envolve **qualquer chart** (via slot) e adiciona o cabeçalho padronizado: título, subtítulo, badge de status, seletor de período e menu de ações. Transforma um gráfico genérico num **bloco de análise** com significado.

> Camadas: **Charts** (desenho) → **Analytics Block** (contexto) → **Widget** (configuração do usuário) → **Dashboard** (layout). Aqui é a segunda.

## Quando usar

Use o AnalyticsBlock sempre que um gráfico precisar de **identidade e contexto** numa tela: um título que diz o que ele mede, um período que o usuário possa trocar, um status que sinalize saúde do dado e ações para fixar, copiar ou expandir. Sozinho, um chart é só desenho; dentro do bloco ele vira uma peça que a pessoa entende e opera.

### Quando NÃO usar

Não use para um número solto sem contexto de período nem ações — nesse caso, um **KpiCard** direto basta. Para layout de vários blocos lado a lado, o bloco não resolve grid: use o **Dashboard**.

## Exemplos

O mesmo bloco envolve **qualquer chart** — com tooltip no hover, linha-guia de interação e menu de ações no header:

Com `status="error"` o badge fica vermelho. **KpiCard** também entra no bloco (indicador + tendência):

## Status e período

O **badge de status** (`ok` / `warning` / `error`) só aparece quando definido — sem ele, nenhum selo "OK" padrão polui o header. Para um rótulo próprio (texto + cor), um selo custom tem prioridade sobre o status semântico.

O **seletor de período** ocupa o header só quando há opções para escolher; sem opções, sem seletor. Trocar o período não busca dados sozinho: o bloco **não faz fetch**. O squad fornece os dados ao chart filho e reage à troca de período recarregando o que precisa.

## Menu de ações

O kebab (⋮) reúne as ações do bloco: **Editar**, **Tipo de gráfico** ▸, **Copiar para** ▸, **Fixar na sidebar**, **Redefinir resolução padrão**, **Visualizar expandido** e **Remover**.

- **Tipo de gráfico** troca a visualização sem refazer o bloco (Área, Barra, Coluna, Linha, Rosca, Pizza, Radar, Radial, Tag Cloud, KPI) — o submeno lista os tipos compatíveis com os dados.
- **Copiar para** envia uma cópia **independente** para outra dashboard ou área; editar a cópia não afeta o original.
- No **modo compacto** (fixado na sidebar) o menu troca *Fixar / Redefinir / Visualizar* por **Desafixar da sidebar** e **Mover para o body**, refletindo as ações que fazem sentido naquele contexto.

## Cabeçalho de conteúdo dinâmico

Ative o 2º header **dentro do corpo** (padrão dos charts de estilo **Interactive**), acima do gráfico, com título/descrição próprios e **cards de dado fixado** que deixam de ser informativos e viram um mini-painel sincronizado com o gráfico:

- **Período filtra de verdade.** O seletor (7d/30d/ano) filtra os dados por data → gráfico **e** stats recalculam juntos.
- **Tendência ↑↓%.** Cada card compara o valor do período com o **período anterior** de mesmo tamanho: verde sobe, vermelho desce, "–" estável.
- **Em foco (hover).** Passar o mouse num segmento do gráfico atualiza o card "em foco" com a categoria, o valor e a **% do total**.
- **Cross-filter (clique).** Clicar num card destaca a categoria no gráfico — barra/fatia realçada ou **guia vertical** em linha/área. Clicar de novo limpa. É two-way com o clique no próprio gráfico.
- **Responsivo.** Com largura sobrando mostra 2 cards + o card em foco; estreito (< ~420px) mostra **1 card** e suprime o foco (não estoura).

## Modo compacto & herança

O compact colapsa o header (1 linha, sem descrição/filtros/footer; período vai pro menu) e — o ponto-chave — **propaga o modo ao chart filho automaticamente**. O chart inserido no slot herda `compact` (esconde eixos, legenda e tooltip) **sem precisar de prop manual**.

Ele entra em compact de **dois jeitos**:

- **Automático por largura:** o bloco observa o próprio tamanho e colapsa sozinho quando a coluna fica estreita (`< 240px`) — ex.: ao ser inserido na Sidebar. Nesse modo o **seletor de período sai do header** e vira item do menu ⋮.
- **Manual:** forçar o modo compact (override) quando o layout exige.

## Estados

`loading` / `empty` são **herdados do chart filho** — o AnalyticsBlock não duplica. Use o loading do bloco apenas para um skeleton de nível superior (ex.: enquanto troca o período).

## Onde se aplica

## Veja também

- [API completa no EletroDS](https://eletro.design/components/analytics-block)
- Charts (Analytics: KpiCard / TagCloud)
- Responsivo

---

## Chart Wizard

_Criação guiada de gráfico em tela única — tipo, dados, estilo/interação, rótulo e selo, com preview ao vivo._

O **ChartWizard** é o componente autônomo de **criação guiada** de gráficos (PDD-3514). Em **tela única** — tipo → dados → estilo/ajustes → detalhes — com **preview ao vivo**. Vai além do básico: **estilos interativos**, **rótulo**, **selo**, **cabeçalho de conteúdo** e **mistura de dados** (múltiplas séries) para gráficos mais completos. Funciona em qualquer contexto (Dashboard, Index de documentos…): recebe o schema de colunas e emite a config gerada via `on-chart-created`. **Desacoplado** — não conhece o Dashboard.

Os estilos **Interactive** (ex.: Pizza/Donut Interativa) habilitam o **cabeçalho de conteúdo**: título/descrição próprios + **cards de dado fixado** (valor + tendência) sincronizados com o gráfico. Ver AnalyticsBlock — cabeçalho de conteúdo.

## Uso

Recebe o schema de colunas da tabela ativa, uma amostra de dados para o preview e as opções de período; abre via `v-model:open` e, ao concluir, emite a configuração gerada. O squad decide o que fazer com ela: renderizar um Widget, adicionar ao Dashboard ou persistir no backend. Passar uma config existente reabre o wizard em **modo edição**, pré-preenchido.

[API completa no EletroDS](https://eletro.design/components/chart-wizard)

## Fluxo

Numa **única tela** com **preview ao vivo**: escolhe o **tipo**, mapeia os **dados** (Index/Coluna), ajusta **estilo e interação**, e define **título/período**. **Criar gráfico** emite `on-chart-created(config)`.

1. **Tipo** — Barras · Linhas · Área · Pizza · Radar · Radial · Tag Cloud · KPI. (Barra horizontal e Donut saem de ajustes/estilos do próprio tipo.)
2. **Dados** — `xKey` (Coluna/dimensão) + a fonte; KPI lê só a coluna de valor.
3. **Estilo + Ajustes** — variante visual + controles (abaixo).
4. **Detalhes** — título, período e **selo**.

**Teclado:** `Esc` fecha, `Enter` conclui (fora de campos); tipos/selects/botões focáveis (Tab + Enter).

## Estilos (variantes)

Cada tipo tem uma faixa de **estilos** (miniaturas) que pré-configuram o gráfico — ex.: Barras **Padrão / Ativa / Negativa / Empilhada / Interativa**; Pizza **Padrão / Donut / Empilhada / Interativa**; Linha/Área **Padrão / Linear / Degraus / (Gradiente) / Interativa**. O estilo **Interativa** liga os recursos interativos (hover destaca, clique trava) e habilita o **cabeçalho de conteúdo** (abaixo).

## Rótulo

Liga o **valor sobre o dado** (rótulo de dado), independente da variante. O controle varia por tipo: `Rótulo` (barras), `Rótulos` (barra horizontal/radar/radial), `Rótulo` de fatia (pizza), `Rótulo do ponto` (linha). Em alguns tipos é um seletor (nenhum / valor / percentual).

## Selo

Badge **custom** no header do card (texto + cor da tematização), **prioritário sobre o status**. Escolhe-se um selo existente ou **cria-se um novo** (`+ Criar selo…`, persistido em `localStorage`). Reflete no card gerado — inclusive em cards dentro de grupos. Ver Analytics Block.

## Misturar dados (séries múltiplas)

Para gráficos mais completos, combine mais de uma dimensão:

- **Tipo de visualização: Múltiplo** + **Separar por** — quebra a Coluna em **várias séries** (uma cor por valor do campo escolhido). Ex.: pedidos por mês **separados por status**.
- **Empilhada** — soma as séries numa só barra/área (Área aceita Empilhamento `Normal` ou `100%`).
- **Pizza Empilhada** — vira **sunburst**: anel interno = Coluna, anel externo = `Separar por`.
- **Mista** (série única) — cada barra com uma cor distinta.

A agregação (contagem/medida, ordenação, Top N) é a mesma raiz `buildChartProps` usada no preview, na index e no dashboard.

## Medida · Ordenação · Limite · Legenda · Tooltip

Conforme o tipo suporta: **Medida** (contagem ou soma de uma coluna numérica), **Ordenação** (nenhuma/asc/desc), **Limite** (Top N — padrão **Top 10**, ou Todos), **Legenda** (com marcador) e **Tooltip no hover**.

## Modo interativo + cabeçalho de conteúdo

No estilo **Interativa**, libera-se o **Cabeçalho de conteúdo** (2º header dentro do corpo): título/descrição próprios + **dados fixados** (máx. 2) que viram um mini-painel sincronizado — período filtra de verdade, mostra tendência ↑↓% vs período anterior, e cruza com o gráfico (hover/clique). Detalhes e o tipo `ContentStat` em Analytics Block › Cabeçalho de conteúdo dinâmico.

## Quando não usar

Não use o ChartWizard para exibir um gráfico já configurado — para renderizar a visualização final use o Widget. O wizard é só o passo de **criação/edição** da config.

## Onde se aplica

## Veja também

- Widget · Analytics Block · [Charts](https://eletro.design/components/charts)

---

## Widgets

_Envoltório (shell) que renderiza qualquer chart ou analytics via type, com header, menu de ações e estados._

O **Widget** é a camada que **envolve qualquer chart ou componente de analytics** num `Card`, com **título**, **descrição**, **menu de ações** e **estados** (loading / empty / error). Ele **roteia** o conteúdo pela prop `type` — não precisa importar o chart manualmente.

> Camada 3 da taxonomia: [Charts](https://eletro.design/components/charts) → Analytics → **Widgets** → Dashboard.

## Exemplos

Chart, KPI e pie como widgets, mais o estado de carregamento. Cada widget é um card com header (título + descrição), menu **⋮** e o desenho do gráfico abaixo.

## Menu de ações (⋮)

O menu do widget reúne, em uma só lista: **Editar**, **Tipo de gráfico ▸**, **Copiar para ▸**, **Fixar na sidebar**, **Redefinir resolução padrão**, **Visualizar expandido** e **Remover**.

- **Tipo de gráfico** troca a visualização sem refazer o widget — Área, Barra, Coluna, Linha, Rosca, Pizza, Radar, Radial, Tag Cloud e KPI ficam num submenu. Trocar o tipo preserva os dados e a configuração de colunas.
- **Copiar para** envia uma cópia independente do widget para outra dashboard/área. As opções vêm das abas/áreas conhecidas pela tela; a cópia passa a ter vida própria.
- **Modo compacto** (widget fixado na sidebar): o menu substitui *Fixar / Redefinir resolução / Visualizar expandido* por **Desafixar da sidebar** e **Mover para o body** — as ações que só fazem sentido no corpo somem para reduzir ruído.

## Composição

O Widget **compõe o AnalyticsBlock** (camada de contexto) e instancia o gráfico certo no slot — herdando `bare`/`mode` automaticamente, sem card-dentro-de-card. Por cima, ele adiciona a camada de **personalização do usuário**: tipo e colunas (via ChartWizard) e portabilidade (copiar/fixar).

> Camadas: **Chart** (desenho) → **AnalyticsBlock** (contexto) → **Widget** (configuração do usuário) → **Dashboard** (layout).

Para dirigir o widget, prefira uma `config` persistível (tipo, colunas, título, período, fixado) sobre passar `type` + `props` soltos — a config é o que a tela salva e recarrega. O header pode exibir um badge de **status** (ok / warning / error) ou um **selo custom** (texto + cor); o selo tem prioridade. Um **seletor de período** no topo e um rodapé "Atualizado…" aparecem só quando alimentados.

## Estados

Prioridade de renderização: **error → loading → empty → conteúdo**.

- **Loading** — esqueleto no lugar do desenho (`aria-busy`).
- **Empty** — deduzido de dados vazios, ou forçado; comunica "sem dados" sem parecer erro.
- **Error** — faixa de erro com mensagem opcional (`role="alert"`).

## Modos

- **`default`** — ocupa a proporção do grid no body/Dashboard.
- **`compact`** — altura máxima fixa, para fixar na Sidebar sem estourar. Esconde eixos, legenda e descrição: fica só o título + o desenho. Entra em compact **automaticamente** quando a largura do bloco fica `< 240px` (container, não viewport — ver Responsivo).
- Mobile: full width.

## Ciclo na tela (drag-and-drop)

Numa tela real (ex.: a **Index** de Transações), o Widget percorre um ciclo completo. O componente só **emite eventos** — quem orquestra layout e persistência é a tela/squad.

1. **Criar** — pelo menu do cabeçalho de uma coluna da tabela (gera um chart/métrica daquela coluna). A edição abre o ChartWizard.
2. **Editar** — **⋮ → Editar** reabre o Wizard pré-preenchido.
3. **Fixar na sidebar** — arrastar o card do corpo até a seção **Gráficos** da sidebar (ou **⋮ → Fixar**). Vira uma **cópia independente** em modo compacto, agrupada pelo contexto de origem (Compras, Contratos…).
4. **Copiar para a dashboard** — **⋮ → Copiar para**, escolhendo a aba de destino.
5. **Persistir** — a tela salva o layout (no demo, `localStorage`; em produção, o endpoint do squad).

As áreas **corpo** e **sidebar** são simétricas: dá pra arrastar nos dois sentidos e reordenar dentro de cada uma. Cópias têm **vidas apartadas** (editar/remover uma não afeta a outra).

## Quando não usar

- Para um único gráfico fixo, sem header, menu nem personalização do usuário, use o [Chart](https://eletro.design/components/charts) direto (ou o AnalyticsBlock quando precisar só do contexto).

## Acessibilidade

- `role="region"` + `aria-label` (título + descrição).
- Erro com `role="alert"`; loading com `aria-busy`.

## Onde se aplica

## Veja também

- [Charts](https://eletro.design/components/charts) · Analytics · AnalyticsBlock · ChartWizard · Widgets & Dashboard

---

## Spinner

_Indicador de carregamento sem porcentagem — variantes border, grow e logo (marca)._

O Spinner sinaliza carregamento sem porcentagem (não sabemos quanto falta). O ME tem três variantes — border, grow e logo (a marca). Quando o progresso é mensurável (prazo, upload), use o Progress.

## Variantes

| Quero… | Use |
|--------|-----|
| Loading inline (botão, widget, célula) | `variant="border"` (padrão) |
| Pulso mais suave | `variant="grow"` |
| Tela/contexto de marca | `variant="logo"` — diferencial do ME |

## Uso

| Cenário | Como |
|---------|------|
| Inline | Spinner pequeno dentro do botão/widget que carrega. |
| Overlay de tela | Spinner centralizado sobre a área que está buscando dados. |

## No código

`<MeSpinner>` é um componente EletroDS. Doc técnica em [eletro.design/components/spinner](https://eletro.design/components/spinner). Aqui o foco é o uso em Design.

## Acessibilidade

Marque a região como `aria-busy="true"` e dê um rótulo "Carregando". Respeite `prefers-reduced-motion` — reduza/elimine a animação para quem pediu menos movimento.

---

## Tooltip

_Dica curta revelada ao passar o cursor — rótulo de um ícone, atalho, esclarecimento._

O Tooltip revela uma dica curta ao passar o cursor (ou focar) sobre um elemento — tipicamente o rótulo de um botão só-ícone (a action bar do Forehead e o ButtonBar usam). Nunca esconda informação essencial só no tooltip.

## Variantes

| Quero… | Use |
|--------|-----|
| Posição | `placement` (top · right · bottom · left) |
| Setinha apontando | `arrow` |

## No código

`<MeTooltip>` é um componente EletroDS. Doc técnica em [eletro.design/components/tooltip](https://eletro.design/components/tooltip). Aqui o foco é o uso em Design.

## Acessibilidade

Não dependa só do hover — o tooltip precisa aparecer no foco por teclado também. Conteúdo essencial não pode viver só aqui (quem usa toque/teclado pode não alcançar). Para botão só-ícone, o tooltip complementa, mas o `aria-label` é o que garante o nome acessível.

---

## Modal

_Janela de diálogo sobreposta (Nuxt UI) — confirmações irreversíveis e a casca do editor de colunas._

O Modal é um diálogo sobreposto que bloqueia o fundo até uma decisão. Na index aparece em dois papéis: confirmar uma ação irreversível (excluir, cancelar — com motivo quando exigido) e como casca do "Editar colunas" (o DualList).

## Uso em tela

Título + corpo + rodapé com Cancelar (secundário) e a ação primária à direita. Reserve o modal para o que interrompe o fluxo: confirmações destrutivas e edições focadas. Ações reversíveis não usam modal — usam toast com Desfazer (ver Excluir). O overlay deve fechar por Esc e por clique fora quando a ação não for destrutiva.

Quando o modal abre um **documento** (pela index), o topo ganha um **chrome** próprio — breadcrumb + "abrir em outra janela" + fechar (X). Esse chrome é **exclusivo do modal**: a página única do documento não o tem — ver Modal × página única.

## Responsividade

Segue a régua geral em Foundations › Breakpoints; o que é próprio do modal:

| Largura | Comportamento |
|---------|---------------|
| **Desktop** · ≥ 1024px | Diálogo centrado de largura contida (limitada pelos tokens de largura), sobre o backdrop. |
| **Tablet** · 640–1024px | Igual ao desktop, largura adaptada. |
| **Mobile** · < 640px | Vira **bottom-sheet** ou **fullscreen** — ocupa a largura da tela e ancora na base. |

## Acessibilidade

- `role="dialog"` + **`aria-modal`**, com nome via **`aria-labelledby`** (o título do modal).
- **Foco inicial** entra no modal ao abrir; **focus-trap** mantém o Tab dentro; ao fechar, o **foco volta ao gatilho**.
- Fecha por **`Esc`** e clique no backdrop **quando não destrutivo** (ações destrutivas exigem decisão explícita — ver Excluir).
- **Não aninhe modais**; o conteúdo atrás fica inerte (`aria-hidden`/`inert`).
- Botão de confirmação destrutivo não é o foco inicial nem o default do `Enter`.

## No código

`UModal` — doc técnica em [ui.nuxt.com/docs/components/modal](https://ui.nuxt.com/docs/components/modal).

---

## Toast

_Feedback efêmero de resultado — "deu certo", erro, ou ação reversível com Desfazer._

O Toast é a notificação efêmera que confirma o resultado de uma ação — salvo, excluído, erro. É o canal padrão do feedback reversível: em vez de um modal, mostra "Item excluído" + Desfazer.

## Variantes

| Quero… | Use |
|--------|-----|
| Confirmar sucesso | `color="success"` + ícone de check |
| Sinalizar erro | `color="error"` |
| Permitir desfazer | ação **Desfazer** no toast (5–8s) — ver Desfazer |
| Operação longa | toast com progresso/carregando |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Entrada | Surge no canto, dura alguns segundos, some sozinho. |
| Com ação | Pausa o timer no hover; "Desfazer" reverte. |
| Erro | Pode exigir fechar manualmente (não some sozinho). |

## Onde se aplica

## No código

`useToast()` — doc técnica em [ui.nuxt.com/docs/components/toast](https://ui.nuxt.com/docs/components/toast).

## Acessibilidade

Anunciar via `role="status"` (ou `alert` para erro). Não depender só da cor — ícone + texto. Dar tempo suficiente para ler e agir (sobretudo quando há "Desfazer").

---

## Progress

_Progresso determinado — prazo, saldo, upload, meta. Barra linear com tom semântico._

O Progress mostra o avanço de algo mensurável: prazo de um documento, saldo de um contrato, upload, meta de um widget. É barra linear; para "está carregando" sem porcentagem, use o Spinner.

## Variantes

| Quero… | Use |
|--------|-----|
| Progresso conhecido (%) | `v-model` determinado |
| Carregando sem % | estado indeterminado (anima sem valor) |
| Sinalizar atenção | `color` semântico (warning para saldo baixo / prazo curto) |

## Estados

| Estado | Comportamento |
|--------|---------------|
| Determinado | Preenche conforme o valor (0–100%). |
| Indeterminado | Animação contínua (não sabe quanto falta). |

## No código

`UProgress` — doc técnica em [ui.nuxt.com/docs/components/progress](https://ui.nuxt.com/docs/components/progress).

## Acessibilidade

`role="progressbar"` com `aria-valuenow`/`min`/`max`; rótulo do que está progredindo. A cor (warning/error) precisa de reforço textual (o número/legenda).

---

## Alert

_Mensagem persistente inline — aviso ou erro de um bloco. Diferente do Toast (efêmero)._

O Alert é uma mensagem persistente, inline — fica na tela junto do conteúdo a que se refere (aviso de prazo, erro de um bloco do formulário). É o oposto do Toast, que é efêmero e some sozinho.

## Variantes

| Quero… | Use |
|--------|-----|
| Tom do aviso | `color` semântico (warning, error, info, success) |
| Peso visual | `variant` (subtle / soft / outline) |
| Permitir fechar | `close` |
| Ação inline | slot de ações (ex.: "Renovar prazo") |

## No código

`UAlert` — doc técnica em [ui.nuxt.com/docs/components/alert](https://ui.nuxt.com/docs/components/alert).

## Acessibilidade

Erro usa `role="alert"` (anunciado na hora); aviso informativo, `role="status"`. Não dependa só da cor — ícone + título carregam o significado.

---

## Drawer

_Painel lateral sobreposto (USlideOver / UDrawer) — carrinho, mensagens, Genius e anexos._

O **Drawer** é um painel que desliza sobre o conteúdo, sem tirar o usuário da tela. No ME ele carrega o que é **transversal ou complementar** ao contexto atual.

## Onde o ME usa

| Uso | Lado | Observação |
|-----|------|------------|
| Carrinho | Direita (`#right-area` do MeLayout) | **Carrinho XOR Mensagens** — nunca os dois juntos; troca conforme o contexto. |
| Mensagens (chat) | Direita (`#right-area`) | Painel contextual; no desktop pode **expandir** para tela cheia. |
| Genius | Direita / assistente | Idem — expande no desktop. |
| **Anexos** | Drawer (nunca modal) | Anexos de um documento **abrem em drawer**, não em modal. |

## Boas práticas

- **Anexos e painéis contextuais → drawer**, não modal. Modal é para **confirmação irreversível** ou fluxo que exige foco total (ver Modal).
- **`#right-area` do chassi** aloja um transversal por vez (Carrinho **XOR** Mensagens); a troca é mutuamente exclusiva.
- **Mobile:** o drawer ocupa quase toda a largura e desliza da lateral; fecha tocando fora (scrim). Sem "X" quando o padrão for fechar por fora.
- **Título + fechar** no topo; conteúdo rola por dentro; ações fixas no rodapé quando houver.

## Quando NÃO usar

- Confirmação destrutiva/irreversível — use **Modal**.
- Conteúdo que é a própria tela (não complementar) — use a estrutura da tela (Documento/Index).

## Onde se aplica

Usado nos **anexos do documento**: pré-visualização de um arquivo (ver sem baixar) e, nos **grupos de anexos** (agrupador de um mesmo tipo), o drawer para inserir novos e ver os já importados. Também nos transversais (Carrinho · Mensagens · Genius).

---

