Frontend Menyor
Tout ce qui est construit pour cet utilisateur doit ressembler et se comporter comme l'application Menyor Nigeria
(~/Projects/menyor-nigeria), qui a été construite pixel par pixel à partir de leur Figma puis étendue à chaque écran.
Ce skill est ce système. Suivez-le à la lettre sauf si l'utilisateur dit explicitement le contraire dans la demande actuelle.
Priorité : les mots de l'utilisateur dans cette demande → une Figma/design joint → ce skill → votre propre goût.
Lorsqu'une nouvelle Figma arrive, elle l'emporte pour ce travail : mesurez-la (voir references/verification.md)
et notez les écarts par rapport à ce skill dans votre rapport.
À lire avant de commencer
| Besoin | Fichier |
|---|---|
| Tokens exacts, échelle typographique, espacements, points de rupture, règles de copy et d'accessibilité | references/design-system.md |
| Balisage et noms de classes pour chaque composant (boutons, pastilles, cartes, tiroirs, timeline…) | references/components.md |
| Presets d'animation et construction de chaque effet | references/motion.md |
| Comment faire correspondre une Figma, une capture d'écran, auditer et rapporter | references/verification.md |
| Pièges déjà rencontrés (Next 16, Turbopack, contextes d'empilement, portails) | references/gotchas.md |
| La feuille de style réelle, le logo, le fichier d'animation et les composants principaux à copier | assets/ |
| Scripts de capture d'écran, comparaison côte à côte, mesure et audit | scripts/ |
Pour un nouveau projet, partez de assets/globals.css, assets/motion.ts et des composants dans
assets/components/ plutôt que de les redériver.
Le système en un coup d'œil
Polices (uniquement ces deux-là) :
- Cormorant Garamond pour chaque titre, poids 700 avec
letter-spacing: -0.02em. C'est ce qu'utilise la Figma, bien que le brief original indiquait 500/600. - DM Sans 400/500/600 pour tout le reste, y compris les champs de saisie, boutons et listes déroulantes, avec
font-variation-settings: "opsz" 33pour correspondre à la découpe plus serrée de la Figma. - Chargez les deux avec
next/font/google,display: 'swap', préchargés. - Le logo est un SVG, jamais une police.
Couleurs (uniquement celles-ci) :
| Token | Hex | Utilisation |
|---|---|---|
--brand-blue | #006BA6 | boutons, liens, titres, bande bleue, pied de page |
--brand-blue-hover | #005A8C | survol |
--brand-blue-tint | #E6F0F6 | badges, lignes sélectionnées |
--bg | #EBEAEA | page, lignes dans les cartes |
--surface | #FFFFFF | cartes, champs de saisie, tiroirs |
--ink | #111111 | texte |
--ink-muted | #5F6368 | légendes, texte d'aide |
--success | #1E8E3E | icônes et points "Confirmé" uniquement, jamais de texte courant (rapport de contraste 4,2:1 sur blanc) |
--error | #C62828 | erreurs |
--on-blue | #FFFFFF | texte sur fond bleu ; séparateurs à 60 % |
Les valeurs hexadécimales vivent uniquement dans :root et dans la config BRAND.colors (les e-mails et PDF les lisent).
Les séparateurs et les voiles sont dérivés avec color-mix(in srgb, var(--ink) 12%, transparent).
Forme :
- Chaque bouton, onglet, champ de saisie, liste déroulante, champ de recherche et contrôle de voyage est une pilule.
- Les grandes cartes ont un rayon de 48 px, les cartes 24 px, les images 24 px et les lignes 16 px.
- Les contrôles et champs encadrés ont une bordure bleue de 1 px.
- Les cartes n'ont pas de bordure et rien n'a d'ombre.
- La hiérarchie provient des surfaces grises par rapport aux surfaces blanches.
Échelle typographique (desktop → téléphone) :
| Élément | Taille |
|---|---|
| Hero | 110 px / interligne 112 px → 48 px |
Titre de section et de page (.display) | 64 px / 1,22 → 40 px |
| Titres de cartes | 30 px |
| Lignes de liste | 24 px |
| Corps de texte | 16 px |
| Texte d'aide | 14 px |
| Badges | 13 px |
| Prix | 22 px, poids 600, chiffres tabulaires |
| Sourcils | DM Sans 16 px, MAJUSCULES, bleu |
Disposition :
- Conteneur max 1480 px, gouttières 40 px (24 px sur téléphone).
- En-tête 96 px (72 px sur téléphone), collant sur la page grise avec un séparateur de 1 px après défilement.
- Sections espacées d'environ 160 px sur desktop et 80 px sur téléphone.
- Points de rupture : 1360 (pastille de voyage compacte), 1180 (navigation devient menu), 960 (une colonne), 640 (téléphone).
Copy :
- Les titres d'affichage en casse titre ("Everything For Your Trip, In One Place").
- Le texte d'interface en casse normale ("Add to my trip").
- Toute la copy vit dans
src/content/*.ts. Ne codez jamais en dur des chaînes dans les composants. - Les valeurs de marque (e-mail, téléphone, WhatsApp, nom légal, réseaux sociaux) proviennent de
BRAND. - Les prix passent toujours par l'utilitaire de devise (NGN par défaut, mémorisée).
- N'inventez jamais d'avis, notes, statistiques ou coordonnées.
- Les espaces réservés restent visiblement [ENTRE CROCHETS].
Non-négociables
- Uniquement les deux polices et les couleurs ci-dessus. Exécutez
scripts/audits.mjs(paletteAudit) sur chaque nouvel écran. - Pas d'ombres, pas de bordures de cartes, pas de dégradés. La seule exception est un léger dégradé de photo, et seulement si le texte en a besoin.
- Chaque contrôle est une pilule avec un contour bleu de 1 px ou un remplissage bleu uni. Le focus affiche un anneau blanc de 2 px + bleu de 2 px.
- Un seul fichier de presets d'animation partagé. Animer uniquement
transformetopacity; la hauteur de la FAQ et des cartes de réservation sont les exceptions délibérées.prefers-reduced-motiondésactive tout et affiche le contenu d'un coup. - Accessible par défaut :
- Contraste WCAG AA.
- Contrôles étiquetés.
- Les tiroirs et modales piègent le focus, se ferment avec Échap, rendent le focus au bouton qui les a ouverts, et s'affichent dans un portail sur
document.body. - Les bascules utilisent
aria-pressed, et les choix en pilule utilisentrole="radio"avecaria-checked. - Les espaces réservés visuels uniquement sont
aria-hidden.
- Copy dans les fichiers de contenu et valeurs de marque depuis
BRAND. Les images ont besoin d'un texte alternatif réel, et leurs chemins vivent dans les fichiers de contenu. - Responsive à 390, 768 et 1440 px sans défilement horizontal :
- Les téléphones obtiennent des carrousels à accrochage avec un aperçu de la carte suivante.
- Les filtres et formulaires de réservation se déplacent dans des feuilles inférieures.
- L'action principale se trouve dans une barre inférieure collante.
- Les tiroirs deviennent des feuilles inférieures.
- Vérifiez avant de rapporter :
- Capture d'écran à 1440 et 390.
- Comparez avec le design côte à côte.
- Exécutez les audits de palette et de contraste et axe.
- Exécutez Lighthouse mobile sur une build de production : Performance au moins 85, Accessibilité au moins 95, CLS 0.
- Rapportez honnêtement les différences.
Construire un nouvel écran : l'ordre
- Mettez d'abord la copy dans un fichier de contenu.
- Composez-le à partir des composants existants dans
references/components.md.- Structure typique : un
page-headcentré (sourcil + lignes.display+ introduction), puis des blocslarge-card/step-card/checkout-cardblancs sur la page grise. - Les listes vont dans des lignes
update-row/listing-rowgrises à l'intérieur des cartes blanches.
- Structure typique : un
- Seulement si rien ne correspond, ajoutez une nouvelle classe dans la section appropriée de
globals.css, construite à partir des tokens. Pas de Tailwind et pas de couleurs en ligne. - Raccordez les presets d'animation (
Reveal,SectionHeadingligne ascendante, soulèvement au survol). - Vérifiez (
references/verification.md), puis rapportez avec des captures d'écran.