Gabaritos
As telas-base do ME, cada uma com seu prompt rico pronto para copiar — anatomia, componentes e a dica que mais reduz erro.
Um gabarito é uma tela-base do ME: a anatomia (as zonas e a ordem) + os componentes certos + o prompt pronto para gerá-la. Partir de um gabarito é partir do padrão, não da página em branco.
Cada tela-base aqui já vem com esse prompt completo — anatomia, componentes e restrições — pronto para copiar e colar na IA. Os templates montados (telas fiéis) vivem em Padrões › Templates; aqui é o atalho para chegar neles com IA. Para preencher os detalhes da tela, use o Compositor E-PROC. As telas-base trazem o prompt inline; os documentos por tipo, em cards com o prompt no modal. A maioria tem um template fiel em Padrões › Templates — Wizard e Livre não têm template fixo.
Telas
Index (listagem)
Listagem de uma entidade — subheader, filter bar e área de dados (tabela, cards ou lista).
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de index do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Estrutura de Index
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Header · Subheader (título + CTA primário) · Filter bar · Área de dados (tabela | cards | lista de foreheads).
Componentes obrigatórios: Header (block EletroDS), Subheader (block EletroDS — CTA, busca, filtros), barra de filtros: MeFilterBar se existir no projeto, senão componha com Subheader + MeCriterionInput, TableView · CardView · ListView (blocks EletroDS; na view lista cada registro é um MeForehead empilhado), MeButtonBar (ações + “Mais ações”), UBadge (Nuxt UI — status).
Status como UBadge semântico: Pendente/Em análise/Em aprovação/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error.
Layout: {EletroDS (MeLayout)}.
Estrutura: {Header, Toolbar, Left-area, Main}.
Header — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeHeader (ativo=Transações, navItens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"},{"l":"Usuários","i":"users","u":"#"},{"l":"Mais","i":"ellipsis"}], transversais=Mensagens, Genius, Carrinho, menuUsuario=Meu perfil, Idioma, Substituição, Configurações, Novidades e Atualizações, Sair, headerMaisItens=Compras, Fornecedores, Configurações, brandBg=Azul ME (padrão), brandIconColor=Branco (padrão), msgBadge=10, cartBadge=60, userNome=Marina Lopes, sigla=ML, cargo=Compradora)
Header — seção ativa: {Transações}.
Toolbar — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeSubheader (variant=primary, toggleSidebar=true, createActions.label=«Ação principal (campo da tela)», createActions.icon=plus, createActions.items=«Opções do botão split (campo da tela)», buttonBar.actions=«Ações da tela (campo da tela)», search.placeholder=«Filter Search — busca (campo da tela)», toggleChart=«state.viewAtiva === "tabela"», gridMode.icon=«state.viewAtiva === "tabela" ? "table-2" : state.viewAtiva === "lista" ? "list" : state.viewAtiva === "cards" ? "layout-grid" : state.viewAtiva === "preview" ? "panel-right" : "table-2"», gridMode.items=«Views disponíveis (campo da tela)»)
Left-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente Menu lateral do index (composição: busca + tabs-âncora + collapsibles com lista/faceta/árvore/slider) (contexto=Transações, contextoState=contexto)
Main — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UModal (openState=modalColunas, title=Editar colunas, description=Escolha e ordene as colunas exibidas na grid., size=lg) { Componente MeDualList (itens=«Colunas (campo da tela)», leftBoxLabel=Colunas disponíveis, rightBoxLabel=Colunas exibidas, draggable=true) · footer: Componente UButton (label=Cancelar, color=neutral, variant=ghost); Componente UButton (label=Aplicar, color=primary, variant=solid) }; Componente UModal (openState=modalExportar, title=Exportar, description=Escolha o formato e o que será exportado.) { Componente URadioGroup (legend=Formato, itens=Excel (.xlsx), CSV (.csv), PDF (.pdf), orientation=vertical) · Componente UCheckbox (label=Somente os registros selecionados) · footer: Componente UButton (label=Cancelar, color=neutral, variant=ghost); Componente UButton (label=Exportar, color=primary, variant=solid) }; Componente MeTableView (colunas=«Colunas (campo da tela)», selectable=true, acoesLinha=favoritar, mais, acoesLinhaItens=«Ações por linha (campo da tela)», headerBlocos=[{"tipo":"Bloco (grupo)","sty":{"dir":"row","gap":"2","av":"center","wMode":"fill"},"blocos":[{"tipo":"Bloco (grupo)","sty":{"dir":"row","gap":"2","av":"center","wMode":"fill","overflow":"scroll","scrollbar":"hover"},"blocos":[{"tipo":"Componente","comp":"UButton","visivelSe":"state.selCount","cfg":{"label":{"$expr":"state.selCount + \" Selecionados\""},"color":"neutral","variant":"outline","size":"sm","class":"h-8 shrink-0"},"on":{"clique":[{"acao":"toggle","alvo":"selAcoes"}]}},{"tipo":"Componente","comp":"UButton","visivelSe":"state.selCount && state.selAcoes","cfg":{"label":"Salvar seleção","color":"primary","variant":"link","size":"sm","class":"h-8"},"on":{"clique":[{"acao":"set","alvo":"selecaoSalva","valor":true}]}},{"tipo":"Componente","comp":"UButton","visivelSe":"state.selCount && state.selAcoes","cfg":{"label":"Limpar seleção","color":"primary","variant":"link","size":"sm","class":"h-8"},"on":{"clique":[{"acao":"set","alvo":"selecao","valor":{}},{"acao":"set","alvo":"selCount","valor":0},{"acao":"set","alvo":"selAcoes","valor":false}]}},{"tipo":"Componente","comp":"MeFilterBar","visivelSe":"!(state.selCount && state.selAcoes)","cfg":{"campos":"Status, Tipo","class":"min-w-0 flex-1"},"filhos":[{"tipo":"Bloco (grupo)","sty":{"dir":"row","gap":"2","av":"center","wMode":"hug"},"blocos":[{"tipo":"Componente","comp":"UDropdownMenu","cfg":{"align":"start","itens":[{"l":"Todos os processos","acao":"set","alvo":"filtroProcesso","valor":"Todos os processos"},{"l":"Meus processos","acao":"set","alvo":"filtroProcesso","valor":"Meus processos"}]},"filhos":[{"tipo":"Componente","comp":"UButton","cfg":{"label":{"$expr":"state.filtroProcesso || \"Todos os processos\""},"color":"neutral","variant":"outline","size":"sm","trailingIcon":"chevron-down","class":"h-8 shrink-0"}}]},{"tipo":"Componente","comp":"UDropdownMenu","cfg":{"align":"start","itens":[{"l":"Todo período","acao":"set","alvo":"filtroPeriodo","valor":"Todo período"},{"l":"Últimos 15 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 15 dias"},{"l":"Últimos 30 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 30 dias"},{"l":"Últimos 60 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 60 dias"},{"l":"Últimos 90 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 90 dias"}]},"filhos":[{"tipo":"Componente","comp":"UButton","cfg":{"label":{"$expr":"state.filtroPeriodo || \"Todo período\""},"color":"neutral","variant":"outline","size":"sm","trailingIcon":"chevron-down","class":"h-8 shrink-0"}}]}]}]}]},{"tipo":"Componente","comp":"VibeTableMoreMenu","cfg":{"configuracoes":true}}]}], analyticsState=chartOpen); Componente MeCardView (headerBlocos=[{"tipo":"Bloco (grupo)","sty":{"dir":"row","gap":"2","av":"center","wMode":"fill"},"blocos":[{"tipo":"Bloco (grupo)","sty":{"dir":"row","gap":"2","av":"center","wMode":"fill","overflow":"scroll","scrollbar":"hover"},"blocos":[{"tipo":"Componente","comp":"UButton","visivelSe":"state.selCount","cfg":{"label":{"$expr":"state.selCount + \" Selecionados\""},"color":"neutral","variant":"outline","size":"sm","class":"h-8 shrink-0"},"on":{"clique":[{"acao":"toggle","alvo":"selAcoes"}]}},{"tipo":"Componente","comp":"UButton","visivelSe":"state.selCount && state.selAcoes","cfg":{"label":"Salvar seleção","color":"primary","variant":"link","size":"sm","class":"h-8"},"on":{"clique":[{"acao":"set","alvo":"selecaoSalva","valor":true}]}},{"tipo":"Componente","comp":"UButton","visivelSe":"state.selCount && state.selAcoes","cfg":{"label":"Limpar seleção","color":"primary","variant":"link","size":"sm","class":"h-8"},"on":{"clique":[{"acao":"set","alvo":"selecao","valor":{}},{"acao":"set","alvo":"selCount","valor":0},{"acao":"set","alvo":"selAcoes","valor":false}]}},{"tipo":"Componente","comp":"MeFilterBar","visivelSe":"!(state.selCount && state.selAcoes)","cfg":{"campos":"Status, Tipo","class":"min-w-0 flex-1"},"filhos":[{"tipo":"Bloco (grupo)","sty":{"dir":"row","gap":"2","av":"center","wMode":"hug"},"blocos":[{"tipo":"Componente","comp":"UDropdownMenu","cfg":{"align":"start","itens":[{"l":"Todos os processos","acao":"set","alvo":"filtroProcesso","valor":"Todos os processos"},{"l":"Meus processos","acao":"set","alvo":"filtroProcesso","valor":"Meus processos"}]},"filhos":[{"tipo":"Componente","comp":"UButton","cfg":{"label":{"$expr":"state.filtroProcesso || \"Todos os processos\""},"color":"neutral","variant":"outline","size":"sm","trailingIcon":"chevron-down","class":"h-8 shrink-0"}}]},{"tipo":"Componente","comp":"UDropdownMenu","cfg":{"align":"start","itens":[{"l":"Todo período","acao":"set","alvo":"filtroPeriodo","valor":"Todo período"},{"l":"Últimos 15 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 15 dias"},{"l":"Últimos 30 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 30 dias"},{"l":"Últimos 60 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 60 dias"},{"l":"Últimos 90 dias","acao":"set","alvo":"filtroPeriodo","valor":"Últimos 90 dias"}]},"filhos":[{"tipo":"Componente","comp":"UButton","cfg":{"label":{"$expr":"state.filtroPeriodo || \"Todo período\""},"color":"neutral","variant":"outline","size":"sm","trailingIcon":"chevron-down","class":"h-8 shrink-0"}}]}]}]}]},{"tipo":"Componente","comp":"VibeTableMoreMenu","cfg":{"configuracoes":true}}]}]); Grupo (visível quando: state.viewAtiva === "lista") { Grupo { Grupo { Grupo { Componente UCheckbox (class=w-9 shrink-0 justify-center) · Componente UButton (label=«state.selCount + " Selecionados"», color=neutral, variant=outline, size=sm, class=h-8 shrink-0) · Componente UButton (label=Salvar seleção, color=primary, variant=link, size=sm, class=h-8) · Componente UButton (label=Limpar seleção, color=primary, variant=link, size=sm, class=h-8) · Componente MeFilterBar (campos=Status, Tipo, class=min-w-0 flex-1) { Grupo { Componente UDropdownMenu (align=start, itens=Todos os processos · Meus processos) { Componente UButton (label=«state.filtroProcesso || "Todos os processos"», color=neutral, variant=outline, size=sm, trailingIcon=chevron-down, class=h-8 shrink-0) } · Componente UDropdownMenu (align=start, itens=Todo período · Últimos 15 dias · Últimos 30 dias · Últimos 60 dias · Últimos 90 dias) { Componente UButton (label=«state.filtroPeriodo || "Todo período"», color=neutral, variant=outline, size=sm, trailingIcon=chevron-down, class=h-8 shrink-0) } } } } } } · Divisor (solid) · Componente MeListView }; Grupo (visível quando: state.viewAtiva === "preview") { Grupo { Grupo { Grupo { Componente UCheckbox (class=w-9 shrink-0 justify-center) · Componente UButton (label=«state.selCount + " Selecionados"», color=neutral, variant=outline, size=sm, class=h-8 shrink-0) · Componente UButton (label=Salvar seleção, color=primary, variant=link, size=sm, class=h-8) · Componente UButton (label=Limpar seleção, color=primary, variant=link, size=sm, class=h-8) · Componente MeFilterBar (campos=Status, Tipo, class=min-w-0 flex-1) { Grupo { Componente UDropdownMenu (align=start, itens=Todos os processos · Meus processos) { Componente UButton (label=«state.filtroProcesso || "Todos os processos"», color=neutral, variant=outline, size=sm, trailingIcon=chevron-down, class=h-8 shrink-0) } · Componente UDropdownMenu (align=start, itens=Todo período · Últimos 15 dias · Últimos 30 dias · Últimos 60 dias · Últimos 90 dias) { Componente UButton (label=«state.filtroPeriodo || "Todo período"», color=neutral, variant=outline, size=sm, trailingIcon=chevron-down, class=h-8 shrink-0) } } } } } } · Divisor (solid) · Componente MePreview }
Right-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente Painel transversal (Mensagens · Genius · Carrinho) na right-area/drawer
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeNavBar (itens=[{"l":"Dashboard","i":"layout-dashboard"},{"l":"Transações","i":"file-input"},{"l":"Fornecedores","i":"store"},{"l":"Catálogos","i":"shopping-bag"}], sitemap=true)
Ação principal: {Novo {entidade}}.
Ações da tela: {ação1, ação2}.
Ações "em massa" aplicam-se aos itens selecionados (somem/desabilitam sem seleção); "abre modal" confirma num modal/painel antes de executar; as demais rodam inline com toast (destrutivas sempre confirmam). As que não couberem no subheader colapsam em "Mais ações".
Sidebar — seções: {Favoritos, Filtros salvos}.
Cada seção da sidebar declara seu tipo de exibição (Lista/Checkbox-faceta/Seleção múltipla/Seleção única/Árvore/Card/Slider) — respeite-o ao montar (ex.: faceta = checkbox com contagem; slider = faixa de dois thumbs).
Use exatamente os itens listados em cada seção da sidebar — não misture itens/facetas de outra entidade (ex.: não traga facetas de Fornecedores num index de Transações).
Sidebar — switcher de contexto (TROCA os filtros): {Meus X ↔ Y}.
Filtros rápidos (select): {Processo, Período}.
Filtros: {filtro1, filtro2}.
Filter Search — busca por: {número, título}.
Views disponíveis: {tabela, cards, lista}.
View padrão: {tabela | cards | lista}.
Colunas: {col1, col2, status, valor}.
Ações por linha: {editar, excluir}.
⛔ REPRODUZA O PADRÃO EXATO (não reinterprete) — evite estes desvios recorrentes: (1) Subheader: ações em ghost (NÃO outline), CTA primário à ESQUERDA, SEM botão "Opções", COM botão de gráficos (ícone chart-column, modo tabela); (2) UMA filter bar, SEM checkbox líder no modo tabela (só lista/card), NÃO duplicada; (3) Sidebar: campo de busca no topo + tabs-âncora + seções AGRUPADAS (nunca itens soltos) — tamanhos normais (não encolha itens/tree); (4) SEM padding externo na área de dados (tabela/lista/card/preview ocupam a área inteira); (5) Lista = só checkbox / Preview = avatar; (6) Mensagens·Genius·Carrinho ABREM painel à direita (#right-area/drawer); (7) Mobile: MESMA estrutura do desk, com FAB, nav bar com "Mais", e subheader SEM busca/hambúrguer (foram pro header/FAB); (8) fundo BRANCO (bg-default) nas zonas; scrollbar fina padrão ME. Se algum aparecer, você reinterpretou — corrija antes de entregar.
Afordâncias de index: ao clicar numa linha/card, abre o documento em página inteira — o identificador (1ª coluna) é o LINK principal; colunas ordenáveis (chevron no cabeçalho); realce da linha selecionada; paginação com seletor de itens por página no rodapé da área de dados.
Busca e filtros: a Filter Search abre por um ícone de funil (overlay com drill-down Critério › Operador › Valor); a Filter Bar rola horizontalmente por baixo do cluster de ações fixo à direita.
Sidebar de navegação agrupada (ex.: Pendências · Itens · Transações · Filtros salvos · Meus links), com contagens por grupo — distinta das facetas (Segmento/Localização) de Fornecedores/Catálogo.
Faceta de tipo na sidebar (grupo Transações: Requisições/Cotações/Pedidos/Contratos/Nota Fiscal): selecioná-la filtra a lista para só aquele tipo (o número reflete o prefixo — REQ/COT/PED…).
Faixa de widgets/gráficos (view "Meus widgets"): grade no desktop; no mobile empilha em 1 coluna full-width e a tela rola até a tabela (área de dados com altura mínima).
App bar: ao lado do "Mais" ficam os transversais Mensagens · Genius · Carrinho — o Carrinho é item rotulado e um divisor separa "Mais" dos transversais; o subheader inclui a ação "Enviar para o Genius".
Sidebar, Filter Bar e paginação NÃO existem prontas no EletroDS — componha-as (regra EDS-first → Nuxt UI → compor); use os blocks reais (MeTableView/MeFilterBar) onde existirem.
A sidebar fica sempre VISÍVEL quando a zona está ligada — NÃO use v-show/condicional sobre o slot dela (isso reserva uma coluna vazia que espreme a tabela); se precisar recolher, use o colapso nativo do rail (ícone), não escondendo o slot.
View "preview" (master-detail): lista à esquerda + painel de detalhe à direita; o subheader do detalhe traz, ao lado de "Opções", um ícone "abrir em outra janela" (afordância para a página única do documento). Sem seleção, o painel mostra um empty state ("Abrir documento" / "Perguntar ao Genius").
Tabela configurável (persiste por conta): densidade das linhas Compacto 40px · Regular 48px (padrão) · Espaçoso 64px (a célula do cabeçalho é SEMPRE 40px); "linhas por registro" 1/2/3 truncam (line-clamp) e "Ajustar ao texto" cresce sem truncar; "itens por tela" 10/20/50/100 (só na tabela — lista/card usam scroll infinito). Rodapé "X–Y de Z registros" (PT-BR) + paginação, 56px; listagens com menos de 10 registros NÃO exibem rodapé.
Cabeçalho de coluna = botão (ícone de ordenação à esquerda, sem chevron) e arrastável para reordenar; clicar abre menu: Ordenar A→Z/Z→A · Fixar/Desafixar coluna · Ocultar coluna · [só em coluna agregável] Criar gráfico / Criar métrica. FIXAR = REORDENAR (a coluna vai para o início, logo após o checkbox, agrupada às demais fixadas) — NÃO é sticky-on-scroll nem o column-pinning nativo do UTable. Checkbox é sempre a 1ª coluna.
"Mais ações" (⋮) da filter bar SÓ na tabela: Exportar · Configurações da tabela (Editar colunas = modal transfer-list MeDualList inativas↔ativas com busca/mover/arrastar-para-ordenar + Restaurar padrão) · Densidade · Linhas por registro · Paginação · Itens por tela.
Filter Bar (peça custom, ainda não é block do EDS): altura 48px; esquerda→direita = checkbox líder (lista/card) · chip "N selecionados" (toggle: desabilita os filtros e expõe Salvar lista / Limpar seleção) · filtros de contexto (escopo/período, radios cor primary) · critérios MeCriterionInput (campo·operador·valor, removíveis, rolam no wheel) · grupo [+][salvar (só com dirty)][limpar (danger)] · ⋮. No mobile colapsa num funil (bottom-sheet) com ponto vermelho quando há filtro ativo.
Widgets/gráficos: nascem da agregação de uma coluna (menu do cabeçalho) ou do Dashboard; faixa "Meus widgets" colapsável no topo do conteúdo (só no modo Tabela), com contagem + Restaurar padrão + Limpar todos; grade auto-ajustável de ~4 por linha; ao abrir, a tabela vira "hug" (mostra a página, sem scroll interno) e o CORPO INTEIRO rola junto (widgets + tabela + footer). Cores por série chart-1…chart-10 (Blue/Orange/Teal/Pink/Yellow/Purple/Red/Cyan/Lime/Slate 600) — NUNCA as cores semânticas de status.
Abrir/fechar a faixa de widgets é do BOTÃO de gráficos: um clique abre (botão fica pressed), outro fecha — mesmo havendo widgets na tela. Ter widget só define a abertura INICIAL (tela que nasce com gráficos abre aberta; gerar gráfico/métrica pelo cabeçalho da coluna também abre). O PONTO no botão aparece SÓ quando existe widget nesta tabela.
Sidebar (peça custom): moldura fixa na ordem busca → tabs 1 (pill = switcher de contexto, quando houver) → tabs 2 (link = âncora das seções) → collapsibles. Tipos de item: link/ativo (azul) · árvore/pasta (contagem) · faceta-checkbox (count) · radio de período (+ date) · slider de métrica (USlider range) · switcher (troca universo E filtros) · box especial (endereço "Destino de compra" = 1º collapsible do Catálogo; banner promo acima da busca) · Favoritos (estrela sólida amarela) · "Ver mais".
Mobile: app bar vira BRANCO (bg-default) com logo ME azul — hambúrguer→drawer da sidebar (w-80), busca→painel, transversais→drawer à direita, avatar→drawer inferior; CTA primário vira FAB acima da nav bar (drawer inferior "Novo documento"); nav bar inferior AZUL com as funções + "Mais" (drawer). Alturas: header 64px · subheader 56px · nav bar 56px. No Preview mobile, tocar num registro abre o documento em TELA CHEIA.
LAYOUT (block MeLayout — preencha só os slots usados)
- #header → Header = app bar do ME: barra AZUL full-width (cor primária = me-brand; NÃO o verde default do Nuxt UI) com a marca "me." em branco à esquerda, navegação horizontal no topo, e à direita os transversais (Mensagens, Genius, Carrinho) + avatar. NÃO renderize header neutro/claro nem mova a marca para uma sidebar.
- #toolbar → Subheader (MeSubheader): a ação primária (botão split azul) fica à ESQUERDA; em seguida até 3 ações da tabela + "Mais ações" (overflow). À direita: Filter Search (busca) + toggle de gráficos + troca de visão (tabela/cards/lista).
- #left-area → sidebar de navegação/filtros (Pendências/Itens/Filtros salvos). Quando há switcher de contexto (ex.: Meus fornecedores ↔ Fornecedores ME), ele TROCA os filtros/facetas da sidebar — facetas: checkbox com contagem, árvore País › Estado › Cidade e "Ver mais".
- #analytics → área de gráficos — visível só pelos gatilhos (toggle da toolbar OU gráfico no header de uma coluna) e com botão de fechar.
- #default → área de dados (tabela | cards | lista) com a Filter Bar no HEADER da grid: filtros rápidos + critérios campo · operador · valor (MeFilterBar/MeCriterionInput — peças encostadas, removíveis), NÃO Selects soltos. Tipo = TEXTO; só Status é badge semântico. Seleção em massa = badge "N selecionados" na Filter Bar (toggle que filtra os selecionados e desabilita os filtros aplicados), NÃO o rodapé padrão "N de M linha(s) selecionada(s)".
- #right-area → painel dos transversais (Mensagens · Genius · Carrinho) — abre pelo ícone do header e fecha quando nenhum está ativo.
- #footer → nav bar inferior (MeNavBar) — só no mobile/tablet.
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Status sempre como badge semântico.
Ações por linha no menu de mais ações.
Seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto ativa).
CTA primário "Novo X" (cadastro de entidade) vs "Adicionar X" (item existente em lista).
Switcher de contexto na sidebar (quando houver) TROCA o conjunto de filtros/facetas — não é um filtro adicional..
PRONTO QUANDO
- A seleção de linhas habilita/desabilita as ações em lote (sem seleção = desabilitadas).
- A área de gráficos só aparece pelos gatilhos (toggle da toolbar ou gráfico no header de coluna) e tem como fechar.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Defina o CTA, as colunas, os filtros e a view padrão — é o que mais muda a saída.
Documento
Visualização de um registro — Forehead, abas e corpo, com ações que dependem do status.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de documento do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Estrutura de Documento
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Header · Subheader (ações por status + Opções) · Nav-area (rail de fases, se processo) · Left-area (opcional) · Alertas · Forehead (badge + leading + building blocks + Ver mais) · Cards informativos · Abas de ancoragem + corpo da aba ativa · Otimização (visão de cenários, na cotação) · Right-area (transversais) · Footer (nav bar mobile).
Componentes obrigatórios: Header (block EletroDS), Subheader (block EletroDS — ações por status + Opções), Phases (rail de fases, se processo), MeForehead + MeForeheadBadge (EletroDS), MeButtonBar (ações + “Mais ações”), UTabs (Nuxt UI — abas de ancoragem), UCollapsible (seções), UBadge (Nuxt UI — status).
Status como UBadge semântico: Pendente/Em análise/Em aprovação/Aguardando=warning · Em andamento=info · Aprovado/Encerrado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error.
Estrutura: {Header, Subheader, Forehead, Conteúdo}.
Tipo de documento: {simples | processo}.
Header — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeHeader (ativo=Transações, navItens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"},{"l":"Usuários","i":"users","u":"#"},{"l":"Mais","i":"ellipsis"}], transversais=Mensagens, Genius, Carrinho, menuUsuario=Meu perfil, Idioma, Substituição, Configurações, Novidades e Atualizações, Sair, headerMaisItens=Compras, Fornecedores, Configurações, brandBg=Azul ME (padrão), brandIconColor=Branco (padrão), msgBadge=10, cartBadge=60, userNome=Marina Lopes, sigla=ML, cargo=Compradora)
Header — seção ativa: {Transações}.
Header — menus: {Dashboard, Transações}.
Header — transversais: {Mensagens, Genius, Carrinho}.
Header — menu do usuário: {Trocar conta, Idioma…}.
Toolbar — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeSubheader (variant=primary, class=h-full w-full, buttonBar.variant=ghost, buttonBar.color=primary, buttonBar.size=md, buttonBar.maxVisibleActions=«maxAcoes (campo da tela)», buttonBar.actions=«acoesDoc (campo da tela)») { right: Componente UTabs (itens=Documento, Mapa, Otimização, tabState=docView, color=neutral, variant=pill, size=md, class=shrink-0); Componente UDropdownMenu (align=end, itens=Documento · Mapa · Otimização) { Componente UButton (icon=«state.docView === 1 ? "map" : state.docView === 2 ? "line-chart" : "file-text"», trailingIcon=chevron-down, color=neutral, variant=ghost, size=md, ariaLabel=Trocar de visão) }; Componente UDropdownMenu (align=end, itens=«opcoesDoc (campo da tela)», ui={"label":"text-xs font-medium text-muted","itemLabel":"text-sm text-highlighted"}) { Componente UButton (label=Opções, icon=settings-2, trailingIcon=chevron-down, color=primary, variant=ghost, size=md) } }
Ações por status: {aprovar, editar, cancelar}.
Ações "em massa" aplicam-se aos itens selecionados (somem/desabilitam sem seleção); "abre modal" confirma num modal/painel antes de executar; as demais rodam inline com toast (destrutivas sempre confirmam). As que não couberem no subheader colapsam em "Mais ações".
Menu "Opções" (config da tela): {Configurações da tela, Exportar}.
Nav-area — tipo: {Fases}.
Nav-area — itens: {RFQ [itens: Rodada 1 | Rodada 2], RFP}.
Otimização — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Cabeçalho da visão: título "Otimização avançada" + linha de apoio + o documento em foco (sigla + código, que acompanha o rail)
• Área 2: Componente UCard (class=flex-1, ui={"root":"rounded-xl ring-0 border border-default","body":"p-4 sm:p-4"}) { KPI "Saving equalizado" (ícone + rótulo + info; valor em destaque) }; Componente UCard (class=flex-1, ui={"root":"rounded-xl ring-0 border border-default","body":"p-4 sm:p-4"}) { KPI "TCO do cenário" (ícone + rótulo + info; valor em destaque) }; Componente UCard (class=flex-1, ui={"root":"rounded-xl ring-0 border border-default","body":"p-4 sm:p-4"}) { KPI "TCO total da cotação" (ícone + rótulo + info; valor em destaque) }
• Área 3: Componente UCard (class=flex-1, ui={"root":"rounded-xl ring-0 border border-default","body":"p-4 sm:p-4"}) { Decomposição "Decomposição do custo por fornecedor": barras horizontais com o valor dentro da barra, eixo de referência embaixo e legenda à direita (uma cor por série) }; Componente UCard (class=flex-1, ui={"root":"rounded-xl ring-0 border border-default","body":"p-4 sm:p-4"}) { Decomposição "Decomposição de itens por fornecedor": barras horizontais com o valor dentro da barra, eixo de referência embaixo e legenda à direita (uma cor por série) }; Componente UCard (class=flex-1, ui={"root":"rounded-xl ring-0 border border-default","body":"p-4 sm:p-4"}) { Decomposição "Decomposição do TCO do cenário": barras horizontais com o valor dentro da barra, eixo de referência embaixo e legenda à direita (uma cor por série) }
• Área 4: Componente USelect (placeholder=Unidades organizacionais, itens=Todos, trailingIcon=chevron-down, size=md, class=w-auto); Componente USelect (placeholder=Regional, itens=Todos, trailingIcon=chevron-down, size=md, class=w-auto); Componente USelect (placeholder=Tipo de frete, itens=Todos, trailingIcon=chevron-down, size=md, class=w-auto)
• Área 5: Lista de CENÁRIOS: card por cenário com resumo em colunas (nome/data, TCO, tipo de decisão em badge, itens alocados com barra + %, vencedores, critérios utilizados), split "Finalizar cotação", ⋮ e chevron que expande a tabela por fornecedor (busca + ⋮ + 14 colunas + paginação). No pé do card, três collapsibles lado a lado: Estratégia · Análise · Critérios utilizados.
Forehead — visão: {Default | Expandida + simplificada | Com fundo}.
Forehead — badge: {Texto | Imagem | Ícone}.
Forehead — leading content: {Título, Nome, Telefone, E-mail}.
Forehead — building blocks: {Status, Valor total, Prazo}.
Status possíveis: {rascunho, em análise, aprovado}.
Alertas: {Aviso: vence em 30 dias}.
Cards informativos: {Entrega, Faturamento}.
Conteúdo (seções) (cada seção é uma lista de BLOCOS): {Informações gerais, Históricos, Itens}.
Cada seção do corpo é montada por BLOCOS empilhados (Descrição, Formulário, Tabela/Cards/Lista, Widgets, Mapa, Anexos, Resumo, Timeline, Collapse). Reproduza os blocos na ordem indicada; Collapse agrupa sub-blocos; tabelas podem ter linhas expansíveis (detalhe = blocos internos).
Left-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UNavigationMenu (tipoLeft=Sidebar de seções, titulo=Navegação, itens=[{"l":"Dados gerais","i":"clipboard-list"},{"l":"Seções","i":"layers"},{"l":"Anexos","i":"paperclip"},{"l":"Histórico","i":"history"}])
Right-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente Painel transversal (Mensagens · Genius · Carrinho) na right-area/drawer
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeNavBar (itens=[{"l":"Dashboard","i":"layout-dashboard"},{"l":"Transações","i":"file-input"},{"l":"Fornecedores","i":"store"},{"l":"Catálogos","i":"shopping-bag"}], ativo=Dashboard, sitemap=true)
Se você tem o bundle E-PROC instalado, NÃO reconstrua esta tela da descrição: copie o kit `references/documento-reference/` (código real do documento — cotação com os seis documentos, visão Otimização, as 13 modais, rail de fases e o responsivo) e troque só os DADOS (preset do tipo + campos). Reconstruir da prosa perde medidas, dados de exemplo, estados e o mobile. Sem o bundle, siga a anatomia abaixo à risca.
Responsivo (mobile/tablet, < lg): Forehead Empilha em coluna; a ação primária fica visível e as demais colapsam em "Mais ações". · Abas: Abas viram scroll horizontal (ou menu); a primeira seção continua sendo o padrão ao abrir. · Corpo: Uma coluna; tabelas de itens viram cards/lista para caber. · Processo: O rail de Fases vira drawer (w-64) com lista PLANA; a moldura é sempre modal-sheet.
Moldura modal × página única: no MODAL (aberto por um item da index) o topo tem chrome — breadcrumb + "abrir em outra janela" + fechar (X); a PÁGINA única (rota própria) NÃO tem esse chrome (navega pelo header/sidebar). O breadcrumb + abrir-em-janela + X é EXCLUSIVO do modal.
Ações por status = máquina de estados (status → ações válidas), NÃO uma toolbar fixa: a ação primária e o status badge ficam sincronizados; onde não há primária, o estado é só leitura; a ação destrutiva sempre confirma em modal.
Button bar no HEADER DA TABELA (ações da grid: "Adicionar ao carrinho", "Adicionar à lista", "Baixar selecionados"…): UButton color primary, variant OUTLINE, size sm — nunca ghost (ghost é do subheader da tela). Em grid com seleção, essas ações ficam DESABILITADAS enquanto nenhuma linha está marcada e habilitam com uma ou mais.
Célula/valor sem dado NUNCA fica em branco: escreva "Sem dados" em text-dimmed (em branco lê como carregando ou quebrado). Vale para tabelas, grids de campos e todas as visões.
As modais e drawers do documento sobem numa CAMADA ACIMA do app bar azul (o header do ME tem z alto): modal abrindo atrás da barra é defeito. Toda modal precisa de gatilho e todo item de menu precisa abrir a sua modal — nenhuma ação sem destino, nenhuma modal órfã.
LAYOUT (block MeLayout — preencha só os slots usados)
- #header → Header = app bar do ME: barra AZUL full-width (cor primária = me-brand; NÃO o verde default do Nuxt UI) com a marca "me." em branco à esquerda, navegação horizontal no topo (menus), e à direita os transversais + avatar. NÃO renderize header neutro/claro nem mova a marca para uma sidebar.
- #nav-area → Rail lateral (só documento de PROCESSO): lista o tipo de dado (Fases/Rodadas/Etapas) e seus itens; é atalho de etapa, não o menu de áreas. Só aparece na visão Documento (em Mapa/Otimização fica oculto) e no mobile/tablet vira drawer com lista plana.
- #toolbar → Subheader: à esquerda as ações por status + "Mais ações" (quantas ficam visíveis depende do tipo: 3 por padrão, 2 na cotação e no leilão, 4 na ficha de fornecedor; a primária muda com o status e a destrutiva é isolada/modal); à direita o menu "Opções" (config da tela). Na visão Otimização a barra é de cenário (3 ações).
- #default → Forehead (badge text/image/icon + leading content + building blocks como Status/Valor/Prazo + opcional "Ver mais" que expande um slot; com ou sem banda de fundo) + abas de ancoragem + corpo da aba ativa (cada aba com o conteúdo definido).
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Status sempre como badge semântico.
As ações primárias dependem do status.
Ação destrutiva passa por modal de confirmação.
Forehead: badge (text/image/icon) + leading content + building blocks + (opcional) botão "Ver mais" que expande um slot.
Abas de ancoragem (scroll-spy) sobre seções empilhadas — não trocam de página.
PRONTO QUANDO
- As ações primárias mudam conforme o status do documento.
- Ação destrutiva passa por modal de confirmação.
- Abas são de ancoragem — rolam para a seção, não trocam de página.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Diga se é documento simples ou de processo, liste os status e a ação de cada um — o Forehead organiza identidade + status.
Dashboard
Tela de síntese — faixa de filtros globais, linha de KPIs e grid de widgets/gráficos.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de dashboard do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Dashboard
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Faixa de filtros globais · Linha de KPIs (KpiCard) · Grid de 12 colunas com widgets/gráficos.
Componentes obrigatórios: Layout (block EletroDS — shell), KpiCard (block EletroDS — KPIs: rótulo + número + variação ↑↓; NÃO CardView, que é card de produto), Subheader (block EletroDS — filtros globais), Charts (lib de chart do EDS; séries com a paleta chart-1..10).
Layout: {EletroDS (MeLayout)}.
Estrutura: {Header, Toolbar, Main, Right-area, Footer}.
Header — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeHeader (ativo=Transações, navItens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"},{"l":"Usuários","i":"users","u":"#"},{"l":"Mais","i":"ellipsis"}], transversais=Mensagens, Genius, Carrinho, menuUsuario=Meu perfil, Idioma, Substituição, Configurações, Novidades e Atualizações, Sair, headerMaisItens=Compras, Fornecedores, Configurações, brandBg=Azul ME (padrão), brandIconColor=Branco (padrão), msgBadge=10, cartBadge=60, userNome=Marina Lopes, sigla=ML, cargo=Compradora)
Painéis: {Painel de compras, Compras, SLA}.
Menu ⋮ da página: {Restaurar padrão, Meus Links}.
Toolbar — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Grupo { Componente UTabs (paineis=Painel de compras, Compras, SLA, itens=«tabsPaineis (campo da tela)», tabState=painelAtivo, variant=link, color=primary, size=lg, class=w-fit shrink-0 h-14, ui={"list":"justify-start gap-4 border-b-0 overflow-visible h-14 items-center","trigger":"group/aba h-full gap-1 border-b-2 border-transparent rounded-none overflow-visible data-[state=active]:border-primary","label":"text-base font-medium h-full flex items-center","indicator":"hidden"}) { Componente UButton (icon=square-pen, square=true, variant=ghost, size=xs, color=«item && item.value === state.painelAtivo ? "primary" : "neutral"», class=hidden group-hover/aba:inline-flex) · Componente UDropdownMenu (align=start, itens=Duplicar · Renomear · Ocultar) { Componente UButton (icon=ellipsis-vertical, square=true, variant=ghost, size=xs, color=«item && item.value === state.painelAtivo ? "primary" : "neutral"», class=hidden group-hover/aba:inline-flex data-[state=open]:inline-flex) } · Componente UDropdownMenu (align=start, itens=Compartilhar · Duplicar · Renomear · Ocultar · Remover) { Componente UButton (icon=ellipsis-vertical, square=true, variant=ghost, size=xs, color=«item && item.value === state.painelAtivo ? "primary" : "neutral"», class=hidden group-hover/aba:inline-flex data-[state=open]:inline-flex) } · label: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span v-if="state.renomeando !== item.value" class="flex h-full items-center">{{ item.label }}</span>
<span v-else class="flex h-full items-center" @click.stop>
<UInput v-model="state.novoNome" size="sm" autofocus class="w-52" :ui="{ base: 'ring-inset focus-visible:ring-inset' }" @keydown.enter="state.tabsPaineis = state.tabsPaineis.map((n, i) => i === state.renomeando ? state.novoNome : n); state.renomeando = -1" @keydown.esc="state.renomeando = -1">
<template #trailing>
<UButton icon="i-lucide-save" color="primary" variant="ghost" size="xs" square aria-label="Salvar" @click="state.tabsPaineis = state.tabsPaineis.map((n, i) => i === state.renomeando ? state.novoNome : n); state.renomeando = -1" />
<UButton icon="i-lucide-x" color="neutral" variant="ghost" size="xs" square aria-label="Cancelar" @click="state.renomeando = -1" />
</template>
</UInput>
</span>
``` } · Componente UButton (icon=plus, square=true, color=neutral, variant=ghost, size=md, class=ml-2 shrink-0) }; Grupo { Componente UDropdownMenu (align=end, itens=Restaurar padrão · «"Meus Links (" + (state.qtdLinks ?? 0) + ")"» · «"Filtros salvos (" + (state.qtdFiltros ?? 0) + ")"» · «"Painéis (" + (state.qtdPaineis ?? 0) + ")"») { Componente UButton (icon=ellipsis-vertical, square=true, color=neutral, variant=ghost, size=md) } }
Main — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Grupo (visível quando: state.painelAtivo === 0) { Grupo { Chip de filtro "Meus Processos": botão outline (rounded-sm) que abre menu com as opções Todos Processos · Meus Processos; cada item traz um RADIO marcando a opção ativa. · Chip de filtro "Criado em: Todo período": botão outline (rounded-sm) que abre menu com as opções Últimos 15 dias · Últimos 30 dias · Últimos 60 dias · Últimos 90 dias · Últimos 12 meses · Todo período · Período específico; cada item traz um RADIO marcando a opção ativa, e "Período específico" revela uma célula com o calendário (MeInputDate range). · Componente MeFilterBar (campos=Processo, Status, Criado em, class=min-w-0 flex-1, salvarAlvo=modalSalvarFiltro) } · Componente UPageGrid (class=vibe-dash-grid grid-cols-12 sm:grid-cols-12 lg:grid-cols-12 gap-4) { Componente UCard (class=relative col-span-12 md:col-span-4 group/card flex flex-col @container bg-primary/5, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Bloco promo: texto de apoio + botão SPLIT "Nova transação" (primário) cujo chevron abre os tipos de processo (Requisição/Cotação com subitens, Contrato, Pedido, Nota fiscal, Leilão). · header: Grupo { Título do card "Crie novos processos" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Pendência de compra": 3 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Pendência de compra" + ícone de informação com tooltip (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-2 group/card flex flex-col @container group transition-colors hover:border-primary/30 hover:bg-primary/5, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Card de Mensagens: ícone + título + link "acessar"; é o único card com hover no card inteiro (borda e fundo azul claro). · header: Grupo { Título do card "" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Pendência de aprovação": 2 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Pendência de aprovação" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Backlog de compras": 3 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Backlog de compras" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-4 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Lista "Cotações": linhas rótulo → valor (valor em destaque azul), linha inteira clicável com hover azul claro; texto trunca e a lista rola dentro do card. · header: Grupo { Título do card "Cotações" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-4 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Lista "Contratos": linhas rótulo → valor (valor em destaque azul), linha inteira clicável com hover azul claro; texto trunca e a lista rola dentro do card. · header: Grupo { Título do card "Contratos" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-4 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Lista "Pedidos": linhas rótulo → valor (valor em destaque azul), linha inteira clicável com hover azul claro; texto trunca e a lista rola dentro do card. · header: Grupo { Título do card "Pedidos" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-4 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Lista "Nota fiscal": linhas rótulo → valor (valor em destaque azul), linha inteira clicável com hover azul claro; texto trunca e a lista rola dentro do card. · header: Grupo { Título do card "Nota fiscal" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-4 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { Lista "Recebimento": linhas rótulo → valor (valor em destaque azul), linha inteira clicável com hover azul claro; texto trunca e a lista rola dentro do card. · header: Grupo { Título do card "Recebimento" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 sm:p-4"}) { Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). · Gráfico de area "Status de contratos" (lib de chart do EDS; séries na paleta chart-1..10): cabeçalho com breadcrumb/título + toolbar de Zoom In · Zoom Out · Selection Zoom · Panning · Reset; hover destaca o ponto e abre tooltip com rótulo e valor. Ocupa a altura do card (mín. 16rem); em card estreito a toolbar colapsa num menu único. } } · Empty state do painel (quando não há widgets): ilustração do EDS + "Seu painel está em branco" + "Copie widgets das index ou de outros painéis para começar a personalizar." }; Grupo (visível quando: state.painelAtivo === 1) { Grupo { Chip de filtro "Meus Processos": botão outline (rounded-sm) que abre menu com as opções Todos Processos · Meus Processos; cada item traz um RADIO marcando a opção ativa. · Chip de filtro "Criado em: Todo período": botão outline (rounded-sm) que abre menu com as opções Últimos 15 dias · Últimos 30 dias · Últimos 60 dias · Últimos 90 dias · Últimos 12 meses · Todo período · Período específico; cada item traz um RADIO marcando a opção ativa, e "Período específico" revela uma célula com o calendário (MeInputDate range). · Componente MeFilterBar (campos=Processo, Status, Criado em, class=min-w-0 flex-1, salvarAlvo=modalSalvarFiltro) } · Componente UPageGrid (class=vibe-dash-grid grid-cols-12 sm:grid-cols-12 lg:grid-cols-12 gap-4) { Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Requisições": 3 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Requisições" + ícone de informação com tooltip (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Cotações": 2 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Cotações" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Pedidos": 3 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Pedidos" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 sm:p-4"}) { Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). · Gráfico de barras "Pedidos por status" (lib de chart do EDS; séries na paleta chart-1..10): cabeçalho com breadcrumb/título + toolbar de Zoom In · Zoom Out · Selection Zoom · Panning · Reset; hover destaca o ponto e abre tooltip com rótulo e valor. Ocupa a altura do card (mín. 14rem); em card estreito a toolbar colapsa num menu único. } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 sm:p-4"}) { Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). · Gráfico de rosca "Cotações por situação" (lib de chart do EDS; séries na paleta chart-1..10): cabeçalho com breadcrumb/título + toolbar de Zoom In · Zoom Out · Selection Zoom · Panning · Reset; hover destaca o ponto e abre tooltip com rótulo e valor. Ocupa a altura do card (mín. 14rem); em card estreito a toolbar colapsa num menu único. } } · Empty state do painel (quando não há widgets): ilustração do EDS + "Seu painel está em branco" + "Copie widgets das index ou de outros painéis para começar a personalizar." }; Grupo (visível quando: state.painelAtivo === 2) { Grupo { Chip de filtro "Meus Processos": botão outline (rounded-sm) que abre menu com as opções Todos Processos · Meus Processos; cada item traz um RADIO marcando a opção ativa. · Chip de filtro "Criado em: Todo período": botão outline (rounded-sm) que abre menu com as opções Últimos 15 dias · Últimos 30 dias · Últimos 60 dias · Últimos 90 dias · Últimos 12 meses · Todo período · Período específico; cada item traz um RADIO marcando a opção ativa, e "Período específico" revela uma célula com o calendário (MeInputDate range). · Componente MeFilterBar (campos=Processo, Status, Criado em, class=min-w-0 flex-1, salvarAlvo=modalSalvarFiltro) } · Componente UPageGrid (class=vibe-dash-grid grid-cols-12 sm:grid-cols-12 lg:grid-cols-12 gap-4) { Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Prazos": 3 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Prazos" + ícone de informação com tooltip (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Atendimentos": 2 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Atendimentos" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 pt-0 sm:p-4 sm:pt-0"}) { KPIs "Cumprimento de SLA": 3 tiles (chip de ícone + número + rótulo), cada um com borda inferior e hover no tom do estado (warning/error/info/neutral). A grade dos tiles é fluida: card estreito reduz colunas em vez de espremer. · header: Grupo { Título do card "Cumprimento de SLA" (trunca quando não cabe) · Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). } } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 sm:p-4"}) { Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). · Gráfico de linha "Tendência de atendimentos" (lib de chart do EDS; séries na paleta chart-1..10): cabeçalho com breadcrumb/título + toolbar de Zoom In · Zoom Out · Selection Zoom · Panning · Reset; hover destaca o ponto e abre tooltip com rótulo e valor. Ocupa a altura do card (mín. 14rem); em card estreito a toolbar colapsa num menu único. } · Componente UCard (class=relative col-span-12 md:col-span-6 group/card flex flex-col @container, ui={"root":"rounded-xl ring-0 border border-default divide-y-0 overflow-hidden","header":"shrink-0 p-4 pb-2 sm:px-4","body":"flex min-h-0 flex-1 flex-col overflow-auto p-4 sm:p-4"}) { Menu ⋮ do card: "Copiar para" (outros painéis + Novo painel) e "Mais opções" (Redefinir resolução padrão · Visualizar expandido · Remover, destrutivo). · Gráfico de radial "Cumprimento por equipe" (lib de chart do EDS; séries na paleta chart-1..10): cabeçalho com breadcrumb/título + toolbar de Zoom In · Zoom Out · Selection Zoom · Panning · Reset; hover destaca o ponto e abre tooltip com rótulo e valor. Ocupa a altura do card (mín. 14rem); em card estreito a toolbar colapsa num menu único. } } · Empty state do painel (quando não há widgets): ilustração do EDS + "Seu painel está em branco" + "Copie widgets das index ou de outros painéis para começar a personalizar." }
Right-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente Painel transversal (Mensagens · Genius · Carrinho) na right-area/drawer
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeNavBar (itens=[{"l":"Dashboard","i":"layout-dashboard"},{"l":"Transações","i":"file-input"},{"l":"Fornecedores","i":"store"},{"l":"Catálogos","i":"shopping-bag"}], ativo=Dashboard, sitemap=true)
Anatomia do dashboard (painel "Meus widgets"), em ORDEM (topo → base): 1) Header (app bar) [Topo, full-width] · 2) Abas de painéis + menus [Faixa abaixo do header] · 3) Filter Bar do painel [Faixa abaixo das abas] · 4) Toolbar do painel [Acima da grade — título/contexto à esquerda, ações à direita (OU delegada ao subheader)] · 5) Seção de métricas (KPIs) [Topo do corpo — ABAIXO da toolbar, nunca acima das ações] · 6) Grade de widgets (12 col) [Corpo (coluna central)] · 7) Chart Wizard (criação/edição) [Overlay/painel — abre por "Novo gráfico" ou "Editar" no ⋮ do card] · 8) Sidebar de fixados (OPCIONAL) [Coluna lateral direita — só quando o modo de fixar-por-arraste está ligado].
Header (app bar): App bar AZUL me-brand no desktop / BRANCO no mobile (mesma casca da Index). No mobile o dashboard NÃO tem hambúrguer (não há sidebar). Marca + navegação horizontal + transversais + avatar. Transversais (Mensagens/Genius/Carrinho) FUNCIONAM: abrem painel na right-area (desktop) ou drawer (mobile). Busca = overlay. Avatar = menu do usuário (dropdown no desktop / drawer no mobile).
Abas de painéis + menus: Abas de painéis (ex.: Painel de compras · Aprovações e Requisições · Fornecedores · +). Editar o nome da aba inline (renomear). Menu da aba (⋮): Compartilhar · Duplicar · Renomear · Ocultar · Remover. O painel DEFAULT (1º) não tem Compartilhar/Remover. ⋮ da página: Restaurar padrão · Meus links · Filtros salvos · Painéis (visibilidade) · Exportar (PDF ou imagem). Botão "+" / "Novo painel" abre o modal "Adicionar painel" com 3 TIPOS: Externo (link de um dashboard externo — só plataformas permitidas: PowerBI, Google Analytics, Tableau, Looker Studio, Zendesk) · Interno (link de compartilhamento de um dashboard ME) · Em branco (só o título). Título sempre obrigatório; link obrigatório em Externo/Interno.
Filter Bar do painel: Filtros persistentes do painel (ex.: Meus processos · Todo período · Processo = X ×). Cluster à direita: adicionar (+) · salvar visão (💾) · limpar (🗑) · ⋮. Controlam os widgets abaixo; sinalizam estado "alterado".
Toolbar do painel: Ordem FIXA: "Novo gráfico" (abre o Chart Wizard) · "Restaurar padrão" (warning: reorganiza, NÃO apaga) · "Limpar" (error: remove). Cada ação só habilita quando há o que fazer. O dashboard NÃO tem FAB — as ações ficam no ⋮ "Mais ações" da página (fixo à direita da faixa de abas, fora do scroll).
Seção de métricas (KPIs): Bloco de TILES em grade responsiva: cada tile = ícone (chip colorido) + RÓTULO + número + delta (Badge semântico ↑↓). NÃO é CardView (card de produto) NEM cards gigantes full-width empilhados — são tiles compactos, vários por linha.
Grade de widgets (12 col): Grid 12 col, gap 16px, card padrão 4 col (mín. 3×3), altura de linha 30px. Cada card: menu ⋮ + ARRASTAR (pointer: sombra azul + reflow) + REDIMENSIONAR (alças) + AGRUPAR (card sobre card = pasta). GRÁFICOS usam a paleta chart-1..10 (NUNCA cor de status): barras/rosca/radial = cor POR ponto/categoria; área/linha = série única (1 cor geral). KPIs (tiles) usam cor de STATUS (neutral/info/warning/error). Cada dado (tile do KPI, linha da lista, ponto do gráfico, CTA) pode ter LINK + DESTINO. O CTA do card promo pode ser botão SPLIT com opções + sub-opções (ex.: "Nova transação"). Cards de dashboard EXTERNO/INTERNO (embed) coexistem com os widgets — placeholder com o link do dashboard. Blocos curados coexistem: Seção de métricas, Lista, Grade de charts, Empty state.
Chart Wizard (criação/edição): Tela única: Tipo → Dados → Estilo/ajustes → Detalhes, com PREVIEW ao vivo. Editar reabre pré-preenchido. Emite a config (on-chart-created); NÃO é onde o gráfico final aparece (isso é o Widget).
Sidebar de fixados (OPCIONAL): Cópias compactas em pastas por grupo (collapsibles). Fixar = COPIAR (vidas apartadas). NÃO incluir por padrão se a tela não pedir explicitamente.
Menu ⋮ de cada widget (ordem fixa): Editar (Reabre o Chart Wizard pré-preenchido) · Tipo de gráfico (Troca o tipo na hora (barra ↔ linha ↔ pizza…)) · Período (Seletor no header do card (7 dias / 30 dias / Este ano)) · Copiar para (Copia o card para outro painel/aba (ou "Novo painel")) · Mover para grupo (Move o card para uma pasta existente) · Fixar / Desafixar (Fixa uma cópia na sidebar (ou remove)) · Redefinir resolução padrão (Volta o card ao tamanho default do tipo; DISABLED quando já está no padrão) · Visualizar expandido (Card assume a largura fill da linha (12 col)) · Remover (Exclui (com modal de confirmação)).
Tipos de gráfico disponíveis (Chart Wizard): Barras (e horizontal) · Linhas · Área · Pizza (e Donut) · Radar · Radial · Tag Cloud · KPI.
Blocos curados que coexistem com os widgets: Seção de métricas / KPIs (tiles) — KPIs num card; cada tile = ícone (chip) + rótulo + número, borda inferior por TOM de status (neutral/info/warning/error) + tooltip ⓘ opcional. NÃO usa paleta de chart. · Lista — Card de linhas rótulo → valor (hover azul), reutilizável (ex.: Cotações, Contratos, Pedidos…). Cada linha pode ter link/destino. · Card promo — CTA de criação (título + descrição + botão). O botão pode ser SPLIT com opções + sub-opções (ex.: Nova transação → Requisição › Requisição de compra/serviço · Cotação · …). · Gráfico (widget) — Card com breadcrumb opcional + tooltip ⓘ + filtro de data + toolbar de zoom (área). Tipos: barras/área/linha/rosca/radial. Cor = paleta chart (por ponto em barras/rosca/radial; série única em área/linha). · Dashboard externo/interno (embed) — Painel/card que incorpora um dashboard por link — Externo (plataformas permitidas) ou Interno (compartilhamento ME). · Grade de charts — Gráficos em grade responsiva (1–3 colunas), em modo galeria (gráfico puro) ou como widget (casca + período). · Empty state do painel — Painel vazio: ilustração EDS (generico-device-3 + badge exclamação) + título "Seu painel está em branco" + "Copie widgets das index ou de outros painéis para começar a personalizar." (sem CTA).
Responsividade por área (desktop → mobile/tablet, recorte lg=1024px): Header: App bar BRANCO (logo azul, lupa, transversais, avatar) — SEM hambúrguer no dashboard (não há sidebar). Transversais (Mensagens/Genius/Carrinho) abrem em drawer; avatar abre drawer de menu do usuário. · Abas de painéis (toolbar): Abas + "+" rolam na horizontal (swipe + roda do mouse), SEM scrollbar; o ⋮ "Mais ações" fica FIXO à direita (fora do scroll). · Filter Bar: A FilterBar INTEIRA rola na horizontal (swipe + roda do mouse), SEM scrollbar. · Seção de métricas (KPIs): Empilham em 1 coluna, mantendo a ordem. · Grade de widgets: 1 coluna full-width; a tela rola verticalmente (só o BODY rola; header/abas/filtros/navbar ficam fixos). · Footer / navbar inferior: Navbar inferior AZUL me-brand com os menus do header + "Mais" (drawer). Dashboard NÃO tem FAB..
LAYOUT (block MeLayout — preencha só os slots usados)
- #header → Header = app bar do ME: barra AZUL full-width (cor primária = me-brand; NÃO o verde default do Nuxt UI) com a marca "me." em branco à esquerda, navegação horizontal no topo, e à direita os transversais + avatar. NÃO renderize header neutro/claro nem mova a marca para uma sidebar.
- #toolbar → Subheader com filtros globais (período, empresa…) que controlam tudo abaixo.
- #default → linha de KpiCards (topo, abaixo das ações) + grid de 12 colunas com widgets/gráficos.
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Cada bloco de gráfico é um Card.
Os filtros globais do topo controlam tudo abaixo.
Ordem fixa da tela: ações/subheader → KPIs (topo do CORPO, ABAIXO das ações, nunca acima) → gráficos no grid.
KPI = KpiCard (número + variação), nunca CardView.
Séries de gráfico usam a paleta chart-1..10 (cada série/categoria uma cor; nunca cor de status; série única pode ser 1 cor só).
No mobile: app bar BRANCO (logo azul) + navbar inferior azul; ações colapsam em "Mais ações" (FAB); KPIs empilham em 1 coluna mantendo a ordem; o grid empilha em 1 coluna full-width e a tela rola verticalmente (sem carrossel horizontal).
PRONTO QUANDO
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.KPIs no topo, gráficos no grid; os filtros globais controlam tudo abaixo.
Formulário
Cadastro/edição — subheader de ações (Cancelar · Salvar · Visualizar), seção de campos e seções com perguntas configuráveis (tipo de resposta, peso, obrigatório).
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de formulário do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Formulário
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Header · Subheader (ações) · Cabeçalho de seção (título + descrição) · Campos em grid · Seções com perguntas.
Componentes obrigatórios: Subheader (block EletroDS — Cancelar/Salvar/Visualizar), MeButtonBar, MeInput · MeInputDate · MeSelectMultiple (campos), UFormField (Nuxt UI — rótulo + validação inline).
Layout: {EletroDS (MeLayout)}.
Estrutura: {Header, Toolbar, Main, Footer}.
Dashboard — sidebar título: {Aplicação}.
Dashboard — sidebar itens: {}.
Dashboard — sidebar user: {Marina Lopes}.
Dashboard — navbar título: {Página}.
Dashboard — navbar ícone: {file-input}.
Dashboard — toolbar: {}.
Page — aside esq. título: {Navegação}.
Page — aside esq. itens: {}.
Page — header título: {Novo cadastro}.
Page — header descrição: {Preencha os campos}.
Page — aside dir. título: {Nesta página}.
Page — aside dir. itens: {}.
Shell — header título: {Minha aplicação}.
Shell — header nav: {}.
Shell — footer texto: {© 2026 Mercado Eletrônico}.
Header — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeHeader (ativo=Transações, navItens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"},{"l":"Usuários","i":"users","u":"#"},{"l":"Mais","i":"ellipsis"}], transversais=Mensagens, Genius, Carrinho, menuUsuario=Meu perfil, Idioma, Substituição, Configurações, Novidades e Atualizações, Sair, headerMaisItens=Compras, Fornecedores, Configurações, brandBg=Azul ME (padrão), brandIconColor=Branco (padrão), msgBadge=10, cartBadge=60, userNome=Marina Lopes, sigla=ML, cargo=Compradora)
Nav-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UStepper (tipoNav=Etapas (UStepper), titulo=Etapas, itens=[{"l":"Dados gerais","i":"clipboard-list"},{"l":"Seções","i":"layers"},{"l":"Revisão","i":"check-check"}], color=primary, size=md, orientation=vertical, variant=pill)
Left-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UNavigationMenu (tipoLeft=Sidebar de seções, titulo=Navegação, itens=[{"l":"Dados gerais","i":"clipboard-list"},{"l":"Seções","i":"layers"},{"l":"Anexos","i":"paperclip"},{"l":"Histórico","i":"history"}])
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeNavBar (itens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"}], color=primary, sitemap=true)
Right-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USlideover (tipoRight=Painéis transversais (ME), side=right, direction=right, handle=true, overlay=true, dismissible=true)
Toolbar — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeButtonBar (variant=ghost, color=primary, size=lg, acoes=Cancelar · Salvar · Visualizar · Salvar rascunho)
Main — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
{
setup() {
const url = Vue.ref('');
const editing = Vue.ref(false);
const committed = Vue.ref(false);
const pos = Vue.ref({ x: 50, y: 50 });
const posDraft = Vue.ref({ x: 50, y: 50 });
const bandEl = Vue.ref(null);
const inp = Vue.ref(null);
const bandClass = Vue.computed(() => 'h-40 sm:h-48' + (editing.value ? ' cursor-move' : ''));
const bandStyle = Vue.computed(() => { const p = editing.value ? posDraft.value : pos.value; return url.value ? { backgroundImage: 'url(' + url.value + ')', backgroundPosition: p.x + '% ' + p.y + '%', backgroundSize: 'cover' } : null; });
function fromFile(f) { if (!f) return; if (url.value && url.value.indexOf('blob:') === 0) URL.revokeObjectURL(url.value); url.value = URL.createObjectURL(f); pos.value = { x: 50, y: 50 }; posDraft.value = { x: 50, y: 50 }; editing.value = true; committed.value = false; }
function onUpload(v) { fromFile(Array.isArray(v) ? v[0] : v); }
function pick() { if (inp.value) inp.value.click(); }
function onReplace(e) { const f = e.target.files && e.target.files[0]; fromFile(f); e.target.value = ''; }
function removeImg() { url.value = ''; editing.value = false; committed.value = false; }
function openEdit() { editing.value = true; posDraft.value = Object.assign({}, pos.value); }
function cancel() { if (!committed.value) removeImg(); else editing.value = false; }
function save() { pos.value = Object.assign({}, posDraft.value); editing.value = false; committed.value = true; }
let drag = null;
const clamp = (n) => Math.max(0, Math.min(100, n));
function onDrag(e) { if (!drag || !bandEl.value) return; const r = bandEl.value.getBoundingClientRect(); const dx = ((e.clientX - drag.mx) / r.width) * 100; const dy = ((e.clientY - drag.my) / r.height) * 100; posDraft.value = { x: clamp(drag.x - dx), y: clamp(drag.y - dy) }; }
function endDrag() { drag = null; window.removeEventListener('mousemove', onDrag); window.removeEventListener('mouseup', endDrag); }
function startDrag(e) { if (!editing.value || !url.value) return; drag = { mx: e.clientX, my: e.clientY, x: posDraft.value.x, y: posDraft.value.y }; window.addEventListener('mousemove', onDrag); window.addEventListener('mouseup', endDrag); }
return { url, editing, bandEl, inp, bandClass, bandStyle, onUpload, pick, onReplace, removeImg, openEdit, cancel, save, startDrag };
},
template: '<div><input ref="inp" type="file" accept="image/png,image/jpeg" style="display:none" @change="onReplace"><div v-if="url" class="group relative overflow-hidden rounded-xl border border-default"><div ref="bandEl" class="w-full bg-elevated" :class="bandClass" :style="bandStyle" @mousedown="startDrag"></div><template v-if="editing"><div class="pointer-events-none absolute inset-0 rounded-xl ring-2 ring-inset ring-primary/60"></div><div class="absolute right-3 top-3 z-10 flex flex-wrap items-center gap-1 rounded-lg bg-default p-1 shadow-md ring ring-default"><UButton icon="i-lucide-image-up" label="Trocar" color="neutral" variant="ghost" size="xs" @click="pick" /><UButton icon="i-lucide-trash" label="Remover" color="error" variant="ghost" size="xs" @click="removeImg" /><UButton label="Cancelar" color="neutral" variant="ghost" size="xs" @click="cancel" /><UButton label="Salvar" color="primary" variant="solid" size="xs" @click="save" /></div></template><UButton v-else icon="i-lucide-pencil" label="Editar" color="neutral" variant="solid" size="sm" class="absolute right-3 top-3 z-10 opacity-100 shadow-md transition-opacity sm:opacity-0 sm:group-hover:opacity-100" @click="openEdit" /></div><UFileUpload v-else variant="area" accept="image/png,image/jpeg" :multiple="false" icon="i-lucide-image-plus" label="Adicionar imagem de banner" description="Arraste ou clique · PNG ou JPG · recomendado 1600x360" class="w-full" @update:model-value="onUpload" /></div>'
}
```
• Área 2: Colunas; Grupo { Componente UFormField (label=Carregar usando um modelo template) { Componente USelect (placeholder=Selecionar, itens=Modelo padrão, RFX, Cotação) } · Colunas · Componente UFormField (label=Descrição do questionário, required=true) { Componente UTextarea (placeholder=Descreva em poucas palavras) } · Componente USwitch (label=Este questionário precisa de aprovação) }
• Área 3: Componente USeparator (color=neutral, stype=solid)
• Área 4: repeat; Componente UButton (icon=plus, label=Adicionar seção, color=primary, variant=soft, size=sm, class=self-start)
LAYOUT (block MeLayout — preencha só os slots usados)
- #header → Header = app bar do ME: barra AZUL full-width (cor primária = me-brand; NÃO o verde default do Nuxt UI) com a marca "me." em branco à esquerda, navegação horizontal no topo, e à direita os transversais + avatar. NÃO renderize header neutro/claro nem mova a marca para uma sidebar.
- #toolbar → Subheader de ações (Cancelar · Salvar · Visualizar; até 3 + "Mais ações").
- #default → cabeçalho de seção + grid de campos (Informações gerais) + seções com perguntas.
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Ações fixas no subheader (Cancelar · Salvar · Visualizar), nunca soltas no meio.
Campos agrupados em seções com cabeçalho (título + descrição).
Cada pergunta declara tipo de resposta, peso e se é obrigatória.
Validação inline; obrigatórios marcados com *.
Criar/editar de um DOCUMENTO = a MESMA tela (uma só) — muda apenas o título ("Novo X" ao criar · "Editar X #número" ao editar); na EDIÇÃO os campos obrigatórios/existentes já vêm PREENCHIDOS. Isso é distinto da tela de VER o documento (leitura: forehead + abas + corpo), que é outra tela..
PRONTO QUANDO
- Ações fixas no subheader (até 3 + "Mais ações"), nunca soltas no meio.
- Cada pergunta com seu tipo de resposta; obrigatório marcado com * e anexo opcional quando habilitado.
- Validação inline nos campos.
- Cada seção com ações próprias: Compartilhar (modal com campo de pessoa em fill + botão +) e Excluir (diálogo de confirmação com ícone, sem body, sem X, footer Manter/Excluir).
- Perguntas gerenciáveis na seção: adicionar, remover (com confirmação) e reordenar por arraste.
- Compartilhar questionário inteiro no topo (mesmo modal de compartilhamento).
- Modais/diálogos abrem dentro da área da tela, não sobre o site.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Monte o corpo por áreas → colunas → peças (Banner, Cabeçalho, Formulário, Seção…). Cada peça é totalmente configurável.
Wizard / fluxo em etapas
Fluxo guiado em etapas — indicador de progresso, conteúdo da etapa e rodapé Voltar/Avançar.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de wizard / fluxo em etapas do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Wizard / fluxo em etapas
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Indicador de progresso (passos) · Conteúdo da etapa atual · Rodapé (Voltar + Avançar / Concluir).
Componentes obrigatórios: Subheader (block EletroDS — título/passos/ações), UStepper (Nuxt UI — indicador de progresso, horizontal no topo do Main), MeButtonBar (Voltar/Continuar/Concluir), MeInput · MeSelectMultiple · UFormField (campos da etapa), UCard (itens em cards na etapa de itens), UIcon (estado de sucesso na confirmação).
Layout: {EletroDS (MeLayout)}.
Estrutura: {Header, Toolbar, Main, Footer}.
Tarefa do fluxo: {tarefa}.
Header — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeHeader (ativo=Transações, navItens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"},{"l":"Usuários","i":"users","u":"#"},{"l":"Mais","i":"ellipsis"}], transversais=Mensagens, Genius, Carrinho, menuUsuario=Meu perfil, Idioma, Substituição, Configurações, Novidades e Atualizações, Sair, headerMaisItens=Compras, Fornecedores, Configurações, brandBg=Azul ME (padrão), brandIconColor=Branco (padrão), msgBadge=10, cartBadge=60, userNome=Marina Lopes, sigla=ML, cargo=Compradora)
Toolbar — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeButtonBar (size=lg, acoes=Voltar · Continuar)
Nav-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UStepper (tipoNav=Etapas (UStepper), titulo=Etapas, itens=[{"l":"Dados","i":"clipboard-list"},{"l":"Itens","i":"list"},{"l":"Revisão","i":"check-check"},{"l":"Confirmação","i":"circle-check"}], color=primary, size=md, orientation=vertical, variant=pill)
Left-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UNavigationMenu (tipoLeft=Sidebar de seções, titulo=Navegação, itens=[{"l":"Dados gerais","i":"clipboard-list"},{"l":"Seções","i":"layers"},{"l":"Anexos","i":"paperclip"},{"l":"Histórico","i":"history"}])
Right-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USlideover (tipoRight=Painéis transversais (ME), side=right, direction=right, handle=true, overlay=true, dismissible=true)
Main — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UStepper (itens=[{"l":"Dados","i":"clipboard-list"},{"l":"Itens","i":"list"},{"l":"Revisão","i":"check-check"},{"l":"Confirmação","i":"circle-check"}], color=primary, size=sm, stepState=wizardStep, class=sticky top-0 z-[5] w-full bg-default pb-4 pt-2); Grupo (visível quando: state.wizardStep === 0) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h2 class="text-lg font-semibold text-highlighted">Dados</h2><p class="mt-0.5 text-sm text-muted">Preencha os dados desta etapa para continuar.</p></div>
``` · Componente UFormField (label=Carregar usando um modelo template) { Componente USelect (placeholder=Selecionar, itens=Modelo padrão, RFX, Cotação) } · Colunas · Componente UFormField (label=Descrição) { Componente UTextarea (placeholder=Descreva em poucas palavras) } }; Grupo (visível quando: state.wizardStep === 1) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h2 class="text-lg font-semibold text-highlighted">Itens</h2><p class="mt-0.5 text-sm text-muted">Adicione os itens deste fluxo.</p></div>
``` · Colunas · Colunas }; Grupo (visível quando: state.wizardStep === 2) { Colunas }; Grupo (visível quando: state.wizardStep === 3) { Componente UIcon (name=i-lucide-circle-check, class=size-12 text-success) · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-center text-base font-semibold text-highlighted">Tudo pronto para enviar</p>
``` · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-center text-sm text-muted">Revise os dados das etapas anteriores e confirme.</p>
``` }
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeNavBar (itens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"}], color=primary, sitemap=true)
LAYOUT (block MeLayout — preencha só os slots usados)
- #header → Header = app bar do ME: barra AZUL full-width (cor primária = me-brand; NÃO o verde default do Nuxt UI) com a marca "me." em branco à esquerda, navegação horizontal no topo, e à direita os transversais + avatar. NÃO renderize header neutro/claro nem mova a marca para uma sidebar.
- #toolbar → Subheader do fluxo: título + "Passo X de N" + Voltar/Continuar.
- #default → indicador de passos (stepper navegável) + conteúdo da etapa ativa.
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Valide cada etapa antes de avançar.
"Concluir" no último passo, não "Avançar".
Estado do passo (concluída · atual · futura) com sinal redundante à cor (não só cor).
Mobile/tablet: o stepper compacta em "Passo X de N" textual; os campos empilham; as ações vão para um rodapé FIXO (Voltar/Avançar ao alcance do polegar).
PRONTO QUANDO
- Cada etapa é validada antes de avançar.
- No último passo, "Continuar" vira "Concluir" (rótulo e ação).
- O stepper reflete a etapa ativa e o corpo mostra o conteúdo dela; clicar num passo navega até ele.
- O stepper é uma peça do Main (horizontal, fixo no topo) e independe da Nav-area — aparece mesmo com a zona Nav desligada.
- Estado do passo (concluída/atual/futura) com sinal redundante à cor.
- Tipos de conteúdo por etapa: Formulário (campos) · Itens em cards (UCard) · Revisão (valores em altura de input) · Confirmação (ícone + textos).
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Liste os passos na ordem, os campos de cada etapa (com tipo) e diga o que valida antes de avançar.
Livre
Ponto de partida universal — escolha uma ESTRUTURA em "O que criar?" (casca: MeLayout / Página / Shell / Login / Full-bleed · OU overlay: Modal / Dialog / Drawer / Slideover / Popover) e componha cada zona por ÁREAS de peças reais. Canvas em branco; as foundations valem sempre.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de livre do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Tela livre
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Estrutura (o tipo escolhido em "O que criar?") · Zonas do tipo — cada uma montada por áreas → colunas → peças reais.
Componentes obrigatórios: A casca/overlay do tipo escolhido (MeLayout / UPage / UModal / UDrawer…), os componentes reais que você compõe nas áreas de cada zona (EDS → Nuxt UI → compor).
Estrutura: {Header, Main}.
SEM CASCA (full-bleed): tela cheia, sem Header/shell do ME — só as foundations (tokens, espaçamento, voz) + acessibilidade. O corpo vem das áreas abaixo.
Zonas ligadas: (nenhuma).
Cada zona é montada por ÁREAS empilhadas → colunas → peças REAIS (hierarquia EDS → Nuxt UI → compor), na ordem. Zona vazia = região sem conteúdo. Nunca recrie o que já existe; use os tokens do ME (sem HEX cru).
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Use os componentes da stack por papel — não recrie o que já existe.
Mantenha as foundations do ME (tokens, espaçamento e voz) mesmo sem um template fixo.
Monte só o que está nas áreas de cada zona; zona vazia = região sem conteúdo.
PRONTO QUANDO
- A tela reflete o TIPO escolhido (casca ou overlay) e o conteúdo composto nas áreas de cada zona.
- A tela respeita as foundations do ME (tokens, espaçamento, voz) mesmo sem um template fixo.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Escolha o TIPO em "O que criar?" (casca ou overlay), ligue as zonas e monte cada uma por áreas → colunas → peças reais (use os Modelos prontos no "+ Adicionar"). Canvas em branco.
Login
Tela de autenticação — FORA do chassi. Split: painel de marca + formulário (MeLogin + MeLoginForm).
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de login do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Login e acesso
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Painel de marca (esquerda, azul me-brand) · Painel de formulário (direita).
Componentes obrigatórios: MeLogin (block EletroDS — split imagem + formulário), MeLoginForm (EletroDS — usuário/senha, lembrar, esqueci, locale, links), painel de marca custom no slot #image (marca "me." + tagline + textura).
Estrutura: {Painel de marca, Formulário}.
Painel de marca — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<img src="/img/me-logo-white.svg" alt="me." class="h-8 w-20 object-contain object-left eds-allow">
```
• Área 2: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-2xl leading-snug font-normal text-white eds-allow">O <strong class="font-bold">MERCADO</strong> elevado à potência do <strong class="font-bold">ELETRÔNICO</strong></p>
```
Formulário — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USelect (itens=Português, English, value=Português, icon=i-lucide-globe, color=neutral, variant=outline, size=md, wfit=true)
• Área 2: Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<h1 class="text-2xl font-semibold text-highlighted eds-allow">Entre na sua conta</h1>
``` · Grupo { Componente UFormField (label=Usuário ou e-mail, required=true) { Componente MeInput (type=email, placeholder=nome@empresa.com) } · Componente UFormField (label=Senha, required=true) { Componente MeInput (type=password, placeholder=••••••••, model=loginSenha) } · Grupo { Grupo { Componente UIcon (name=«(len(state.loginSenha) >= 8) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(len(state.loginSenha) >= 8) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 8 caracteres</span>
``` } · Grupo { Componente UIcon (name=«(test(state.loginSenha, '[a-z]') && test(state.loginSenha, '[A-Z]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.loginSenha, '[a-z]') && test(state.loginSenha, '[A-Z]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Letras maiúsculas e minúsculas</span>
``` } · Grupo { Componente UIcon (name=«(test(state.loginSenha, '[0-9]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.loginSenha, '[0-9]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 1 número</span>
``` } · Grupo { Componente UIcon (name=«(test(state.loginSenha, '[^A-Za-z0-9]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.loginSenha, '[^A-Za-z0-9]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 1 caractere especial</span>
``` } } · Grupo { Componente UCheckbox (label=Lembrar senha) · Componente UButton (label=Esqueci a senha, variant=link, color=primary, size=md) } · Componente UButton (label=Entrar, color=primary, size=lg, block=true) } · Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-sm text-muted eds-allow">Não tem uma conta?</span>
``` · Componente UButton (label=Cadastre-se como Fornecedor, variant=link, color=primary, size=md) } · Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-sm text-muted eds-allow">Não recebeu um e-mail de ativação?</span>
``` · Componente UButton (label=Clique aqui, variant=link, color=primary, size=md) } }
LAYOUT (block MeLayout — preencha só os slots usados)
- #image → Painel de marca: azul me-brand + textura hexagonal + "me." branco + tagline. No mobile some (vira faixa no topo).
- #default → MeLoginForm: usuário/senha (mostrar/ocultar), lembrar senha + esqueci a senha, CTA "Entrar", links (Cadastre-se como Fornecedor, ativação).
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
FORA do chassi MeLayout — sem header/nav do app; a identidade vem do painel de marca..
CTA "Entrar" primário full-width; ações secundárias viram links..
Seletor de idioma no topo do painel de formulário..
No mobile o split empilha: header branco no topo + formulário abaixo (só o form rola)..
PRONTO QUANDO
- Split de marca + formulário, fora do chassi.
- CTA "Entrar" full-width; idioma no topo.
- Mobile: header branco + form empilhado.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.É a exceção ao chassi: a identidade vem do painel de marca azul, não do header. Use MeLogin + MeLoginForm reais.
Cadastro Comprador
Criação de conta de comprador — split de marca + formulário em 2 passos + validação por e-mail.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de cadastro comprador do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Cadastro Comprador
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Painel de marca · Formulário multi-step (2 passos + validação).
Componentes obrigatórios: MeLogin (split), MeInput c/ máscara (CNPJ/CEP/telefone), USelect (País/Natureza/Cidade/Estado), UCheckbox (aceite dos Termos), UModal (Termos), barra de progresso.
Estrutura: {Painel de marca, Formulário}.
Painel de marca — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<img src="/img/me-logo-white.svg" alt="me." class="h-8 w-20 object-contain object-left eds-allow">
```
• Área 2: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-2xl leading-snug font-normal text-white eds-allow">O <strong class="font-bold">MERCADO</strong> elevado à potência do <strong class="font-bold">ELETRÔNICO</strong></p>
```
Formulário — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USelect (itens=Português, English, value=Português, icon=i-lucide-globe, color=neutral, variant=outline, size=md, wfit=true)
• Área 2: Grupo (visível quando: state.wizardStep === 0) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<h1 class="text-2xl font-semibold text-highlighted eds-allow">Crie sua conta gratuita.</h1>
``` · Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-sm text-muted eds-allow">Já tem uma conta?</span>
``` · Componente UButton (label=Fazer login, variant=link, color=primary, size=md) } · Grupo { Componente UFormField (label=País, required=true) { Componente USelect (placeholder=Selecione um país, itens=Brasil, Portugal, Estados Unidos) } · Componente UFormField (label=Natureza, required=true) { Componente USelect (placeholder=Selecione a natureza do perfil, itens=Pessoa Jurídica, Pessoa Física) } · Componente UFormField (label=CNPJ, required=true) { Componente MeInput (placeholder=000.000.0000-00) } · Componente UFormField (label=Razão Social, required=true) { Componente MeInput (placeholder=Insira o nome da sua empresa) } · Componente UFormField (label=CEP, required=true) { Componente MeInput (placeholder=00000-000) } · Componente UFormField (label=Endereço, required=true) { Componente MeInput (placeholder=Insira seu endereço) } · Colunas · Componente UFormField (label=Bairro, required=true) { Componente MeInput (placeholder=Insira seu bairro) } · Componente UFormField (label=Cidade, required=true) { Componente USelect (placeholder=Selecione a cidade) } · Componente UFormField (label=Estado, required=true) { Componente USelect (placeholder=Selecione o estado) } } · Componente UButton (label=Próximo passo, color=primary, size=lg, block=true) }; Grupo (visível quando: state.wizardStep === 1) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h1 class="text-2xl font-semibold text-highlighted eds-allow">Dados cadastrais</h1><p class="mt-0.5 text-sm text-muted eds-allow">Insira seus dados para prosseguir</p></div>
``` · Grupo { Componente UFormField (label=Nome completo, required=true) { Componente MeInput (placeholder=Informe seu nome) } · Componente UFormField (label=E-mail, required=true) { Componente MeInput (placeholder=nome@empresa.com.br, type=email) } · Componente UFormField (label=Login, required=true) { Componente MeInput (placeholder=Informe seu login) } · Colunas · Componente UFormField (label=Senha, required=true) { Componente MeInput (placeholder=••••••••, type=password, model=cadSenha) } · Grupo { Grupo { Componente UIcon (name=«(len(state.cadSenha) >= 8) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(len(state.cadSenha) >= 8) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 8 caracteres</span>
``` } · Grupo { Componente UIcon (name=«(test(state.cadSenha, '[a-z]') && test(state.cadSenha, '[A-Z]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.cadSenha, '[a-z]') && test(state.cadSenha, '[A-Z]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Letras maiúsculas e minúsculas</span>
``` } · Grupo { Componente UIcon (name=«(test(state.cadSenha, '[0-9]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.cadSenha, '[0-9]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 1 número</span>
``` } · Grupo { Componente UIcon (name=«(test(state.cadSenha, '[^A-Za-z0-9]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.cadSenha, '[^A-Za-z0-9]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 1 caractere especial</span>
``` } } · Componente UFormField (label=Repetir senha, required=true) { Componente MeInput (placeholder=••••••••, type=password) } · Componente UCheckbox (label=Confirmo que li e aceito os Termos e Condições do Mercado Eletrônico.) } · Componente UButton (label=Avançar, color=primary, size=lg, block=true) · Componente UButton (label=Voltar, variant=link, color=primary, size=md, block=true) }; Grupo (visível quando: state.wizardStep === 2) { Componente UIcon (name=i-lucide-list-checks, size=xl, color=primary) · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<h2 class="text-center text-lg font-semibold text-highlighted eds-allow">Validar cadastro</h2>
``` · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="max-w-sm text-center text-sm text-muted eds-allow">Enviamos um e-mail de confirmação. Acesse seu e-mail e clique no link de validação. Caso não tenha recebido, verifique sua caixa de spam ou tente novamente.</p>
``` · Componente UButton (label=Reenviar (27s), color=neutral, variant=outline, size=lg, block=true, disabled=true) · Componente UButton (label=Voltar, variant=link, color=primary, size=md, block=true) }; Grupo { Colunas · Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Próximo passo: <strong class="font-medium text-highlighted">{{ state.wizardStep === 0 ? 'Dados cadastrais' : state.wizardStep === 1 ? 'Validar cadastro' : 'Concluído' }}</strong></span>
``` · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs font-medium text-muted eds-allow">{{ (state.wizardStep || 0) + 1 }}/3</span>
``` } }
LAYOUT (block MeLayout — preencha só os slots usados)
- #image → Painel de marca (banner azul).
- #default → Multi-step: País/Natureza/CNPJ/Razão Social/CEP/Endereço/Número/Complemento/Bairro/Cidade/Estado → Nome/E-mail/Login/Telefone/Celular/Senha/Repetir + Termos → Validar cadastro.
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
FORA do chassi; split de marca + formulário..
Passo 1: empresa/endereço. Passo 2: dados cadastrais + senha (checklist de força) + aceite dos Termos..
Barra de progresso (X/2) com "Próximo passo"..
NÃO é o cadastro de Fornecedor (fluxo e campos diferentes)..
PRONTO QUANDO
- Split de marca + form 2 passos + validação por e-mail.
- Senha com checklist de força; aceite dos Termos.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Comprador = 3 passos (empresa/endereço → dados+senha → validar) por áreas + validação. Fora do chassi.
Cadastro Fornecedor
Conta de fornecedor — split de marca + 5 passos (conta → dados → validar e-mail → validar telefone → senha). Variante por convite.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de cadastro fornecedor do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Cadastro Fornecedor
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Painel de marca (ou banner de convite) · Formulário de 5 passos.
Componentes obrigatórios: MeLogin (split), MeInput c/ máscara (CNPJ), USelect (País), UCheckbox (Termos), UModal (Termos), barra de progresso (5 passos).
Estrutura: {Painel de marca, Formulário}.
Painel de marca — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<img src="/img/me-logo-white.svg" alt="me." class="h-8 w-20 object-contain object-left eds-allow">
```
• Área 2: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-2xl leading-snug font-normal text-white eds-allow">O <strong class="font-bold">MERCADO</strong> elevado à potência do <strong class="font-bold">ELETRÔNICO</strong></p>
```
Formulário — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USelect (itens=Português, English, value=Português, icon=i-lucide-globe, color=neutral, variant=outline, size=md, wfit=true)
• Área 2: Grupo (visível quando: state.wizardStep === 0) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<h1 class="text-2xl font-semibold text-highlighted eds-allow">Crie sua conta gratuita.</h1>
``` · Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-sm text-muted eds-allow">Já tem uma conta?</span>
``` · Componente UButton (label=Fazer login, variant=link, color=primary, size=md) } · Grupo { Componente UFormField (label=País, required=true) { Componente USelect (placeholder=Selecione, itens=Brasil, Portugal, Estados Unidos) } · Componente UFormField (label=CNPJ) { Componente MeInput (placeholder=000.000.0000-00) } · Componente UFormField (label=Razão Social, required=true) { Componente MeInput (placeholder=Informe a razão social) } · Componente UCheckbox (label=Confirmo que li e aceito os Termos e Condições do Mercado Eletrônico.) } · Componente UButton (label=Começar agora, color=primary, size=lg, block=true) }; Grupo (visível quando: state.wizardStep === 1) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h1 class="text-2xl font-semibold text-highlighted eds-allow">Dados cadastrais</h1><p class="mt-0.5 text-sm text-muted eds-allow">Insira seus dados para prosseguir</p></div>
``` · Grupo { Componente UFormField (label=Nome completo, required=true) { Componente MeInput (placeholder=Informe seu nome) } · Componente UFormField (label=Como você gostaria de ser chamado?) { Componente MeInput (placeholder=Insira o nome da empresa) } · Componente UFormField (label=Telefone, required=true) { Componente MeInput (placeholder=Informe seu telefone) } · Componente UFormField (label=E-mail corporativo, required=true) { Componente MeInput (placeholder=nome@empresa.com.br, type=email) } } · Componente UButton (label=Avançar, color=primary, size=lg, block=true) · Componente UButton (label=Voltar, variant=link, color=primary, size=md, block=true) }; Grupo (visível quando: state.wizardStep === 2) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h1 class="text-2xl font-semibold text-highlighted eds-allow">Validar Email</h1><p class="mt-0.5 text-sm text-muted eds-allow">Informe o código enviado para o e-mail<br><strong class="font-medium text-highlighted">j.halpert@dundermifflin.com</strong></p></div>
``` · Componente UFormField (label=Código, required=true) { Componente MeInput (placeholder=Informe o código) } · Componente UButton (label=Reenviar (27s), color=neutral, variant=outline, size=lg, block=true, disabled=true) · Componente UButton (label=Avançar, color=primary, size=lg, block=true) · Componente UButton (label=Voltar, variant=link, color=primary, size=md, block=true) }; Grupo (visível quando: state.wizardStep === 3) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h1 class="text-2xl font-semibold text-highlighted eds-allow">Validar Telefone</h1><p class="mt-0.5 text-sm text-muted eds-allow">Informe o código enviado para o telefone<br><strong class="font-medium text-highlighted">+55 (11) 1234-5678</strong></p></div>
``` · Componente UFormField (label=Código, required=true) { Componente MeInput (placeholder=Informe o código) } · Componente UButton (label=Reenviar (27s), color=neutral, variant=outline, size=lg, block=true, disabled=true) · Componente UButton (label=Avançar, color=primary, size=lg, block=true) · Componente UButton (label=Voltar, variant=link, color=primary, size=md, block=true) }; Grupo (visível quando: state.wizardStep === 4) { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h1 class="text-2xl font-semibold text-highlighted eds-allow">Crie sua senha</h1><p class="mt-0.5 text-sm text-muted eds-allow">Para a sua maior segurança, a senha deve contemplar todos os critérios listados</p></div>
``` · Grupo { Componente UFormField (label=Senha, required=true) { Componente MeInput (placeholder=••••••••, type=password, model=fornSenha) } · Grupo { Grupo { Componente UIcon (name=«(len(state.fornSenha) >= 8) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(len(state.fornSenha) >= 8) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 8 caracteres</span>
``` } · Grupo { Componente UIcon (name=«(test(state.fornSenha, '[a-z]') && test(state.fornSenha, '[A-Z]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.fornSenha, '[a-z]') && test(state.fornSenha, '[A-Z]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Letras maiúsculas e minúsculas</span>
``` } · Grupo { Componente UIcon (name=«(test(state.fornSenha, '[0-9]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.fornSenha, '[0-9]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 1 número</span>
``` } · Grupo { Componente UIcon (name=«(test(state.fornSenha, '[^A-Za-z0-9]')) ? 'i-lucide-circle-check' : 'i-lucide-circle-x'», size=sm, color=«(test(state.fornSenha, '[^A-Za-z0-9]')) ? 'success' : 'neutral'») · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Pelo menos 1 caractere especial</span>
``` } } · Componente UFormField (label=Repetir senha, required=true) { Componente MeInput (placeholder=••••••••, type=password) } } · Componente UButton (label=Concluir, color=primary, size=lg, block=true) · Componente UButton (label=Voltar, variant=link, color=primary, size=md, block=true) }; Grupo { Colunas · Grupo { Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs text-muted eds-allow">Próximo passo: <strong class="font-medium text-highlighted">{{ state.wizardStep === 0 ? 'Dados cadastrais' : state.wizardStep === 1 ? 'Validar e-mail' : state.wizardStep === 2 ? 'Validar telefone' : state.wizardStep === 3 ? 'Criar senha' : 'Acessar plataforma' }}</strong></span>
``` · Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<span class="text-xs font-medium text-muted eds-allow">{{ (state.wizardStep || 0) + 1 }}/5</span>
``` } }
LAYOUT (block MeLayout — preencha só os slots usados)
- #image → Painel de marca; ou banner de convite (empresa convidante) na variante por convite.
- #default → Formulário de 5 passos com barra de progresso (X/5) + "Próximo passo".
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
FORA do chassi; a partir do "Cadastre-se como Fornecedor" no login..
5 passos: conta (país/CNPJ/razão social + Termos) → dados cadastrais → validar e-mail → validar telefone → criar senha..
Variante POR CONVITE: muda só o banner (logo/nome da empresa convidante + vantagens do ME); o formulário é o mesmo..
PRONTO QUANDO
- 5 passos com validação de e-mail e telefone.
- Variante por convite muda só o banner.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Fornecedor = 5 passos + 2FA (e-mail/telefone) por áreas. Fora do chassi.
Acesso livre
Tela de acesso EM BRANCO — split de marca + formulário/fluxo montado do zero, mesmas opções de estrutura.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de acesso livre do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Acesso livre
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Painel de marca · Formulário.
Componentes obrigatórios: MeLogin (split imagem + formulário), os componentes conforme os elementos que você adicionar em cada passo.
Estrutura: {Painel de marca, Formulário}.
Painel de marca — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<img src="/img/me-logo-white.svg" alt="me." class="h-8 w-20 object-contain object-left eds-allow">
```
• Área 2: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-2xl leading-snug font-normal text-white eds-allow">O <strong class="font-bold">MERCADO</strong> elevado à potência do <strong class="font-bold">ELETRÔNICO</strong></p>
```; Grupo { Colunas }
Formulário — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USelect (itens=Português, English, value=Português, icon=i-lucide-globe, color=neutral, variant=outline, size=md, wfit=true)
• Área 2: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<h1 class="text-2xl font-semibold text-highlighted eds-allow">Título da tela</h1>
```; Grupo
LAYOUT (block MeLayout — preencha só os slots usados)
- #image → Painel de marca (ou banner de convite).
- #default → Formulário/fluxo montado do zero (passos + elementos).
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
FORA do chassi MeLayout; split de marca + formulário..
Estrutura livre — você define os passos e os elementos de cada um..
PRONTO QUANDO
- Split de marca + formulário, fora do chassi.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Comece do zero por áreas: idioma + título prontos; adicione campos/botões/passos. Painel personalizável.
Configurações gerais
Tela de configurações — chassi com left-area = menu de configurações (grupos aninhados + busca) + conteúdo da seção.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de configurações gerais do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Config gerais
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Header · Left-area (menu de configurações) · Conteúdo da seção.
Componentes obrigatórios: Layout (block EletroDS — chassi), UNavigationMenu (menu de config: grupos aninhados + busca "Busque neste menu"), MeButtonBar (toolbar da seção), UTable / UFormField (conteúdo da seção).
Layout: {EletroDS (MeLayout)}.
Estrutura: {Header, Left-area, Main, Footer}.
Header — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeHeader (ativo=__none__, navItens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"},{"l":"Usuários","i":"users","u":"#"},{"l":"Mais","i":"ellipsis"}], transversais=Mensagens, Genius, Carrinho, menuUsuario=Meu perfil, Idioma, Substituição, Configurações, Novidades e Atualizações, Sair, headerMaisItens=Compras, Fornecedores, Configurações, brandBg=Azul ME (padrão), brandIconColor=Branco (padrão), msgBadge=10, cartBadge=60, userNome=Marina Lopes, sigla=ML, cargo=Compradora)
Toolbar — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeButtonBar (variant=ghost, color=primary, size=lg, acoes=Cancelar · Salvar · Visualizar · Salvar rascunho)
Nav-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UNavigationMenu (tipoLeft=Sidebar de seções, titulo=Navegação, itens=[{"l":"Dados gerais","i":"clipboard-list"},{"l":"Seções","i":"layers"},{"l":"Anexos","i":"paperclip"},{"l":"Histórico","i":"history"}])
Left-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente UNavigationMenu (tipoLeft=Menu de configurações, titulo=Configurações, busca=true, buscaPlaceholder=Busque neste menu, secoes=[{"tab":"Estrutura","icon":"i-lucide-folder-tree","itens":[{"label":"Organizacional","defaultExpanded":true,"children":[{"label":"Níveis","active":true},{"label":"Cargos"},{"label":"Locais e Filiais"}]},{"label":"Operacional","defaultExpanded":true,"children":[{"label":"Objetos de Custo","active":true},{"label":"Condições de Pagamento"},{"label":"Fretes"},{"label":"Unidade de Medida"},{"label":"Moeda"}]},{"label":"Grupos","defaultExpanded":true,"children":[{"label":"Grupo de Produto","active":true},{"label":"Grupo de Fornecedores"},{"label":"Grupo de Compras"}]}]},{"tab":"Usuários e Acessos","icon":"i-lucide-users","itens":[{"label":"Usuários","active":true},{"label":"Perfis e Permissões"},{"label":"SSO"},{"label":"Autenticação e Segurança"}]},{"tab":"Processos","icon":"i-lucide-book-marked","itens":[{"label":"Requisição","defaultExpanded":true,"children":[{"label":"Funcionalidades","active":true},{"label":"Categorias"}]},{"label":"Cotação","defaultExpanded":true,"children":[{"label":"Funcionalidades","active":true},{"label":"Impostos e taxas"},{"label":"Mapa Comparativo"},{"label":"Savings"},{"label":"Categorias"}]},{"label":"Pedido","defaultExpanded":true,"children":[{"label":"Funcionalidades","active":true},{"label":"Alertas e Notificações"},{"label":"Termos de Aceite"},{"label":"Categorias"}]},{"label":"Contrato","defaultExpanded":true,"children":[{"label":"Funcionalidades","active":true},{"label":"Campos"}]},{"label":"Nota Fiscal","defaultExpanded":true,"children":[{"label":"Funcionalidades","active":true},{"label":"Alertas e Notificações"},{"label":"Campos"},{"label":"Categorias"}]},{"label":"Registro de Serviço","defaultExpanded":true,"children":[{"label":"Funcionalidades","active":true},{"label":"Categorias"}]}]},{"tab":"Funcionalidades","icon":"i-lucide-toggle-right","itens":[{"label":"Permissões","active":true},{"label":"Validações"},{"label":"Fluxos"},{"label":"Interface"}]},{"tab":"Sistema e Operações","icon":"i-lucide-unplug","itens":[{"label":"Automação","active":true},{"label":"Cargas"},{"label":"Integrações"},{"label":"Regras"}]},{"tab":"Alertas e Notificações","icon":"i-lucide-bell","itens":[{"label":"Processos","active":true},{"label":"Sistema"},{"label":"Emails"}]},{"tab":"Personalização","icon":"i-lucide-paintbrush-vertical","itens":[{"label":"Aparência","active":true},{"label":"Dashboards"}]}])
Main — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<div><h2 class="text-xl font-semibold text-default">Automação</h2><p class="mt-1 text-sm font-normal text-toned">Gerencie e edite os fluxos de automação</p></div>
```; Grupo { Componente MeTableView (colunas=[{"l":"","t":"selecao"},{"l":"Documento","t":"texto","lk":true},{"l":"Descrição","t":"texto"},{"l":"Criado por","t":"texto","fmt":"nome"},{"l":"Criado em","t":"texto","fmt":"data"},{"l":"Editado por","t":"texto","fmt":"nome"},{"l":"Versão","t":"texto","fmt":"numero"},{"l":"Status","t":"status"},{"l":"","t":"slot","slot":"[{\"tipo\":\"Componente\",\"comp\":\"UButton\",\"cfg\":{\"icon\":\"i-lucide-star\",\"color\":\"neutral\",\"variant\":\"ghost\",\"size\":\"xs\",\"square\":true}}]"},{"l":"","t":"slot","slot":"[{\"tipo\":\"Componente\",\"comp\":\"UDropdownMenu\",\"cfg\":{\"itens\":\"[{\\\"l\\\":\\\"Editar\\\",\\\"i\\\":\\\"pencil\\\"},{\\\"l\\\":\\\"Duplicar\\\",\\\"i\\\":\\\"copy\\\"},{\\\"l\\\":\\\"Excluir\\\",\\\"i\\\":\\\"trash\\\",\\\"color\\\":\\\"error\\\"}]\"},\"filhos\":[{\"tipo\":\"Componente\",\"comp\":\"UButton\",\"cfg\":{\"icon\":\"i-lucide-ellipsis-vertical\",\"color\":\"neutral\",\"variant\":\"ghost\",\"size\":\"xs\",\"square\":true}}]}]"}], headerBlocos=[{"tipo":"Colunas","sty":{"gap":"2","av":"center"},"colunas":[{"w":55,"blocos":[{"tipo":"Componente","comp":"MeButtonBar","cfg":{"size":"sm","acoes":[{"l":"Nova automação","i":"plus","color":"primary","variant":"solid"},{"l":"Importar","i":"download","color":"neutral","variant":"outline"},{"l":"Exportar","i":"upload","color":"neutral","variant":"outline"}]}}]},{"w":45,"sty":{"dir":"row","gap":"2","av":"center","ah":"end"},"blocos":[{"tipo":"Bloco (grupo)","sty":{"wMode":"fill"},"blocos":[{"tipo":"Componente","comp":"UInput","cfg":{"placeholder":"Placeholder","icon":"search","size":"sm","class":"w-full"}}]},{"tipo":"Componente","comp":"VibeTableMoreMenu","cfg":{"configuracoes":false}}]}]}]) }
Right-area — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente USlideover (tipoRight=Painéis transversais (ME), side=right, direction=right, handle=true, overlay=true, dismissible=true)
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Componente MeNavBar (itens=[{"l":"Dashboard","i":"layout-dashboard","u":"#"},{"l":"Transações","i":"file-input","u":"#"},{"l":"Fornecedores","i":"store","u":"#"},{"l":"Catálogos","i":"shopping-bag","u":"#"}], color=primary, sitemap=true)
LAYOUT (block MeLayout — preencha só os slots usados)
- #header → Header azul do ME.
- #left-area → Menu de configurações: grupos aninhados (Estrutura, Usuários e Acessos, Sistema e Operações…) + busca; seção ativa destacada.
- #default → Cabeçalho da seção + toolbar da seção + conteúdo (ex.: Automação = tabela).
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Usa o chassi MeLayout com o LEFT-AREA como menu de configurações (grupos aninhados + busca)..
NÃO usa o subheader/toolbar de documento; a ação primária + busca ficam no cabeçalho da seção (dentro do Main)..
Cabeçalho da seção (título + descrição) + toolbar da seção (ação primária + secundárias + busca) + conteúdo (tabela/form)..
No mobile o hambúrguer no header abre o menu de config em drawer (esquerda)..
PRONTO QUANDO
- Menu de config à esquerda (grupos aninhados + busca) + conteúdo da seção no corpo.
- Sem subheader de documento; a ação primária e a busca ficam no cabeçalho da seção.
- Grupos colapsáveis — o grupo com a seção ativa abre; item ativo destacado.
- Edição da seção via modal/inline (sem submit global).
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Config = chassi com Left-area = menu de config (grupos + busca) e Main = a seção ativa. Sem toolbar de documento; a ação primária fica no cabeçalho da seção.
Templates de e-mail
E-mail transacional do ME — um template default (header de marca + conteúdo + footer) contextualizado por cenário.
CONTEXTO
Você é um(a) engenheiro(a) de front-end do ME.
Você trabalha no ME — a plataforma de procurement (E-PROC) — seguindo o EletroDS Design Guide: foundations (tokens, espaçamento, tipografia, cor), os componentes do design system e a voz do produto em PT-BR (Glossário do ME).
ALVO (STACK) — EletroDS + Nuxt
- Stack: Nuxt 3 + Vue 3 (Composition API, `<script setup>`) + Nuxt UI v4, sobre o EletroDS Design Guide.
- Hierarquia de componentes (NESTA ordem; nunca recrie o que já existe): 1) blocks EletroDS Header, Subheader, Layout, TableView, CardView, ListView, Preview (em código as tags `<MeHeader>`, `<MeSubheader>`, `<MeLayout>`, `<MeTableView>`, `<MeCardView>`, `<MeListView>`, `<MePreview>`) + componentes MeForehead, MeButtonBar, MeFilterBar, MeCriterionInput, MeInput, MeInputDate, MeSelectMultiple, MeNavBar…; 2) Nuxt UI (UButton, UTabs, UBadge, UModal, UFormField, UTable…); 3) Vue puro só no que não existir nas libs acima.
- Foundations: apenas classes Tailwind + variáveis `--ui-*` (e tokens do EletroDS) — sem HEX, pixel cru ou valor fora da escala; dark mode pelos tokens.
- Saída: um componente Vue (Composition API).
TAREFA
Gere a tela de templates de e-mail do zero, seguindo o PADRÃO ME abaixo.
PADRÃO ME — Templates de e-mail
A anatomia abaixo é a estrutura da tela — a mesma que o preview do Compositor desenha. Siga a ordem e monte só o que está listado.
Anatomia, nesta ordem: Header (marca me.) · Conteúdo · Footer (atendimento + redes).
Componentes obrigatórios: shell de e-mail (card estreito + Roboto), zonas composáveis: Header (logo + slot) · Conteúdo · Footer, peças reais: UCard (tópicos), UButton (CTA e footer), UIcon, CTA primário único.
Cenário: {Confirmação de cadastro}.
Estrutura: {Header, Conteúdo, Footer}.
Conteúdo — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<h1 class="text-center text-lg font-bold text-gray-800 mb-1 eds-allow">Bem vindo ao Mercado Eletrônico!</h1>
```; Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-gray-600 text-sm leading-relaxed mb-2.5 eds-allow">Olá [Nome do fornecedor],</p>
```; Código custom (HTML) — use SÓ se não houver componente EDS/Nuxt equivalente:
```html
<p class="text-gray-600 text-sm leading-relaxed mb-2.5 eds-allow">Obrigado por se cadastrar! Para validar sua conta, clique no botão abaixo.</p>
```; Grupo { Componente UButton (label=Concluir cadastro, color=primary, variant=solid, size=md, trailingIcon=i-lucide-external-link) }
Footer — layout (o corpo é montado por ÁREAS empilhadas → colunas → peças; reproduza na ordem):
• Área 1: Grupo { Grupo { Componente UButton (label=Atendimento, icon=i-lucide-phone, color=neutral, variant=ghost, size=sm, class=text-white hover:text-white hover:bg-white/10) · Componente UButton (label=Conheça o ME, icon=i-lucide-external-link, color=neutral, variant=ghost, size=sm, class=text-white hover:text-white hover:bg-white/10) } · Grupo { Componente UButton (icon=i-lucide-linkedin, color=neutral, variant=ghost, size=sm, square=true, class=text-white hover:text-white hover:bg-white/10) · Componente UButton (icon=i-lucide-facebook, color=neutral, variant=ghost, size=sm, square=true, class=text-white hover:text-white hover:bg-white/10) · Componente UButton (icon=i-lucide-instagram, color=neutral, variant=ghost, size=sm, square=true, class=text-white hover:text-white hover:bg-white/10) } }
LAYOUT (block MeLayout — preencha só os slots usados)
- header → Faixa de marca — logo (toggle, upload OU "me." padrão) + slot composável (toggle). Áreas → peças.
- conteudo → Miolo contextual (áreas → peças): título/texto (custom), UCard nos tópicos, UButton no CTA. Cenários: confirmação, convite (ativo/novo), redefinir senha.
- footer → Faixa de marca — UButtons: Atendimento · Conheça o ME (ícone+texto) + LinkedIn/Facebook/Instagram (só-ícone).
CONVENÇÕES DO ME (padrões do guide — valem para toda tela)
- Voz e labeling em PT-BR (Glossário do ME), sem UPPERCASE: "Novo X" = cadastro de entidade; "Adicionar X" = item em lista existente.
- Hierarquia de ações: a primária à esquerda do subheader; até 3 ações aparentes + "Mais ações" (overflow); ação destrutiva passa por modal de confirmação.
- Rótulos sempre em PT-BR: se um componente trouxer rótulo default em inglês (ex.: o overflow "Options" do MeButtonBar), sobrescreva-o — o overflow do subheader é "Mais ações".
- Cor primária = me-brand (AZUL da marca). No alvo Nuxt, o Nuxt UI v4 NÃO resolve o nome "me-brand" sozinho e cai no DEFAULT VERDE — por isso, além de `ui.colors.primary: 'me-brand'` no app.config, é preciso definir a paleta `--color-me-brand-50..950` (azul) E mapear `--ui-color-primary-*` para ela (tokens da suite me-foundations / `tokens.me-brand.css`). Header/CTA VERDE = sintoma de me-brand não aplicado (erro) — a barra do header é azul me-brand.
- Status sempre como badge semântico (cor nunca sozinha — combine com rótulo): Pendente/Em análise/Aguardando=warning · Em andamento=info · Aprovado/Concluído=success · Rascunho=neutral · Recusado/Cancelado=error. O rótulo é curto (1–2 palavras); o detalhe vai na descrição/tooltip, não no rótulo.
- Valor monetário: total/financeiro usa "R$ 1.234,56"; preço unitário/de lista usa "BRL 38,90".
- Menu por linha/item no kebab vertical (⋮); seleção em massa vira badge-toggle na filter bar (filtros desabilitados enquanto a seleção está ativa).
- Cabeçalho de TODA tabela (qualquer tela): a célula tem 40px e o rótulo é o gatilho de ordenação — botão ghost neutro na escala md (rótulo 14px semibold em text-muted + ícone de ordenação de 20px à esquerda, gap 6px). Coluna de serviço (checkbox, chevron, ação de linha) tem cabeçalho VAZIO. O rótulo NÃO trunca: é ele que define a largura mínima da coluna.
- Feedback de ação por toast (com desfazer quando fizer sentido); trate sempre os estados vazio, carregando e erro.
- Responsivo: no mobile, o header global vira navbar inferior e o app bar fica compacto (marca "me." + busca + avatar); o menu da sidebar vai para o subheader (não no app bar); o CTA primário vira FAB; e as ações secundárias do subheader rolam horizontalmente.
- Responsivo (widgets/KPIs): no mobile a grade de widgets (até 4 colunas no desktop) vira 1 coluna full-width empilhada e a tela rola verticalmente até a tabela, que preserva uma altura mínima — não vira carrossel horizontal.
- Layout & altura (área de dados): MeTableView/MeListView/MePreview têm header sticky e rolam o próprio corpo — exigem um ANCESTRAL com altura definida (h-full + flex flex-col + min-h-0). O slot #default do MeLayout já rola e já tem padding (p-4 sm:p-6) — não duplique. Grid de itens dentro de aba/seção usa sticky=false (ou recebe altura própria), senão a tabela colapsa a ~0 e nenhuma linha aparece.
- Estado inicial + filter bar: a view inicial deve EXIBIR dados (escopo/filtro default que retorna linhas — não abrir num recorte vazio); mesmo assim trate vazio/carregando/erro. Na filter bar, os controles de filtro (Selects/critérios) e o MeCriterionInput usam o MESMO size (altura igual).
- Header/Subheader (desktop): o header mantém a navegação horizontal + o divisor antes dos transversais (use disable-mobile-layout quando houver muitos itens, senão ele compacta e some o divisor); o MeSubheader tem regiões fixas (esquerda CTA · centro ações · direita busca/visões) — não empilhe além de ~3 ações + "Mais ações", senão o centro abre gaps.
- "Mais ações": ordene por frequência de uso e separe a ação destrutiva por um divisor.
- Ação em massa rotula a contagem do alvo ("Excluir 5 itens", não "Excluir seleção"); a barra de seleção mostra "N selecionados".
- Tabela com seleção: o checkbox do cabeçalho fica em estado indeterminado quando a seleção é parcial (nem todas as linhas).
- Filtros — dois recursos distintos: Filter Bar = filtros persistentes/rápidos sempre visíveis (chips/critérios); Filter Search = busca livre por texto (overlay). Não os confunda. A sidebar também faceta por tipo/escopo: selecionar uma faceta (ex.: Transações › Cotações) filtra a lista para aquele recorte.
- Quando há ciclo de status (ex.: documento), as ações do subheader mudam conforme o status/fase atual.
- Breadcrumb do documento (breadcrumb + "abrir em outra janela" + fechar) é chrome de MODAL; a página única (full-page) não tem essa barra — navega pelo header/sidebar do app.
- Fichas de entidade (Fornecedor/Produto) usam template dedicado (forehead + abas ancoradas + seções numeradas), sem o padrão de "locais" (Entrega/Faturamento/Cobrança) dos documentos transacionais.
- Transversais (Mensagens/Genius/Carrinho) abrem como painel lateral, com o cabeçalho do painel alinhado ao header do app (mesma altura); ao expandir, ocupam a tela inteira.
DIRETRIZES
- Entregue a TELA REAL montada 1:1 com o padrão ME (anatomia, componentes e comportamento) — completa e funcional, não descrição/esboço/esqueleto; inclua dados de exemplo realistas em PT-BR.
- Respeite a anatomia e a ORDEM das zonas do PADRÃO ME; só monte as zonas listadas.
- CONSISTÊNCIA entre telas do mesmo tipo: se o projeto JÁ tem uma tela deste tipo (ex.: outro dashboard/index/documento), SIGA-A como referência — mesmo layout, mesmos componentes, mesmos tokens e as mesmas decisões já tomadas. NÃO remonte do zero nem reinvente a estrutura; troque só o conteúdo. Consistência com a tela existente vence preferência pontual.
- Trate os estados relevantes: vazio, carregando, erro e (quando houver seleção) o estado selecionado.
- Garanta responsividade desktop/tablet/mobile e acessibilidade (foco visível, rótulos, contraste, navegação por teclado).
- Use os blocks/componentes prontos do EletroDS antes de remontar qualquer coisa; só caia para Vue puro quando não existir equivalente.
RESTRIÇÕES
Respeite o ALVO (STACK) acima — hierarquia de componentes e tokens — sem recriar o que já existe; mantenha o labeling e a voz em PT-BR conforme o Glossário do ME.
Todas as zonas são COMPOSÁVEIS (áreas → colunas → peças) — nada cravado; use componentes reais, custom só p/ texto puro..
Fonte Roboto (fonte do produto ME), não a fonte do guide..
Um CTA primário por e-mail (Concluir cadastro / Cadastrar / Acessar perfil / Recuperar senha) = UButton real..
Header de marca: logo por toggle (imagem = upload OU "me." padrão) + slot composável por toggle. Footer de marca = UButtons ghost (2 ícone+texto à esquerda, 3 só-ícone à direita)..
PRONTO QUANDO
- 3 zonas composáveis (áreas → peças reais); header com logo/slot por toggle.
- Peças reais: UCard (tópicos) · UButton (CTA/footer) · UIcon. Custom só p/ texto.
- Um CTA primário; fonte Roboto.
- Componentes EletroDS reais (blocks/Me* antes de remontar) — nada recriado do zero que já exista.
- Foundations: só classe Tailwind + var(--ui-*) — sem HEX, valor fora de escala ou style inline fixo; dark mode pelos tokens.
- A tela RENDERIZA de fato (valide o render, não só o build — build verde ≠ tela correta): listas/tabelas exibem linhas com rolagem interna e o corpo NÃO colapsa a zero; no desktop o header mostra o divisor antes dos transversais e os filtros/critérios ficam na mesma altura.
SAÍDA ESPERADA
A TELA REAL, montada e funcional 1:1 com o PADRÃO ME — pronta para rodar e visualizar (um componente Vue (Composition API) usando os componentes REAIS do EletroDS/Nuxt UI, nada recriado do zero), com dados de exemplo realistas em PT-BR e os estados tratados. NÃO entregue descrição, esboço, pseudo-código ou esqueleto — entregue a tela montada. Feche com um resumo de 1–2 linhas do que a tela entrega ao usuário.Template contextualizado por cenário, TODO composável (áreas → peças reais). Header = logo (toggle) + slot; Conteúdo = título/texto (custom) + UCard (tópicos) + UButton (CTA); Footer = UButtons. Fonte Roboto. Detalhe: docs/email-builder.md.
Documentos
Pedido
Gabarito: Estrutura de Documento
Documento de compra confirmado enviado ao fornecedor. View full-page com identificação, informações gerais, históricos e itens com aprovação por linha.
Anatomia
Cotação (RFQ)
Gabarito: Estrutura de Documento
Processo de negociação com fornecedores. Não é um documento: são SEIS — RFQ, RFP e RFI, cada um com a sua rodada de negociação — que convivem no mesmo rail de fases, cada um com abas, barra de ações e dados próprios.
Anatomia
Requisição
Gabarito: Estrutura de Documento
Pedido interno de uma necessidade de compra, sujeito a aprovação, que dá origem a pedidos. View full-page com itens e os pedidos gerados.
Anatomia
Pré-pedido
Gabarito: Estrutura de Documento
Documento intermediário entre requisição/cotação e o pedido, sujeito a aprovação. View full-page enxuta (Informações gerais · Históricos).
Anatomia
Leilão
Gabarito: Estrutura de Documento
Disputa de preços por lances entre fornecedores, com janela de tempo. Abre em modal com rail, alternador de visão e as abas Lotes · Lances · Resultado.
Anatomia
Contrato
Gabarito: Estrutura de Documento
Acordo de fornecimento com vigência, cláusulas e saldo. View full-page com Dados · Cláusulas · Aditivos · Históricos · Anexos.
Anatomia
Nota Fiscal
Gabarito: Estrutura de Documento
Documento fiscal de entrada vinculado ao pedido, sujeito a conferência e aprovação. View full-page com Informações gerais · Itens · Históricos.
Anatomia
Documento de fornecedor
Gabarito: Estrutura de Documento
Ficha de um fornecedor — Forehead (logo, razão social, status, marketplace) + abas de ancoragem sobre as seções cadastrais.
Anatomia
Documento de produto
Gabarito: Estrutura de Documento
Ficha de um produto — Forehead (imagem, tipo, descrição, carrinho) + abas de especificação.
Anatomia
Dicas para errar menos
- Sempre parta de um gabarito — não peça uma tela "do zero"; copie o prompt da tela mais próxima.
- Preencha os
{placeholders}— o que está entre chaves (colunas, status, KPIs…) é o que mais muda a saída. - Alimente o contexto — o prompt já manda usar os blocks/componentes do EletroDS → Nuxt UI, tokens e nada de HEX cru; mantenha isso.
- Use o vocabulário do Glossário — "Subheader", "Forehead", "Novo X" vs "Adicionar X".
- Escreva como o ME escreve — ver Voz e conteúdo para rótulos e mensagens.
- Revise contra o template — compare a saída da IA com a tela de referência antes do handoff.