Guide UI
Objet
Référence UI faisant autorité pour Pulse my Promo, destinée aux humains et aux assistants IA. Le dashboard admin est la référence canonique : toute nouvelle page ou tout refactor s'aligne sur les valeurs ci-dessous. Les tokens vivent dans app/mypromo/app/app.config.ts et app/mypromo/app/assets/css/main.css ; ne pas dupliquer de valeurs codées en dur qui les contredisent.
Shell / layout
Source de référence : app/mypromo/app/layouts/admin.vue.
- Header collant :
sticky top-0 z-50 border-b border-default bg-default/95 backdrop-blur, containerw-full max-w-none px-4 sm:px-6 lg:px-8. - Contrôles en haut à droite, dans cet ordre :
Mentions légales(UButtonghost neutral size="sm") →ULocaleSelect(size="sm",class="w-28", locales[fr, en]) → menu utilisateur / déconnexion (NavSessionManager). - CGU gate : modale montée au niveau du layout, pilotée par
useCguGate(). - Sidebar :
collapsible resizable— pas seulement redimensionnable, elle se replie aussi en rail d'icônes via le boutonUDashboardSidebarCollapse(ancré en absolute sur le bord du panneau).min-size 16/default-size 20/max-size 28,border-e border-default bg-muted/25. L'en-tête de sidebar est une simple barreh-14 border-b border-default(sans libellé texte) qui ne porte que le bouton de repli et aligne la sidebar sur la barre de navigation du panneau. À l'état replié (collapsed), la navigation passe en icônes seules via la prop:compactdeNavDashboardSidebarNav: les titres de section deviennentsr-onlyet chaque bouton affiche uniquement son icône, avectitle/aria-labelportant le libellé pour l'accessibilité. - Shell partagée : ce shell (header du haut + sidebar sans en-tête texte + pas de footer + collapse en rail d'icônes) est identique sur les trois espaces (
admin,distributeur,industriel). La seule différence inter-espaces est leCartPreviewajouté dans le slot#rightde la navbar du panel, côté industriel. - Navbar du panel :
h-14 border-b border-default, titretext-sm font-semibold text-highlighted, descriptiontext-xs text-dimmed. - Wrapper de contenu de page (div racine de chaque page) :
space-y-6 px-4 py-8 sm:px-6 sm:py-10 lg:px-8. Largeur pleine du panel, pas demax-wsur le contenu.
En-tête de page
Utiliser <PageHeader> (générique) ou <AdminPageHeader> (preset admin). Structure : fil d'Ariane → titre → description → actions.
- Container :
flex flex-wrap items-start justify-between gap-4. - Fil d'Ariane (
UBreadcrumb) :text-[12px], linktext-stone-500 hover:text-stone-900, separatortext-stone-300. - Titre
h1:mt-1 text-2xl font-semibold tracking-tight text-pulse-800. - Description :
mt-1 text-sm text-stone-500 max-w-2xl. - Actions : slot
#actions, à droite du titre, boutonssize="md".
<PageHeader
:title="t('...')"
:description="t('...')"
:root="{ label: 'Admin', to: '/admin' }"
:breadcrumbs="[{ label: t('...') }]"
>
<template #actions>
<UButton color="neutral" variant="outline" icon="i-lucide-refresh-cw">{{ t('common.actions.refresh') }}</UButton>
</template>
</PageHeader>
Couleurs
| Rôle | Couleur | Usage |
|---|---|---|
| primary | pulse (teal) | CTA, booking, activation — jamais décoratif |
| secondary | indigo | vues distributeur / admin, contrepoint |
| success | teal | confirmation, KYB validé |
| info | blue | notifications neutres |
| warning | amber | états en attente, KYB en attente |
| error | red | erreurs, destructif |
| neutral | stone | surfaces, textes, base chaude |
Titres de page : text-pulse-800. La couleur primaire porte le sens « agir ici » — jamais décorative.
Typographie
Police : Public Sans.
| Niveau | Classes |
|---|---|
| Titre de page | text-2xl font-semibold tracking-tight text-pulse-800 |
| Titre de section / table | text-sm font-semibold text-highlighted |
| Corps | text-sm |
| Méta / secondaire | text-xs text-dimmed |
| Texte d'aide / explicatif | text-xs text-toned |
dimmed pour ce qu'on survole, toned pour ce qu'on lit. text-dimmed est un gris clair
(contraste ≈ 2,6 sur fond blanc) : il convient à une méta-donnée qu'on balaie du regard — un
horodatage, un compteur, un libellé de champ redondant — mais il est sous le seuil WCAG AA
(4,5 pour du texte courant). Dès qu'une phrase doit réellement être lue pour comprendre l'écran
(mode d'emploi d'un graphique, règle métier qui explique un filtrage), utiliser text-toned
(contraste ≈ 7,6, conforme AA et AAA). La taille reste text-xs : c'est la couleur qui porte la
hiérarchie, pas la taille.
Avis / notifications
- Feedback de page (persistant) :
<UAlert variant="subtle" :color :title>, placé juste sous le PageHeader. Couleur sémantique (success/error/warning). - Confirmations transitoires :
useToast(thèmeneutral, icône colorée porteuse du sens).
Tables
- Base :
<AkDataList>(de@aidalinfo/nuxt-ui-kit), modeserverviauseServerAdminList(recherche / pagination / tri / sync URL) ou modeclient. - Titre : via le slot
#headerd'AkDataList, avec<AppDataListHeader :title>(titretext-sm font-semibold text-highlighted). - Toute nouvelle table utilise
AkDataList.UTable/TableTemplaterestent uniquement sur le legacy déjà en place.
<AkDataList :data="rows" :columns="columns" mode="server">
<template #header>
<AppDataListHeader :title="t('...')" />
</template>
</AkDataList>
Cartes de section (boxes)
- Pour regrouper du contenu non tabellaire sous un en-tête titré (formulaires, panneaux de détail…), utiliser
<AppSectionCard>plutôt qu'un<UCard>+#headerfait main. - Contrat : prop
title(obligatoire),description?, slot#actions(actions à droite de l'en-tête), slot par défaut (corps). - Le titre reprend le style de section (
text-sm font-semibold text-highlighted) ; l'en-tête gris et le contour arrondi proviennent des tokensUCard(app.config.ts). - Les boutons de ces cartes (en-tête
#actionscomme corps) utilisentsize="sm". - Hors périmètre : tables (voir
AkDataList), mini-cartes de métriques, cartes à en-tête visuel/image.
<AppSectionCard :title="t('...')" :description="t('...')">
<template #actions>
<UButton size="sm" color="neutral" variant="outline">…</UButton>
</template>
<!-- contenu -->
</AppSectionCard>
Boutons
- Taille par défaut
md. - CTA principal :
solid primary(seule élévation colorée). - Actions secondaires :
neutralenoutline/soft/ghostselon le niveau. - Navigation / actions discrètes :
size="sm" variant="ghost".