Files
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
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎨 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