frontend Menyor
Tudo o que for construído para este usuário deve parecer e se comportar como o aplicativo Menyor Nigéria
(~/Projects/menyor-nigeria), que foi construído pixel a pixel a partir do Figma deles e depois
estendido para cada tela. Este skill é esse sistema. Siga-o exatamente, a menos que o
usuário diga o contrário na solicitação atual.
Precedência: as palavras do usuário nesta solicitação → um Figma/design que eles anexarem → este skill → seu próprio julgamento.
Quando um novo Figma chegar, ele vence para aquele trabalho: meça-o (veja references/verification.md)
e anote quaisquer desvios deste skill em seu relatório.
Leia antes de começar
| Necessidade | Arquivo |
|---|---|
| Tokens exatos, escala tipográfica, espaçamento, breakpoints, regras de copy e acessibilidade | references/design-system.md |
| Marcação e nomes de classe para cada componente (botões, pills, cards, gavetas, timeline…) | references/components.md |
| Presets de movimento e como cada efeito é construído | references/motion.md |
| Como combinar com um Figma, captura de tela, auditoria e relatório | references/verification.md |
| Armadilhas já encontradas (Next 16, Turbopack, contextos de empilhamento, portais) | references/gotchas.md |
| A stylesheet real, logotipo, arquivo de movimento e componentes principais para copiar | assets/ |
| Captura de tela, lado a lado, scripts de medição e auditoria | scripts/ |
Para um novo projeto, comece a partir de assets/globals.css, assets/motion.ts e dos componentes em
assets/components/ em vez de derivá-los novamente.
O sistema de relance
Fontes (apenas estas duas):
- Cormorant Garamond para todos os títulos, peso 700 com
letter-spacing: -0.02em. É o que o Figma usa, embora o briefing original dissesse 500/600. - DM Sans 400/500/600 para todo o resto, incluindo inputs, botões e selects, com
font-variation-settings: "opsz" 33para corresponder ao corte mais justo do Figma. - Carregue ambas com
next/font/google,display: 'swap', pré-carregadas. - O logotipo é um SVG, nunca uma fonte.
Cores (apenas estas):
| Token | Hex | Uso |
|---|---|---|
--brand-blue | #006BA6 | botões, links, títulos, faixa azul, rodapé |
--brand-blue-hover | #005A8C | hover |
--brand-blue-tint | #E6F0F6 | badges, linhas selecionadas |
--bg | #EBEAEA | página, linhas dentro de cards |
--surface | #FFFFFF | cards, inputs, gavetas |
--ink | #111111 | texto |
--ink-muted | #5F6368 | legendas, texto de ajuda |
--success | #1E8E3E | ícones e pontos "Confirmado" apenas, nunca texto do corpo (tem contraste 4.2:1 sobre branco) |
--error | #C62828 | erros |
--on-blue | #FFFFFF | texto sobre azul; divisores a 60% |
Os valores hexadecimais vivem apenas em :root e na configuração BRAND.colors (e-mails e PDFs os leem).
Divisores e scrims são derivados com color-mix(in srgb, var(--ink) 12%, transparent).
Forma:
- Cada botão, aba, input, select, caixa de pesquisa e controle de viagem é uma pill.
- Cards grandes têm raio de 48px, cards 24px, imagens 24px e linhas 16px.
- Controles de contorno e inputs têm uma borda azul de 1px.
- Cards não têm bordas e nada tem sombra.
- A hierarquia vem de superfícies cinza vs. brancas.
Escala tipográfica (desktop → telefone):
| Elemento | Tamanho |
|---|---|
| Hero | 110px / 112px line-height → 48px |
Título de seção e página (.display) | 64px / 1.22 → 40px |
| Títulos de card | 30px |
| Linhas de listagem | 24px |
| Corpo | 16px |
| Texto de ajuda | 14px |
| Badges | 13px |
| Preços | 22px, peso 600, algarismos tabulares |
Sobrancelhas (eyebrows) | DM Sans 16px, MAIÚSCULO, azul |
Layout:
- Container máximo 1480px, gutters 40px (24px em telefones).
- Cabeçalho 96px (72px em telefones), fixo na página cinza com um divisor de 1px quando rolado.
- Seções com cerca de 160px de distância no desktop e 80px em telefones.
- Breakpoints: 1360 (pill de viagem compacta), 1180 (navegação vira menu), 960 (uma coluna), 640 (telefone).
Copy:
- Títulos de exibição em Title Case ("Everything For Your Trip, In One Place").
- Texto de UI em sentence case ("Add to my trip").
- Toda a copy vive em
src/content/*.ts. Nunca codifique strings diretamente nos componentes. - Valores da marca (e-mail, telefone, WhatsApp, nome legal, redes sociais) vêm de
BRAND. - Preços sempre passam pelo helper de moeda (NGN padrão, lembrado).
- Nunca invente reviews, avaliações, estatísticas ou detalhes de contato.
- Placeholders permanecem visivelmente
[ENTRE COLCHETES].
Inegociáveis
- Apenas as duas fontes e as cores acima. Execute
scripts/audits.mjs(paletteAudit) em cada nova tela. - Sem sombras, sem bordas de card, sem gradientes. A única exceção é um gradiente fotográfico sutil, e apenas se o texto precisar dele.
- Todo controle é uma pill com contorno azul de 1px ou preenchimento azul sólido. Foco mostra um anel de 2px branco + 2px azul.
- Um único arquivo compartilhado de presets de movimento. Anime apenas
transformeopacity; altura de FAQ e booking-card são as exceções deliberadas.prefers-reduced-motiondesabilita tudo e mostra o conteúdo de uma vez. - Acessível por padrão:
- Contraste WCAG AA.
- Controles rotulados.
- Gavetas e modais prendem o foco, fecham com Escape, retornam o foco ao botão que os abriu e renderizam em um portal no
document.body. - Toggles usam
aria-pressed, e escolhas em pill usamrole="radio"comaria-checked. - Placeholders apenas visuais são
aria-hidden.
- Copy em arquivos de conteúdo e valores da marca de
BRAND. Imagens precisam de texto alternativo real, e seus caminhos vivem em arquivos de conteúdo. - Responsivo em 390, 768 e 1440px sem rolagem horizontal:
- Telefones recebem carrosséis de encaixe com uma prévia do próximo card.
- Filtros e formulários de reserva vão para folhas inferiores.
- A ação principal vai em uma barra inferior fixa.
- Gavetas se tornam folhas inferiores.
- Verifique antes de relatar:
- Capture tela em 1440 e 390.
- Compare com o design lado a lado.
- Execute as auditorias de paleta e contraste e axe.
- Execute Lighthouse mobile em uma build de produção: Performance pelo menos 85, Acessibilidade pelo menos 95, CLS 0.
- Relate as diferenças honestamente.
Construindo uma nova tela: a ordem
- Coloque a copy em um arquivo de conteúdo primeiro.
- Componha a tela a partir de componentes existentes em
references/components.md.- Estrutura típica: um
page-headcentralizado (sobrancelha + linhas.display+ introdução), depois blocos brancoslarge-card/step-card/checkout-cardna página cinza. - Listas vão em linhas cinza
update-row/listing-rowdentro de cards brancos.
- Estrutura típica: um
- Apenas se nada se encaixar, adicione uma nova classe na seção correta de
globals.css, construída a partir de tokens. Sem Tailwind e sem cores inline. - Conecte os presets de movimento (
Reveal, elevação de linhaSectionHeading, hover lift). - Verifique (
references/verification.md), depois relate com capturas de tela.