Menyor frontend
Todo lo construido para este usuario debe verse y comportarse como la aplicación de Menyor Nigeria
(~/Projects/menyor-nigeria), que fue construida pixel-exacta a partir de su Figma y luego
extendida a cada pantalla. Este skill es ese sistema. Síguelo exactamente a menos que el
usuario indique lo contrario en la solicitud actual.
Precedencia: las palabras del usuario en esta solicitud → un Figma/diseño que adjunte → este skill → tu propio criterio.
Cuando llegue un nuevo Figma, ese gana para ese trabajo: mídelo (consulta references/verification.md)
y anota cualquier desviación de este skill en tu informe.
Lee antes de empezar
| Necesidad | Archivo |
|---|---|
| Tokens exactos, escala tipográfica, espaciado, breakpoints, reglas de copy y accesibilidad | references/design-system.md |
| Marcado y nombres de clase para cada componente (botones, píldoras, tarjetas, drawers, timeline…) | references/components.md |
| Presets de animación y cómo se construye cada efecto | references/motion.md |
| Cómo emparejar un Figma, captura de pantalla, auditar e informar | references/verification.md |
| Errores ya encontrados (Next 16, Turbopack, contextos de apilamiento, portales) | references/gotchas.md |
| La hoja de estilos real, el logo, el archivo de animación y los componentes principales para copiar | assets/ |
| Scripts de captura de pantalla, comparación lado a lado, medición y auditoría | scripts/ |
Para un proyecto nuevo, comienza desde assets/globals.css, assets/motion.ts y los componentes en
assets/components/ en lugar de derivarlos nuevamente.
El sistema de un vistazo
Fuentes (solo estas dos):
- Cormorant Garamond para cada encabezado, peso 700 con
letter-spacing: -0.02em. Eso es lo que usa el Figma, aunque el resumen original indicaba 500/600. - DM Sans 400/500/600 para todo lo demás, incluyendo inputs, botones y selects, con
font-variation-settings: "opsz" 33para que coincida con el corte más ajustado del Figma. - Carga ambas con
next/font/google,display: 'swap', precargadas. - El logo es un SVG, nunca una fuente.
Colores (solo estos):
| Token | Hex | Uso |
|---|---|---|
--brand-blue | #006BA6 | botones, enlaces, encabezados, banda azul, pie de página |
--brand-blue-hover | #005A8C | hover |
--brand-blue-tint | #E6F0F6 | insignias, filas seleccionadas |
--bg | #EBEAEA | página, filas dentro de tarjetas |
--surface | #FFFFFF | tarjetas, inputs, drawers |
--ink | #111111 | texto |
--ink-muted | #5F6368 | leyendas, texto de ayuda |
--success | #1E8E3E | solo iconos y puntos "Confirmado", nunca texto del cuerpo (tiene 4.2:1 sobre blanco) |
--error | #C62828 | errores |
--on-blue | #FFFFFF | texto sobre azul; divisores al 60% |
Los valores hex viven solo en :root y en la configuración BRAND.colors (correos y PDFs lo leen).
Los divisores y cortinas se derivan con color-mix(in srgb, var(--ink) 12%, transparent).
Forma:
- Cada botón, pestaña, input, select, cuadro de búsqueda y control de viaje es una píldora.
- Las tarjetas grandes tienen un radio de 48px, las tarjetas 24px, las imágenes 24px y las filas 16px.
- Los controles de contorno y los inputs tienen un borde azul de 1px.
- Las tarjetas no tienen bordes y nada tiene sombra.
- La jerarquía proviene de superficies grises vs blancas.
Escala tipográfica (escritorio → teléfono):
| Elemento | Tamaño |
|---|---|
| Hero | 110px / 112px interlineado → 48px |
Título de sección y página (.display) | 64px / 1.22 → 40px |
| Títulos de tarjeta | 30px |
| Filas de listados | 24px |
| Cuerpo | 16px |
| Texto de ayuda | 14px |
| Insignias | 13px |
| Precios | 22px, peso 600, cifras tabulares |
| Cejas | DM Sans 16px, MAYÚSCULAS, azul |
Diseño:
- Contenedor máximo 1480px, márgenes internos 40px (24px en teléfonos).
- Cabecera 96px (72px en teléfonos), sticky sobre la página gris con un divisor de 1px al hacer scroll.
- Secciones separadas unos 160px en escritorio y 80px en teléfonos.
- Breakpoints: 1360 (píldora de viaje compacta), 1180 (navegación se convierte en menú), 960 (una columna), 640 (teléfono).
Copy:
- Los titulares display en Title Case ("Everything For Your Trip, In One Place").
- El texto de la interfaz en sentence case ("Add to my trip").
- Todo el copy vive en
src/content/*.ts. Nunca codifiques cadenas directamente en los componentes. - Los valores de marca (correo, teléfono, WhatsApp, nombre legal, redes sociales) provienen de
BRAND. - Los precios siempre pasan por el helper de moneda (NGN por defecto, recordado).
- Nunca inventes reseñas, valoraciones, estadísticas o datos de contacto.
- Los placeholders se mantienen visiblemente
[CORCHETES].
No negociables
- Solo las dos fuentes y los colores anteriores. Ejecuta
scripts/audits.mjs(paletteAudit) en cada nueva pantalla. - Sin sombras, sin bordes de tarjeta, sin degradados. La única excepción es un degradado fotográfico sutil, y solo si el texto lo necesita.
- Cada control es una píldora con un contorno azul de 1px o un relleno azul sólido. El foco muestra un anillo de 2px blanco + 2px azul.
- Un archivo de presets de animación compartido. Anima solo
transformyopacity; la altura de FAQ y tarjetas de reserva son las excepciones deliberadas.prefers-reduced-motiondesactiva todo y muestra el contenido de inmediato. - Accesible por defecto:
- Contraste WCAG AA.
- Controles etiquetados.
- Los drawers y modales atrapan el foco, se cierran con Escape, devuelven el foco al botón que los abrió y se renderizan en un portal en
document.body. - Los toggles usan
aria-pressed, y las opciones de píldora usanrole="radio"conaria-checked. - Los placeholders solo visuales son
aria-hidden.
- Copy en archivos de contenido y valores de marca desde
BRAND. Las imágenes necesitan texto alternativo real, y sus rutas viven en archivos de contenido. - Responsive a 390, 768 y 1440px sin scroll horizontal:
- Los teléfonos obtienen carruseles snap con un adelanto de la siguiente tarjeta.
- Los filtros y formularios de reserva se mueven a paneles inferiores.
- La acción principal va en una barra inferior sticky.
- Los drawers se convierten en paneles inferiores.
- Verifica antes de informar:
- Captura de pantalla a 1440 y 390.
- Compara con el diseño lado a lado.
- Ejecuta las auditorías de paleta y contraste y axe.
- Ejecuta Lighthouse móvil en una compilación de producción: Rendimiento al menos 85, Accesibilidad al menos 95, CLS 0.
- Informa las diferencias honestamente.
Construyendo una nueva pantalla: el orden
- Coloca el copy en un archivo de contenido primero.
- Cómponlo a partir de componentes existentes en
references/components.md.- Estructura típica: un
page-headcentrado (ceja + líneas.display+ introducción), luego bloques blancoslarge-card/step-card/checkout-cardsobre la página gris. - Las listas van en filas grises
update-row/listing-rowdentro de tarjetas blancas.
- Estructura típica: un
- Solo si nada encaja, añade una nueva clase a la sección correcta de
globals.css, construida a partir de tokens. Sin Tailwind y sin colores en línea. - Conecta los presets de animación (
Reveal, elevación de líneaSectionHeading, hover lift). - Verifica (
references/verification.md), luego informa con capturas de pantalla.