Keep/_bmad-output/planning-artifacts/DESIGN-WIREFRAMES.md
sepehr ddb67ba9e5 fix: unify theme system - fix theme switching persistence
- Unified localStorage key to 'theme-preference' across all components
- Fixed header.tsx using wrong localStorage key ('theme' instead of 'theme-preference')
- Added localStorage hybrid persistence for instant theme changes
- Removed router.refresh() which was causing stale data revert
- Replaced Blue theme with Sepia
- Consolidated auth() calls to prevent race conditions
- Updated UserSettingsData types to include all themes
2026-01-18 22:33:41 +01:00

1181 lines
46 KiB
Markdown

# 🎨 WIREFRAMES - PROJET KEEP
**Date:** 2026-01-17
**Responsable:** John - Product Manager
**Client:** Ramez
**Version:** 1.0
---
## 📋 SOMMAIRE
1. [Page Notebook - Desktop](#1-page-notebook---desktop)
2. [Page Notebook - Mobile](#2-page-notebook---mobile)
3. [Page Admin](#3-page-admin)
4. [Page Profil](#4-page-profil)
5. [Composants UI Réutilisables](#5-composants-ui-réutilisables)
6. [Design System Unified](#6-design-system-unified)
---
## 1. PAGE NOTEBOOK - DESKTOP
### 1.1 Vue d'ensemble
**Dimensions :** 1920x1080 (responsive jusqu'à 1280x720)
**Layout :** 3 colonnes (Sidebar gauche + Contenu central + (optionnel) Sidebar droite)
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ HEADER GLOBAL (64px de hauteur) │
│ [LOGO] [RECHERCHE LARGEUR 384px] [NOTIFS] [AVATAR] │
├──────────────┬──────────────────────────────────────────────────────────────┤
│ │ │
│ SIDEBAR │ CONTENU PRINCIPAL │
│ GAUCHE │ (Masonry Grid - 3 colonnes) │
│ (256px) │ │
│ │ │
│ [ICÔNE │ ┌────────┐ ┌────────┐ ┌────────┐ │
│ NOTEBOOK] │ │CARTE 1│ │CARTE 2│ │CARTE 3│ │
│ │ │Image │ │Image │ │Image │ │
│ [PERSONAL] │ │Titre │ │Titre │ │Titre │ │
│ │ │Contenu│ │Contenu│ │Contenu│ │
│ [VOYAGE] ✅ │ │Labels │ │Labels │ │Labels │ │
│ ├─#Hôtels│ └────────┘ └────────┘ └────────┘ │
│ ├─#Vols │ │
│ ├─#Restos │ ┌────────┐ ┌────────┐ ┌────────┐ │
│ └─+[LABEL]│ │CARTE 4│ │CARTE 5│ │CARTE 6│ │
│ │ │Image │ │Image │ │Image │ │
│ [WORK] │ │Titre │ │Titre │ │Titre │ │
│ │ │Contenu│ │Contenu│ │Contenu│ │
│ [IDEAS] │ │Labels │ │Labels │ │Labels │ │
│ │ └────────┘ └────────┘ └────────┘ │
│ ──────────────┤ │
│ SMART VIEWS │ [NOTE CARD AU SURVOL] │
│ │ ┌──────────────────────────────────────────────────┐ │
│ [⭐ FAVS] │ │ [...] [EDITER] │ │
│ [✓ TÂCHES] │ │ ┌─────────────────────────────────────────┐│ │
│ │ │ │ Image Hero (60% hauteur) ││ │
│ │ │ │ ┌─────────────────────────────────┐ ││ │
│ AI SUGGESTIONS│ │ │ │ Titre de la note │ ││ │
│ [💡 2 idées │ │ │ │ ┌─────────────────────────────────┐│ ││ │
│ pour │ │ │ │ │ Contenu de la note (2-3 lignes)││ ││ │
│ Voyage] │ │ │ │ └─────────────────────────────────┘│ ││ │
│ │ │ │ └─────────────────────────────────┘ ││ │
│ │ │ │ [AVATAR] [DATE] │ ││ │
│ │ │ │ 🏷️ #Hôtels 🏷️ #Réservations │ ││ │
│ │ │ └─────────────────────────────────────────┘│ │
│ │ └──────────────────────────────────────────────────┘ │
│ │ │
│ │ [BOUTON FLOTTANT "AJOUTER NOTE" (FAB)] │
│ │ (carrond, icône +, ombre) │
└──────────────┴──────────────────────────────────────────────────────────────┘
```
### 1.2 Spécifications détaillées
#### HEADER GLOBAL
```tsx
<header className="h-16 flex items-center justify-between px-6 border-b bg-background z-20">
{/* Logo */}
<div className="flex items-center gap-3">
<div className="size-8 bg-primary rounded-lg flex items-center justify-center">
<StickyNote2Icon className="text-white" />
</div>
<h1 className="text-xl font-bold tracking-tight">KEEP</h1>
</div>
{/* Recherche */}
<label className="hidden md:flex w-96">
<div className="flex w-full h-10 rounded-xl bg-muted focus-within:ring-2">
<SearchIcon className="muted-foreground ml-4" />
<input
className="flex-1 bg-transparent px-3 text-sm focus:ring-0"
placeholder="Rechercher notes, étiquettes..."
/>
</div>
</label>
{/* Actions droite */}
<div className="flex items-center gap-3">
<Button variant="ghost" size="icon">
<SettingsIcon />
</Button>
<Avatar className="size-10 ring-2 ring-background">
<AvatarImage src={user.avatar} />
<AvatarFallback>{user.initials}</AvatarFallback>
</Avatar>
</div>
</header>
```
#### SIDEBAR GAUCHE (256px)
```tsx
<aside className="w-64 hidden md:flex flex-col border-r bg-background overflow-y-auto">
<div className="p-4 flex flex-col gap-6">
{/* Section Notebooks */}
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between px-3 mb-2">
<h3 className="text-xs font-bold uppercase tracking-wider text-muted-foreground">
Notebooks
</h3>
<Button variant="ghost" size="icon-sm">
<AddIcon className="text-muted-foreground" />
</Button>
</div>
{/* Notebook Personal (inactif) */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<BookIcon className="text-muted-foreground" />
<span>Personal</span>
</Button>
{/* Notebook Voyage (actif - ouvert) */}
<div className="flex flex-col rounded-lg overflow-hidden border-l-4 border-primary bg-primary/5">
<div className="flex items-center justify-between px-3 py-2.5">
<div className="flex items-center gap-3">
<FlightTakeoffIcon className="text-primary" />
<span className="font-bold text-primary">Voyage</span>
</div>
<ChevronDownIcon className="text-primary/60" />
</div>
{/* Labels contextuels imbriqués */}
<div className="flex flex-col pb-2">
<Button variant="ghost" className="justify-start gap-3 pl-10 pr-3 py-1.5">
<LabelIcon className="text-primary/70" />
<span className="text-xs font-medium">#Hôtels <span className="opacity-50">(3)</span></span>
</Button>
<Button variant="ghost" className="justify-start gap-3 pl-10 pr-3 py-1.5">
<LabelIcon className="text-primary/70" />
<span className="text-xs font-medium">#Vols</span>
</Button>
<Button variant="ghost" className="justify-start gap-3 pl-10 pr-3 py-1.5">
<LabelIcon className="text-primary/70" />
<span className="text-xs font-medium">#Restos</span>
</Button>
<Button variant="ghost" className="justify-start gap-2 pl-10 pr-3 py-1.5 text-primary hover:underline">
<AddCircleIcon />
<span className="text-xs font-bold">Labels</span>
</Button>
</div>
</div>
{/* Notebook Work (inactif) */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<WorkIcon className="text-muted-foreground" />
<span>Work Projects</span>
</Button>
</div>
{/* Section Smart Views */}
<div className="flex flex-col gap-2 mt-4">
<h3 className="text-xs font-bold uppercase tracking-wider text-muted-foreground px-3 mb-1">
Smart Views
</h3>
<Button variant="ghost" className="justify-start gap-3 px-3 py-2">
<StarIcon className="text-amber-500" />
<span>Favorites</span>
</Button>
<Button variant="ghost" className="justify-start gap-3 px-3 py-2">
<CheckCircleIcon className="text-emerald-500" />
<span>Tâches</span>
</Button>
</div>
</div>
{/* Footer avec AI Suggestions */}
<div className="mt-auto p-4 border-t">
<div className="rounded-lg border bg-gradient-to-br from-primary/10 to-transparent p-3">
<div className="flex gap-2 items-start">
<AutoAwesomeIcon className="text-primary text-sm mt-0.5" />
<div>
<p className="text-xs font-semibold">AI Suggestions</p>
<p className="text-[10px] leading-relaxed text-muted-foreground">
2 nouvelles suggestions pour "Voyage"
</p>
</div>
</div>
</div>
</div>
</aside>
```
#### GRILLE MASONRY (3 colonnes)
```tsx
<main className="flex-1 overflow-y-auto bg-muted p-6 md:p-10">
<div className="max-w-6xl mx-auto flex flex-col gap-8">
{/* En-tête de page */}
<div className="flex flex-wrap items-center justify-between gap-4">
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<span>Notebooks</span>
<ChevronRightIcon />
<span className="text-primary">Voyage</span>
</div>
<h1 className="text-4xl font-black tracking-tight flex items-center gap-3">
<span className="bg-primary/10 p-2 rounded-xl text-3xl">
✈️
</span>
Voyage
</h1>
</div>
<div className="flex items-center gap-3">
<Button variant="outline" size="sm">
<FilterListIcon />
Filtrer
</Button>
<Button className="shadow-lg">
<AddIcon />
Ajouter Note
</Button>
</div>
</div>
{/* Grille Masonry */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Cartes de notes (voir ci-dessous) */}
{[...notes].map(note => (
<NoteCard key={note.id} note={note} />
))}
</div>
</div>
</main>
```
#### CARTE NOTE (DESKTOP)
```tsx
<Card className="group relative flex flex-col rounded-lg overflow-hidden bg-card shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300 border h-[380px]">
{/* Menu d'action (au survol) */}
<div className="absolute top-4 right-4 z-10 opacity-0 group-hover:opacity-100 transition-opacity">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="bg-background/90 rounded-full p-2">
<MoreHorizIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<PushPinIcon /> Épingler
</DropdownMenuItem>
<DropdownMenuItem>
<FolderOpenIcon /> Déplacer
</DropdownMenuItem>
<DropdownMenuItem>
<BellIcon /> Rappel
</DropdownMenuItem>
<DropdownMenuItem>
<Link2Icon /> Connexions
</DropdownMenuItem>
<DropdownMenuItem>
<PaletteIcon /> Couleur
</DropdownMenuItem>
<DropdownMenuItem>
<Share2Icon /> Partager
</DropdownMenuItem>
<DropdownMenuItem>
<ArchiveIcon /> Archiver
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-destructive">
<Trash2Icon /> Supprimer
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
{/* Zone d'image (si présente) - 60% de hauteur */}
{note.image && (
<div className="relative h-3/5 w-full bg-cover bg-center">
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" />
<div className="absolute bottom-4 left-4 right-4">
<h3 className="text-white text-xl font-bold leading-tight drop-shadow-md">
{note.title}
</h3>
</div>
<Image
src={note.image}
alt={note.title}
className="absolute inset-0 w-full h-full object-cover group-hover:scale-105 transition-transform duration-700"
/>
</div>
)}
{/* Zone de contenu */}
<div className="flex-1 p-5 flex flex-col justify-between">
<div className="flex flex-col gap-2">
{/* Icône + texte */}
<div className="flex items-start gap-2 text-sm text-muted-foreground">
{note.icon && (
<Icon icon={note.icon} className="mt-0.5" />
)}
<p className="leading-relaxed">
{note.contentPreview}
</p>
</div>
</div>
{/* Tags */}
<div className="flex flex-wrap gap-2 mt-4">
{note.labels.map(label => (
<Badge key={label.id} variant="outline" className="gap-1.5">
<LabelIcon />
{label.name}
</Badge>
))}
</div>
</div>
{/* Avatar en bas à gauche */}
<div className="absolute bottom-2 left-2">
<Avatar className="size-6 ring-2 ring-background">
<AvatarImage src={note.author.avatar} />
<AvatarFallback className="text-xs">
{note.author.initials}
</AvatarFallback>
</Avatar>
</div>
{/* Date en bas à droite */}
<div className="absolute bottom-2 right-2 text-xs text-muted-foreground">
{formatDistanceToNow(note.date)}
</div>
</Card>
```
---
## 2. PAGE NOTEBOOK - MOBILE
### 2.1 Vue d'ensemble
**Dimensions :** 375x812 (iPhone SE) - jusqu'à 768px (tablette)
**Layout :** Navigation drawer + Contenu scrollable + Bottom Tab Bar
```
┌─────────────────────┐
│ [☰] Voyage [🔍] [...]│ ← HEADER (60px)
├─────────────────────┤
│ FILTRES HORIZONTAUX│ ← SCROLLABLE (36px)
│ [✓ALL] #Hôtels #Vols│
├─────────────────────┤
│ │
│ CONTENU PRINCIPAL │ ← VERTICAL LIST (pas masonry)
│ (SCROLLABLE) │
│ │
│ ┌─────────────────┐ │
│ │ HERO CARD │ │ ← Grande carte avec image
│ │ [Image] │ │ (première note)
│ │ #Vols │ │
│ │ Tokyo Trip Plan │ │
│ │ Flight JL005... │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ │
│ │ HOTEL CARD │ │
│ │ Kyoto Ryokan... │ │ ← Carte compacte
│ │ #Hôtels │ │
│ │ Oct 14 - 17 │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ │
│ │ RESTAURANT LIST │ │
│ │ 🍜 Sushi Dai │ │
│ │ ✅ Rokurinsha │ │
│ │ ☐ Starbucks │ │
│ │ #Restos │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ │
│ │ IDEA NOTE │ │
│ │ 💡 Souvenir... │ │
│ │ Matcha Kit, ... │ │
│ └─────────────────┘ │
│ │
├─────────────────────┤
│ [🏠] [📁] [🔍] [⚙️] │ ← BOTTOM TAB BAR (72px)
└─────────────────────┘
[+] FAB (56px)
```
### 2.2 Spécifications détaillées
#### HEADER MOBILE
```tsx
<header className="flex items-center justify-between px-4 pt-4 pb-2 sticky top-0 z-20">
{/* Menu bouton (ouvre le drawer) */}
<Button variant="ghost" size="icon" className="-ml-2">
<MenuIcon className="h-7 w-7" />
</Button>
{/* Titre de page */}
<h1 className="text-xl font-extrabold tracking-tight">
Voyage
</h1>
{/* Actions droite */}
<div className="flex items-center gap-1">
<Button variant="ghost" size="icon">
<SearchIcon className="h-6 w-6" />
</Button>
<Button variant="ghost" size="icon" className="-mr-2">
<MoreVertIcon className="h-6 w-6" />
</Button>
</div>
</header>
```
#### FILTRES HORIZONTAUX (SCROLLABLE)
```tsx
<div className="w-full overflow-x-auto pb-4 pt-1 hide-scrollbar sticky top-[60px] z-10">
<div className="flex gap-2 px-4">
{/* Bouton "All" (actif) */}
<Button className="h-9 shrink-0 gap-2 rounded-full bg-primary px-5 shadow-lg">
<CheckIcon />
<span className="text-sm font-bold">All</span>
</Button>
{/* Filtres de labels */}
{labels.map(label => (
<Button
key={label.id}
variant="outline"
className="h-9 shrink-0 px-4 rounded-full"
>
<span className="text-sm font-medium">#{label.name}</span>
</Button>
))}
</div>
</div>
```
#### CARTES NOTES MOBILE (VERTICAL LIST)
**HERO CARD (première note - avec image)**
```tsx
<Card className="relative overflow-hidden bg-card rounded-2xl shadow-sm group cursor-pointer h-[240px]">
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent z-10" />
<Image
src={note.image}
alt={note.title}
className="absolute inset-0 w-full h-full object-cover group-hover:scale-105 transition-transform duration-700"
/>
<div className="absolute bottom-0 left-0 right-0 p-5 z-20 flex flex-col gap-1.5">
<div className="flex items-center gap-2">
<Badge className="bg-primary text-primary-foreground px-2 py-0.5 text-[10px] uppercase tracking-wider font-bold">
#Vols
</Badge>
<Badge className="bg-background/20 text-background px-2 py-0.5 text-[10px] uppercase tracking-wider font-bold backdrop-blur-md">
Next Up
</Badge>
</div>
<h2 className="text-white text-2xl font-bold leading-tight">
{note.title}
</h2>
<p className="text-background/80 text-sm font-medium line-clamp-1">
{note.contentPreview}
</p>
</div>
</Card>
```
**CARTE COMPACTE (sans image)**
```tsx
<Card className="bg-card p-4 rounded-2xl shadow-sm border flex flex-col cursor-pointer hover:border-primary/30 transition-colors">
<Badge className="self-start mb-2 text-[10px] font-bold">
#Hôtels
</Badge>
<h3 className="text-base font-bold leading-tight mb-2">
{note.title}
</h3>
<p className="text-xs text-muted-foreground line-clamp-3 mb-3">
{note.contentPreview}
</p>
<div className="mt-auto flex items-center gap-1 text-[10px] text-muted-foreground">
<CalendarIcon />
<span>{formatDate(note.date)}</span>
</div>
</Card>
```
**CARTE LISTE (checklist)**
```tsx
<Card className="bg-card p-4 rounded-2xl shadow-sm border flex flex-col cursor-pointer">
<h3 className="text-sm font-bold mb-2">
{note.title}
</h3>
<ul className="space-y-1.5">
{note.items.map((item, index) => (
<li key={index} className="flex items-center gap-2">
<div className="size-4 rounded-full border-2 border-border bg-card flex items-center justify-center shrink-0">
{item.checked && (
<CheckIcon className="text-xs" />
)}
</div>
<span className={`text-xs ${item.checked ? 'text-muted-foreground line-through' : ''}`}>
{item.text}
</span>
</li>
))}
</ul>
<div className="mt-3">
<Badge>#Restos</Badge>
</div>
</Card>
```
#### BOTTOM TAB BAR (72px)
```tsx
<nav className="fixed bottom-0 w-full bg-background/90 backdrop-blur-lg border-t z-40 pb-safe">
<div className="flex justify-around items-center h-[72px] pb-2">
{/* Home */}
<Button variant="ghost" className="flex-col items-center justify-center w-16 gap-1">
<HomeIcon className="h-6 w-6" />
<span className="text-[10px]">Home</span>
</Button>
{/* Notebooks (actif) */}
<Button variant="ghost" className="flex-col items-center justify-center w-16 gap-1 text-primary">
<FolderIcon className="h-6 w-6 fill" />
<span className="text-[10px] font-bold">Notebooks</span>
</Button>
{/* Espace vide pour le FAB */}
<div className="w-8" />
{/* Search */}
<Button variant="ghost" className="flex-col items-center justify-center w-16 gap-1">
<SearchIcon className="h-6 w-6" />
<span className="text-[10px]">Search</span>
</Button>
{/* Settings */}
<Button variant="ghost" className="flex-col items-center justify-center w-16 gap-1">
<SettingsIcon className="h-6 w-6" />
<span className="text-[10px]">Settings</span>
</Button>
</div>
</nav>
```
#### FLOATING ACTION BUTTON (FAB)
```tsx
<Button
className="fixed bottom-[90px] right-5 z-30 size-14 bg-primary text-primary-foreground rounded-2xl shadow-lg shadow-primary/30 hover:scale-105 active:scale-95 transition-all group"
>
<AddIcon className="h-8 w-8 group-hover:rotate-90 transition-transform duration-300" />
</Button>
```
---
## 3. PAGE ADMIN
### 3.1 Vue d'ensemble
**Layout :** Sidebar navigation + Contenu principal avec tableau de bord
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ HEADER ADMIN (64px) │
│ [LOGO ADMIN] [RECHERCHE] [NOTIFS] [AVATAR ADMIN] │
├──────────────┬──────────────────────────────────────────────────────────────┤
│ │ │
│ SIDEBAR │ CONTENU PRINCIPAL │
│ NAVIGATION │ │
│ (256px) │ │
│ │ ┌──────────────────────────────────────────────────┐ │
│ 📊 DASHBOARD│ │ 📊 ADMIN DASHBOARD │ │
│ │ │ │ │
│ 👥 UTILISATEURS│ │ ┌──────────┐ ┌──────────┐ ┌───────┐│ │
│ │ │ │ Utilisa │ │ Notes │ │ AI Met ││ │
│ 📈 ANALYTIQUE│ │ │teurs │ │ │ │ rics ││ │
│ │ │ │ Active │ │ Total │ │ Tokens ││ │
│ ⚙️ CONFIG │ │ │ 156 │ │ 1,234 │ │ 45.2K ││ │
│ │ │ │ (+12) │ │ (+89) │ │ ││ │
│ 🔒 SÉCURITÉ │ │ └──────────┘ └──────────┘ └───────┘│ │
│ │ │ │ │
│ 💰 COÛTS AI │ │ ┌────────────────────────────────────────┐ │ │
│ │ │ │ Utilisation AI par jour │ │ │
│ 📝 JOURNAL │ │ │ 📊 [Graphique en ligne] │ │ │
│ │ │ │ │ │ │
│ 🔔 NOTIFS │ │ │ [Graphique circulaire par feature] │ │ │
│ │ │ └────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ │ ┌────────────────────────────────────────┐ │ │
│ │ │ │ ACTIONS RAPIDES │ │ │
│ │ │ └────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ └──────────────────────────────────────────────────┘ │
└──────────────┴──────────────────────────────────────────────────────────────┘
```
### 3.2 Spécifications détaillées
#### HEADER ADMIN
```tsx
<header className="h-16 flex items-center justify-between px-6 border-b bg-background z-20">
{/* Logo + titre */}
<div className="flex items-center gap-3">
<div className="size-8 bg-amber-500 rounded-lg flex items-center justify-center text-white">
<AdminPanelSettingsIcon />
</div>
<div>
<h1 className="text-xl font-bold">Admin Console</h1>
<p className="text-xs text-muted-foreground">Keep Platform Management</p>
</div>
</div>
{/* Recherche */}
<label className="hidden lg:flex w-96">
<div className="flex w-full h-10 rounded-xl bg-muted focus-within:ring-2">
<SearchIcon className="muted-foreground ml-4" />
<input
className="flex-1 bg-transparent px-3 text-sm focus:ring-0"
placeholder="Rechercher utilisateurs, notes..."
/>
</div>
</label>
{/* Actions droite */}
<div className="flex items-center gap-3">
<Badge variant="secondary" className="gap-1">
<DotIcon className="size-2 fill-green-500" />
Système en ligne
</Badge>
<Button variant="ghost" size="icon">
<BellIcon />
<Badge className="absolute -top-1 -right-1 size-4 bg-destructive rounded-full text-[10px] text-white flex items-center justify-center">
3
</Badge>
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Avatar className="size-10 ring-2 ring-background cursor-pointer">
<AvatarImage src={admin.avatar} />
<AvatarFallback>AD</AvatarFallback>
</Avatar>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<UserIcon /> Profil Admin
</DropdownMenuItem>
<DropdownMenuItem>
<SettingsIcon /> Paramètres
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-destructive">
<LogOutIcon /> Déconnexion
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</header>
```
#### SIDEBAR ADMIN
```tsx
<aside className="w-64 hidden md:flex flex-col border-r bg-background overflow-y-auto">
<nav className="p-4 flex flex-col gap-2">
{/* Dashboard */}
<Button
variant="ghost"
className="justify-start gap-3 px-3 py-2.5 bg-primary/10 text-primary"
>
<BarChart3Icon />
Dashboard
</Button>
{/* Utilisateurs */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<UsersIcon />
Utilisateurs
</Button>
{/* Analytics */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<TrendingUpIcon />
Analytics
</Button>
{/* Configuration */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<SettingsIcon />
Configuration
</Button>
{/* Sécurité */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<ShieldIcon />
Sécurité
</Button>
{/* Coûts AI */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<CreditCardIcon />
Coûts AI
</Button>
{/* Journal */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<FileTextIcon />
Journal d'audit
</Button>
{/* Notifications */}
<Button variant="ghost" className="justify-start gap-3 px-3 py-2.5">
<BellIcon />
Notifications
</Button>
</nav>
{/* Footer */}
<div className="mt-auto p-4 border-t">
<div className="text-xs text-muted-foreground">
<p>Keep v{version}</p>
<p className="mt-1">© 2026 Keep Platform</p>
</div>
</div>
</aside>
```
#### CARDS MÉTRIQUES
```tsx
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
{/* Carte Utilisateurs */}
<Card className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<UsersIcon className="text-muted-foreground" />
<h3 className="font-semibold">Utilisateurs</h3>
</div>
<Badge variant="outline">Actifs</Badge>
</div>
<div className="flex items-end gap-2">
<p className="text-4xl font-bold">156</p>
<Badge className="mb-1 bg-green-500/10 text-green-600">
+12 cette semaine
</Badge>
</div>
</Card>
{/* Carte Notes */}
<Card className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<FileTextIcon className="text-muted-foreground" />
<h3 className="font-semibold">Notes</h3>
</div>
</div>
<div className="flex items-end gap-2">
<p className="text-4xl font-bold">1,234</p>
<Badge className="mb-1 bg-blue-500/10 text-blue-600">
+89 aujourd'hui
</Badge>
</div>
</Card>
{/* Carte AI Metrics */}
<Card className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<SparklesIcon className="text-muted-foreground" />
<h3 className="font-semibold">AI Tokens</h3>
</div>
<Badge variant="outline">Ce mois</Badge>
</div>
<div className="flex items-end gap-2">
<p className="text-4xl font-bold">45.2K</p>
<Badge className="mb-1 bg-purple-500/10 text-purple-600">
12% vs mois dernier
</Badge>
</div>
</Card>
</div>
```
---
## 4. PAGE PROFIL
### 4.1 Vue d'ensemble
**Layout :** Header avec avatar + Contenu principal organisé en sections
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ HEADER PROFIL (avec bannière) │
│ [BANNIÈRE IMAGE] │
│ [AVATAR 96px] [NOM COMPLET] [EMAIL] [✏️ ÉDITER] │
│ [BIO] [⚙️ PARAMÈTRES] │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ CONTENU (scrollable) │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ 📊 STATISTIQUES │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 156 │ │ 1,234 │ │ 23 │ │ 4 │ │ │
│ │ │ Notes │ │ Labels │ │ Notebooks│ │ Jours │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ 🎨 THÈMES │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ ☀️ Light │ │ 🌙 Dark │ │ 🌊 Midnight│ │ 📖 Sepia │ │ │
│ │ │ │ │ ✅ │ │ │ │ │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ ⚙️ PARAMÈTRES PRÉFÉRÉNCES │ │
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Langue : 🇫🇷 Français │ │ │
│ │ │ Fuseau : 🕐 Central European Time │ │ │
│ │ │ Email : ✅ Recevoir les notifications │ │ │
│ │ │ Privacy : ✅ Profile public │ │ │
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ 🔐 SÉCURITÉ │ │
│ │ [Mot de passe] [✏️ Modifier] │ │
│ │ [2FA] [✏️ Configurer] │ │
│ │ [Sessions actives] [👁️ Voir] │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ 🤖 AI SETTINGS │ │
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Provider : [Auto ▼] │ │ │
│ │ │ │ │ │
│ │ │ ☑️ Suggestions de titres │ │ │
│ │ │ ☑️ Recherche sémantique │ │ │
│ │ │ ☑️ Reformulation de paragraphes │ │ │
│ │ │ ☑️ Memory Echo (1/jour) │ │ │
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘
```
### 4.2 Spécifications détaillées
#### HEADER PROFIL (AVEC BANNIÈRE)
```tsx
<div className="relative">
{/* Bannière image */}
<div className="h-48 bg-gradient-to-br from-primary/20 to-primary/5" />
<div className="max-w-4xl mx-auto px-6 -mt-16">
<Card className="border-2 bg-background shadow-lg">
<CardContent className="p-6">
<div className="flex items-start gap-6">
{/* Avatar */}
<Avatar className="size-24 ring-4 ring-background shadow-lg">
<AvatarImage src={user.avatar} />
<AvatarFallback className="text-2xl font-bold">
{user.initials}
</AvatarFallback>
</Avatar>
{/* Infos utilisateur */}
<div className="flex-1">
<div className="flex items-center justify-between mb-2">
<div>
<h1 className="text-2xl font-bold">{user.fullName}</h1>
<p className="text-sm text-muted-foreground">{user.email}</p>
</div>
<div className="flex gap-2">
<Button variant="outline" size="sm">
<EditIcon />
Éditer profil
</Button>
<Button variant="ghost" size="icon">
<SettingsIcon />
</Button>
</div>
</div>
{/* Bio */}
<p className="text-sm text-muted-foreground">
{user.bio || "Aucune bio renseignée"}
</p>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
```
#### SECTION STATISTIQUES
```tsx
<section className="max-w-4xl mx-auto px-6 py-8">
<h2 className="text-lg font-semibold mb-4">📊 Statistiques</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<Card className="p-4 text-center">
<p className="text-3xl font-bold text-primary">{stats.notesCount}</p>
<p className="text-xs text-muted-foreground mt-1">Notes</p>
</Card>
<Card className="p-4 text-center">
<p className="text-3xl font-bold text-secondary">{stats.labelsCount}</p>
<p className="text-xs text-muted-foreground mt-1">Labels</p>
</Card>
<Card className="p-4 text-center">
<p className="text-3xl font-bold text-accent">{stats.notebooksCount}</p>
<p className="text-xs text-muted-foreground mt-1">Notebooks</p>
</Card>
<Card className="p-4 text-center">
<p className="text-3xl font-bold text-muted-foreground">{stats.daysActive}</p>
<p className="text-xs text-muted-foreground mt-1">Jours actifs</p>
</Card>
</div>
</section>
```
#### SECTION THÈMES
```tsx
<section className="max-w-4xl mx-auto px-6 py-8">
<h2 className="text-lg font-semibold mb-4">🎨 Thème</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{themes.map(theme => (
<Card
key={theme.id}
className={`cursor-pointer transition-all hover:scale-105 ${
currentTheme === theme.id ? 'ring-2 ring-primary' : ''
}`}
onClick={() => setTheme(theme.id)}
>
<CardContent className="p-4 text-center">
<div className="text-3xl mb-2">{theme.icon}</div>
<p className="text-sm font-medium">{theme.name}</p>
{currentTheme === theme.id && (
<CheckIcon className="mx-auto mt-2 text-primary" />
)}
</CardContent>
</Card>
))}
</div>
</section>
```
---
## 5. COMPOSANTS UI RÉUTILISABLES
### 5.1 Bouton
```tsx
<Button
variant="default" // | "outline" | "ghost" | "destructive"
size="default" // | "sm" | "icon" | "lg"
className="h-9 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200"
>
{/* content */}
</Button>
```
### 5.2 Badge
```tsx
<Badge
variant="default" // | "outline" | "secondary" | "destructive"
className="rounded-full px-2 py-0.5 text-xs font-medium"
>
{/* content */}
</Badge>
```
### 5.3 Input
```tsx
<Input
type="text" // | "email" | "password" | "search"
className="h-9 px-3 py-2 text-sm rounded-md border border-input focus-visible:ring-2 focus-visible:ring-ring/50"
placeholder="Placeholder"
/>
```
### 5.4 Card
```tsx
<Card className="rounded-xl border p-4 shadow-sm hover:shadow-md transition-all duration-200">
<CardHeader>
<CardTitle className="text-lg font-medium">Titre</CardTitle>
</CardHeader>
<CardContent>
{/* content */}
</CardContent>
</Card>
```
---
## 6. DESIGN SYSTEM UNIFIED
### 6.1 Palette de couleurs
```css
/* Primary */
--primary: #356ac0;
--primary-foreground: #ffffff;
/* Secondary */
--secondary: #f7f7f8;
--secondary-foreground: #1a1d23;
/* Accent */
--accent: #356ac0/10;
--accent-foreground: #356ac0;
/* Muted */
--muted: #f7f7f8;
--muted-foreground: #64748b;
/* Background */
--background: #ffffff;
--foreground: #0f172a;
/* Card */
--card: #ffffff;
--card-foreground: #0f172a;
/* Border */
--border: #e2e8f0;
/* Input */
--input: #e2e8f0;
/* Ring */
--ring: #356ac0;
/* Destructive */
--destructive: #ef4444;
--destructive-foreground: #ffffff;
```
### 6.2 Typographie
```css
/* Font Sizes */
--text-xs: 0.75rem; /* 12px - Labels, badges */
--text-sm: 0.875rem; /* 14px - Body text */
--text-base: 1rem; /* 16px - Cards */
--text-lg: 1.125rem; /* 18px - Headers */
--text-xl: 1.25rem; /* 20px - Page titles */
--text-2xl: 1.5rem; /* 24px - Hero */
/* Font Weights */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
```
### 6.3 Spacing (4px base unit)
```css
--spacing-1: 0.25rem; /* 4px */
--spacing-2: 0.5rem; /* 8px */
--spacing-3: 0.75rem; /* 12px */
--spacing-4: 1rem; /* 16px */
--spacing-6: 1.5rem; /* 24px */
--spacing-8: 2rem; /* 32px */
```
### 6.4 Border Radius
```css
--radius-sm: 0.25rem; /* 4px */
--radius-md: 0.375rem; /* 6px */
--radius-lg: 0.5rem; /* 8px */
--radius-xl: 0.75rem; /* 12px */
--radius-2xl: 1rem; /* 16px */
--radius-full: 9999px; /* Circular */
```
### 6.5 Shadows
```css
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
```
### 6.6 Transitions
```css
--transition-colors: color 200ms;
--transition-opacity: opacity 150ms;
--transition-transform: transform 200ms;
--transition-all: all 200ms;
```
---
## ✅ CHECKLIST D'IMPLÉMENTATION
### Phase 1 : Foundation
- [ ] Configurer Tailwind avec Design System
- [ ] Créer les composants UI de base (Button, Badge, Input, Card)
- [ ] Mettre à jour globals.css avec les variables CSS
- [ ] Tester tous les thèmes (light, dark, midnight, sepia)
### Phase 2 : Desktop Notebook
- [ ] Implémenter Header global
- [ ] Implémenter Sidebar gauche
- [ ] Implémenter Grille Masonry (3 colonnes)
- [ ] Implémenter NoteCard avec menu "..."
- [ ] Tester responsive (lg, xl, 2xl)
### Phase 3 : Mobile Notebook
- [ ] Implémenter Header mobile
- [ ] Implémenter Filtres horizontaux scrollables
- [ ] Implémenter Cartes notes (hero, compacte, liste)
- [ ] Implémenter Bottom Tab Bar
- [ ] Implémenter FAB
- [ ] Tester sur mobile (< 768px)
### Phase 4 : Admin
- [ ] Implémenter Header admin
- [ ] Implémenter Sidebar admin
- [ ] Implémenter Dashboard avec métriques
- [ ] Tester responsive
### Phase 5 : Profil
- [ ] Implémenter Header avec bannière
- [ ] Implémenter Section Statistiques
- [ ] Implémenter Section Thèmes
- [ ] Implémenter Section Paramètres
- [ ] Tester responsive
### Phase 6 : Tests Playwright
- [ ] Créer tests pour NoteCard
- [ ] Créer tests pour Sidebar
- [ ] Créer tests pour modales
- [ ] Créer tests pour navigation mobile
- [ ] Définir procédure en cas d'échec
---
**Statut du document :** ACTIF
**Date de création :** 2026-01-17
**Version :** 1.0
**Responsable :** John - Product Manager