ObsiViewer/docs/PROMPTS/Nimbus_Interface/ObsiViewer_NewInterface_Nimbus.md

760 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🎯 Prompt Windsurf — ObsiViewer Nimbus UI (Desktop + Mobile)
## ObsiViewer → UI/UX "Nimbus-like" (simple, dense, rapide)
**Rôle & mode :** Agis comme **Staff Frontend Engineer Angular 20 + UX designer**. Raisonnement détaillé autorisé. Tu as les pleins pouvoirs de refactor UI, d'ajout de composants, et de migration CSS vers Tailwind. Conserve la compatibilité de toutes features existantes.
**Contrainte majeure :** L'interface doit être **100% responsive** (Desktop + Mobile). Un **bouton toggle** dans la navbar permet de basculer entre l'ancienne interface et la nouvelle sans perte d'état.
---
## Contexte rapide
* Projet : **ObsiViewer** (Angular 20 + Tailwind, Node/Express backend).
* Objectif : Refondre l'interface selon un design **Nimbus Notes**-like.
* Cœurs d'usage : navigation par **dossiers**, **tags**, **recherche**, **lecture markdown** plein écran, **ToC** à droite, **tri et filtres** rapides.
* **Nouveauté** : Design adaptatif complet (Desktop/Mobile/Tablet) avec UI toggle persisté.
---
## 🎯 Objectif final (résumé)
### Desktop (≥1024px)
Refondre l'interface ObsiViewer en **3 colonnes** :
1. **Sidebar gauche** (Quick Links, Dossiers arborescents, Tags) — Redimensionnable.
2. **Colonne centrale** Liste des pages (recherche, filtres dossiers/tags, tris, résultats virtualisés).
3. **Vue de page** à droite (lecture markdown, barre d'actions, **panneau sommaire/ToC** docké à l'extrême droite).
Le tout **compact, performant, thème clair/sombre**, navigation au clavier, états persistés localement.
### Mobile/Tablet (<1024px)
Une navigation **par onglets/drawer** intelligente :
- **Tab 1 : Sidebar** (dossiers, tags, recherche) — Panneau full-width ou drawer collapsible.
- **Tab 2 : Liste** (résultats de recherche) — Full-width scrollable.
- **Tab 3 : Page** (markdown) — Full-width avec ToC inline collapsible ou drawer.
**Gestures** : Swipe horizontal pour navigation onglets, pull-to-refresh, tap = open item.
---
## 📋 Architecture Feature Flag & Toggle
### 1) Toggle UI dans la NavBar
Ajouter un **bouton toggle** dans `src/app/layout/app-navbar/app-navbar.component.ts` :
```html
<!-- app-navbar.component.html (snippet) -->
<div class="flex items-center gap-2">
<!-- Autres boutons -->
<button
(click)="toggleUIMode()"
[attr.aria-label]="'Toggle ' + (isNimbusMode$ | async ? 'legacy' : 'nimbus') + ' UI'"
class="p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800">
<span *ngIf="(isNimbusMode$ | async)">✨ Nimbus</span>
<span *ngIf="!(isNimbusMode$ | async)">🔧 Legacy</span>
</button>
</div>
```
### 2) Service de gestion du mode UI
Créer `src/app/shared/services/ui-mode.service.ts` :
```typescript
import { Injectable, signal } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class UiModeService {
// Signal pour réactivité fine-grained
isNimbusMode = signal<boolean>(this.loadUIMode());
constructor() {}
toggleUIMode() {
const newMode = !this.isNimbusMode();
this.isNimbusMode.set(newMode);
localStorage.setItem('obsiviewer-ui-mode', newMode ? 'nimbus' : 'legacy');
}
private loadUIMode(): boolean {
if (typeof localStorage === 'undefined') return false;
const saved = localStorage.getItem('obsiviewer-ui-mode');
return saved ? saved === 'nimbus' : true; // Nimbus par défaut
}
}
```
### 3) Layout wrapper avec feature flag
Créer `src/app/layout/app-shell-adaptive/app-shell-adaptive.component.ts` :
```typescript
import { Component, inject } from '@angular/core';
import { UiModeService } from '@app/shared/services/ui-mode.service';
import { AppShellNimbusLayoutComponent } from '../app-shell-nimbus/app-shell-nimbus.component';
import { AppShellLegacyLayoutComponent } from '../app-shell-legacy/app-shell-legacy.component';
@Component({
selector: 'app-shell-adaptive',
template: `
@if (uiMode.isNimbusMode()) {
<app-shell-nimbus-layout></app-shell-nimbus-layout>
} @else {
<app-shell-legacy-layout></app-shell-legacy-layout>
}
`,
standalone: true,
imports: [AppShellNimbusLayoutComponent, AppShellLegacyLayoutComponent],
})
export class AppShellAdaptiveComponent {
uiMode = inject(UiModeService);
}
```
---
## 🎨 Responsive Design Strategy
### Breakpoints Tailwind (standard)
```typescript
// tailwind.config.js
module.exports = {
theme: {
screens: {
'xs': '320px', // iPhone SE
'sm': '640px', // Petites tablettes
'md': '768px', // iPad, tablettes
'lg': '1024px', // Desktop compact
'xl': '1280px', // Desktop standard
'2xl': '1536px', // Larges écrans
},
},
};
```
### Mobile First Approach
**Développer pour mobile d'abord, puis enrichir pour desktop.**
---
## 📱 Layouts Responsifs
### Desktop Layout (≥1024px)
```
┌─────────────────────────────────────────────────────────┐
│ NAVBAR (Dark, fixed, h-14) │
├────────────────┬──────────────────┬──────────────────────┤
│ │ │ │
│ SIDEBAR │ RESULT LIST │ NOTE VIEW + TOC │
│ (240-440px) │ (virtualized) │ (Resizable) │
│ Resizable │ │ │
│ │ │ │
│ - Quick │ - Search bar │ - Markdown │
│ Links │ - Filters │ - ToC drawer │
│ - Folders │ - Items (80px) │ - Actions bar │
│ - Tags │ - Pagination │ │
│ │ │ │
└────────────────┴──────────────────┴──────────────────────┘
```
### Tablet Layout (768px ≤ width < 1024px)
```
┌──────────────────────────────────────┐
│ NAVBAR + Toggle (fixed, h-14) │
├──────────────────────────────────────┤
│ TAB NAVIGATION (fixed, bottom) │
│ [Sidebar] [List] [Page] [ToC] │
├──────────────────────────────────────┤
│ │
│ ACTIVE TAB CONTENT (scrollable) │
│ - Drawer si besoin │
│ - Full-width panels │
│ │
└──────────────────────────────────────┘
```
### Mobile Layout (<768px)
```
┌──────────────────────────────────┐
│ NAVBAR (compact, h-12) │
│ [Menu] [Search] [Toggle] │
├──────────────────────────────────┤
│ │
│ TAB/DRAWER NAVIGATION │
│ [≡] [🔍] [📄] [📋] │
│ │
│ CONTENT AREA (Full-width) │
│ - Drawer sidebar (80vw left) │
│ - Swipeable list (list tab) │
│ - Markdown full-screen (page) │
│ - Inline ToC (toggle button) │
│ │
├──────────────────────────────────┤
│ Bottom Navigation (sticky) │
│ Tab buttons (4 icônes) │
└──────────────────────────────────┘
```
---
## 🎬 Composants Nimbus Responsifs
### Desktop/Mobile Variants
Chaque composant doit avoir des **variants responsifs** :
```
app-left-sidebar/
├── app-left-sidebar.component.ts # Logique partagée
├── app-left-sidebar.desktop.component.ts # ≥1024px (fixed, resizable)
└── app-left-sidebar.mobile.component.ts # <1024px (drawer)
app-center-list/
├── app-center-list.component.ts
├── app-center-list.desktop.component.ts # ≥1024px (2 colonnes)
└── app-center-list.mobile.component.ts # <1024px (full-width)
app-note-view/
├── app-note-view.component.ts
├── app-note-view.desktop.component.ts # ≥1024px (3 colonnes + ToC)
└── app-note-view.mobile.component.ts # <1024px (full-width + ToC inline)
app-toc-drawer/
├── app-toc-drawer.component.ts
├── app-toc-drawer.desktop.component.ts # ≥1024px (Fixed right)
└── app-toc-drawer.mobile.component.ts # <1024px (Collapsible, inline)
```
### Détection et Injection
```typescript
// app-left-sidebar.component.ts
import { Component, inject } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
@Component({
selector: 'app-left-sidebar',
standalone: true,
template: `
@if (isDesktop$ | async) {
<ng-container *ngComponentOutlet="DesktopSidebarComponent"></ng-container>
} @else {
<ng-container *ngComponentOutlet="MobileSidebarDrawerComponent"></ng-container>
}
`,
})
export class AppLeftSidebarComponent {
private breakpoint = inject(BreakpointObserver);
isDesktop$ = this.breakpoint.observe(Breakpoints.Large).pipe(
map(result => result.matches)
);
}
```
---
## 📱 Navigation Mobile Avancée
### Tab/Drawer Navigation
```typescript
// src/shared/services/mobile-nav.service.ts
@Injectable({ providedIn: 'root' })
export class MobileNavService {
activeTab = signal<'sidebar' | 'list' | 'page' | 'toc'>('list');
setTab(tab: 'sidebar' | 'list' | 'page' | 'toc') {
this.activeTab.set(tab);
// Persist if needed
}
}
// Usage in component
<app-bottom-nav [activeTab]="mobileNav.activeTab()"
(tabChange)="mobileNav.setTab($event)">
</app-bottom-nav>
```
### Swipe Navigation (Gestures)
```typescript
// Directive pour détection de swipe
import { Directive, Output, EventEmitter, HostListener } from '@angular/core';
@Directive({
selector: '[appSwipeNav]',
standalone: true,
})
export class SwipeNavDirective {
@Output() swipeLeft = new EventEmitter<void>();
@Output() swipeRight = new EventEmitter<void>();
private startX = 0;
@HostListener('touchstart', ['$event'])
onTouchStart(e: TouchEvent) {
this.startX = e.touches[0].clientX;
}
@HostListener('touchend', ['$event'])
onTouchEnd(e: TouchEvent) {
const endX = e.changedTouches[0].clientX;
const diff = this.startX - endX;
if (Math.abs(diff) > 50) { // Seuil minimum
if (diff > 0) this.swipeLeft.emit();
else this.swipeRight.emit();
}
}
}
```
---
## 🎨 Composants Spécifiques (Mobile-First)
### 1) Bottom Navigation (Mobile)
```html
<!-- app-bottom-nav.component.html -->
<nav class="fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-900 border-t
border-gray-200 dark:border-gray-800 h-16 flex justify-around md:hidden">
<button *ngFor="let tab of tabs"
(click)="selectTab(tab.id)"
[class.active]="activeTab === tab.id"
class="flex-1 flex flex-col items-center justify-center gap-1
text-xs hover:bg-gray-50 dark:hover:bg-gray-800">
<span class="text-lg">{{ tab.icon }}</span>
<span>{{ tab.label }}</span>
</button>
</nav>
```
### 2) Drawer Sidebar (Mobile)
```html
<!-- app-left-sidebar.mobile.component.html -->
<aside class="fixed left-0 top-0 bottom-0 w-80vw max-w-xs
bg-white dark:bg-gray-900 shadow-lg z-50
transform transition-transform duration-300"
[class.-translate-x-full]="!isOpen">
<!-- Contenu sidebar -->
<button (click)="close()" class="absolute top-4 right-4"></button>
</aside>
<!-- Backdrop -->
<div *ngIf="isOpen"
(click)="close()"
class="fixed inset-0 bg-black/50 z-40 md:hidden"></div>
```
### 3) Search Bar Compact (Mobile)
```html
<!-- app-search-bar.mobile.component.html -->
<div class="sticky top-0 bg-white dark:bg-gray-900 p-2 shadow-sm z-10">
<div class="flex gap-2">
<!-- Menu toggle -->
<button (click)="toggleSidebar()"
class="p-2 rounded hover:bg-gray-100"></button>
<!-- Search input (full-width on mobile) -->
<input type="text"
placeholder="Search..."
class="flex-1 px-3 py-2 rounded border dark:border-gray-700">
<!-- Filters button (mobile: popover instead of dropdown) -->
<button (click)="openFilters()"
class="p-2 rounded hover:bg-gray-100">⚙️</button>
</div>
<!-- Active badges (scrollable horizontally) -->
<div class="flex gap-1 mt-2 overflow-x-auto">
<span *ngFor="let badge of activeBadges"
class="badge badge-sm">
{{ badge }} ✕
</span>
</div>
</div>
```
### 4) Result List Item (Mobile-Optimized)
```html
<!-- app-result-list-item.component.html -->
<div class="p-3 border-b hover:bg-gray-50 dark:hover:bg-gray-800 cursor-pointer">
<!-- Title -->
<h3 class="font-semibold text-sm sm:text-base truncate">
{{ item.title }}
</h3>
<!-- Date + Tags (stacked on mobile) -->
<div class="flex flex-col sm:flex-row sm:items-center gap-1 mt-1 text-xs text-gray-600">
<span>{{ item.modified | date:'short' }}</span>
<div class="flex gap-1 flex-wrap">
<span *ngFor="let tag of item.tags"
class="badge badge-sm">{{ tag }}</span>
</div>
</div>
<!-- Excerpt (truncated) -->
<p class="mt-2 text-xs text-gray-600 line-clamp-2">
{{ item.excerpt }}
</p>
</div>
```
### 5) Markdown Viewer (Mobile-Responsive)
```html
<!-- app-markdown-viewer.component.html -->
<article class="prose dark:prose-invert max-w-none
prose-sm sm:prose-base
prose-img:max-w-full prose-img:h-auto
px-3 sm:px-6 py-4 sm:py-8">
<!-- Markdown content -->
<div [innerHTML]="markdownHTML"></div>
<!-- ToC (mobile: inline toggle) -->
<button *ngIf="headings.length > 0"
(click)="showToC = !showToC"
class="lg:hidden fixed bottom-20 right-4 p-3 rounded-full bg-blue-500 text-white shadow-lg">
📋
</button>
<nav *ngIf="showToC" class="lg:hidden fixed inset-0 bg-white dark:bg-gray-900
z-40 overflow-y-auto p-4">
<!-- ToC content -->
</nav>
</article>
```
### 6) ToC Drawer (Desktop Fixed, Mobile Inline)
```typescript
// app-toc-drawer.component.ts
@Component({
selector: 'app-toc-drawer',
template: `
<!-- Desktop: Fixed right panel (≥1024px) -->
<aside class="hidden lg:flex fixed right-0 top-14 bottom-0 w-64
bg-gray-50 dark:bg-gray-800 border-l
border-gray-200 dark:border-gray-700
flex-col overflow-y-auto">
<app-toc-content [headings]="headings"></app-toc-content>
</aside>
<!-- Mobile: Collapsible inline (< 1024px) -->
<div *ngIf="(isMobile$ | async)"
[@slideDown]="showTocMobile ? 'in' : 'out'"
class="bg-gray-50 dark:bg-gray-800 border-t p-3 max-h-96 overflow-y-auto">
<app-toc-content [headings]="headings"></app-toc-content>
</div>
`,
animations: [
trigger('slideDown', [
state('in', style({ height: '*' })),
state('out', style({ height: '0px' })),
transition('in <=> out', animate('200ms ease-in-out')),
]),
],
standalone: true,
})
export class AppTocDrawerComponent {
@Input() headings: Heading[] = [];
showTocMobile = false;
isMobile$ = this.breakpoint.observe('(max-width: 1023px)').pipe(
map(r => r.matches)
);
}
```
---
## 🎯 Livrables Attendus
### Code
1. **Toggle UI** : `UiModeService`, bouton navbar, `AppShellAdaptiveComponent`
2. **Responsive Wrappers** : Variants pour chaque composant (Desktop/Mobile)
3. **Mobile Components** : Bottom nav, drawer sidebar, inline ToC, mobile search
4. **Gesture Handling** : Swipe navigation directive, touch-friendly interactions
5. **Breakpoint Utilities** : Service CDK layout, reactive signals
### Styling
1. **Tailwind Config** : Breakpoints personnalisés, tokens tokens clair/sombre
2. **Mobile-First CSS** : Base mobile, enrichissements desktop via `md:`, `lg:`
3. **Touch-Friendly** : Boutons ≥44x44px, padding adéquat, hover states
### Documentation
1. **README_UI.md** : Schémas responsive, breakpoints, guide toggle
2. **MOBILE_GUIDE.md** : Navigation gestures, bottom nav flow, drawer patterns
3. **RESPONSIVE_CHECKLIST.md** : Tests par breakpoint, checklist A11y mobile
### Tests
1. **E2E** : Toggle persistence, layout switch, gesture navigation
2. **Visual Regression** : Screenshots desktop/tablet/mobile
3. **Accessibility** : Touch targets, ARIA labels, keyboard nav (Tab key)
---
## ⚡ Performance & Mobile Optimizations
### Critical Optimizations
- **Lazy-load images** : `loading="lazy"`, responsive `srcset`
- **Virtual scroll** : CDK virtual scroll adapté mobile (item height ≈ 7080px)
- **Debounce search** : 300ms sur mobile, 150ms sur desktop
- **Avoid layout shift** : Aspect ratios, skeleton loaders
- **Network awareness** : `navigator.connection.effectiveType` pour adapt qualité
- **Battery saver** : Réduire animations, throttle updates en mode saver
### Lighthouse Mobile Targets
- Performance ≥ 85
- Accessibility ≥ 95
- Best Practices ≥ 90
---
## 🎮 Raccourcis Clavier & Gestures
### Desktop
- `Ctrl/Cmd + K` : Palette commandes
- `Ctrl/Cmd + F` : Focus recherche
- `[` `]` : Replier/ouvrir ToC
- `Alt + ←/→` : Navigation historique
### Mobile/Tablet
- **Tap** : Ouvrir note/item
- **Swipe left/right** : Changer onglet (list → page → sidebar)
- **Long-press** : Menu contextuel (favoris, open in new tab)
- **Pull-to-refresh** : Rafraîchir liste (optionnel)
- **Double-tap** : Zoom ToC (mobile)
---
## 📋 Critères d'Acceptation
### Desktop (≥1024px)
- [x] Layout 3 colonnes (sidebar fixe/resizable, liste, page+ToC)
- [x] Changement dossier/tag/tri reflété en URL
- [x] 1000+ items fluide (60fps virtual scroll)
- [x] ToC synchronisé + repliable
- [x] Tous les flux clavier-seuls possibles
### Tablet (7681023px)
- [x] Navigation par onglets (Sidebar / List / Page)
- [x] Drawer sidebar (80vw, swipeable)
- [x] Bottom navigation sticky (4 icônes)
- [x] Contenu full-width par onglet
- [x] ToC inline collapsible
### Mobile (<768px)
- [x] Drawer sidebar (80vw max)
- [x] Bottom nav (4 onglets)
- [x] Search bar compact (menu + search + filters)
- [x] List items optimisés (titre + date + excerpt)
- [x] Markdown full-screen
- [x] ToC overlay ou inline toggle
- [x] Touch targets ≥ 44x44px
### Feature Flag
- [x] Toggle UI visible dans navbar
- [x] État persisté (localStorage)
- [x] Pas de perte d'état lors du switch
- [x] Legacy UI reste intacte
### Accessibility
- [x] WCAG 2.1 AA sur tous les breakpoints
- [x] Keyboard navigation complète (Tab, Arrow, Enter)
- [x] ARIA labels pour navigation tactile
- [x] Focus visible partout
- [x] Zoom ≤ 200% sans horizontal scroll
### Performance
- [x] TTI < 2.5s cold start
- [x] Scroll 60fps sur 1000+ items
- [x] Lighthouse Mobile 85 perf, 95 a11y
- [x] ImageOptimizations (lazy, srcset, format next-gen)
---
## 🗂️ Arborescence Fichiers
```
src/app/
├── layout/
│ ├── app-shell-adaptive/
│ │ └── app-shell-adaptive.component.ts # Feature flag wrapper
│ ├── app-shell-nimbus/
│ │ ├── app-shell-nimbus.component.ts # 3 colonnes (desktop)
│ │ ├── app-shell-nimbus.desktop.component.ts
│ │ └── app-shell-nimbus.mobile.component.ts
│ └── app-navbar/
│ ├── app-navbar.component.ts
│ └── [Bouton toggle UI intégré]
├── features/
│ ├── sidebar/
│ │ ├── app-left-sidebar.component.ts
│ │ ├── app-left-sidebar.desktop.component.ts
│ │ └── app-left-sidebar.mobile.component.ts
│ │
│ ├── search-bar/
│ │ ├── app-search-bar.component.ts
│ │ ├── app-search-bar.desktop.component.ts
│ │ └── app-search-bar.mobile.component.ts
│ │
│ ├── result-list/
│ │ ├── app-result-list.component.ts
│ │ ├── app-result-list.desktop.component.ts
│ │ ├── app-result-list.mobile.component.ts
│ │ └── app-result-list-item.component.ts
│ │
│ ├── note-view/
│ │ ├── app-note-view.component.ts
│ │ ├── app-note-view.desktop.component.ts
│ │ └── app-note-view.mobile.component.ts
│ │
│ ├── toc-drawer/
│ │ ├── app-toc-drawer.component.ts
│ │ └── app-toc-content.component.ts
│ │
│ └── bottom-nav/ [NEW]
│ ├── app-bottom-nav.component.ts
│ └── app-bottom-nav.component.html
├── shared/
│ ├── services/
│ │ ├── ui-mode.service.ts # [NEW] Toggle management
│ │ ├── mobile-nav.service.ts # [NEW] Tab/drawer state
│ │ └── breakpoint.service.ts # [NEW] Responsive helper
│ │
│ ├── directives/
│ │ └── swipe-nav.directive.ts # [NEW] Gesture detection
│ │
│ └── components/
│ └── resizable-handle/
└── styles/
├── tokens.css # Tailwind tokens
├── responsive.css # Breakpoint utilities
└── mobile.css # Mobile-specific (touches, etc.)
```
---
## 📅 Plan d'Implémentation (ordre conseillé)
1. **Feature Flag Infrastructure** (1-2j)
- `UiModeService` + localStorage persistence
- `AppShellAdaptiveComponent` wrapper
- Toggle button dans navbar
2. **Responsive Shell & Breakpoints** (2-3j)
- Desktop layout 3 colonnes (>=1024px)
- Tailwind breakpoints & tokens
- Resizable sidebar logic
3. **Mobile Navigation & Bottom Nav** (2-3j)
- `BottomNavComponent` (4 onglets)
- `MobileNavService` (state management)
- Tab/drawer routing
4. **Mobile Sidebar Drawer** (1-2j)
- Drawer animé (translate, backdrop)
- Swipe dismiss directive
- Z-index management
5. **Responsive Components** (3-4j)
- Search bar variants (desktop/mobile)
- Result list item responsive
- Markdown viewer mobile optimizations
6. **ToC Drawer Adaptive** (1-2j)
- Fixed right panel (desktop)
- Inline toggle (mobile)
- Animations smooth
7. **Gestures & Touch** (1-2j)
- Swipe nav directive
- Long-press menu
- Pull-to-refresh (optionnel)
8. **Accessibility & Testing** (2-3j)
- WCAG 2.1 AA audit
- Keyboard nav (Tab, Arrow)
- E2E tests (toggle, breakpoints)
- Visual regression (3 breakpoints)
**Total estimé** : 1321 jours (équipe 1 FE engineer)
---
## 🚀 Scripts NPM
```bash
# Dev complet (Nimbus activé par défaut)
npm run dev
# Build production
npm run build
# Tests responsifs (plusieurs breakpoints)
npm run test:responsive
# Lighthouse audit mobile
npm run audit:lighthouse:mobile
# Feature flag (override)
NIMBUS_UI=false npm run dev # Force legacy UI
```
---
## ✅ Checklist Livraison
- [ ] Toggle UI visible, fonctionnel, persisté
- [ ] Desktop (≥1024px) : 3 colonnes, interactions fluides
- [ ] Tablet (7681023px) : Onglets + drawer, full-width contenu
- [ ] Mobile (<768px) : Bottom nav, drawer, touch-friendly
- [ ] Tous les flux clavier-seuls réalisables
- [ ] Lighthouse mobile 85 perf, 95 a11y
- [ ] Virtual scroll 60fps sur 1000+ items
- [ ] Tests E2E (toggle, breakpoints, gestures)
- [ ] Documentation complète (README_UI.md, MOBILE_GUIDE.md, RESPONSIVE_CHECKLIST.md)
- [ ] Zéro régression : legacy UI inchangée, Wikilinks, bookmarks, graph intacts
- [ ] Screenshots before/after 3 breakpoints
---
## 📖 Documentation à Produire
1. **README_UI.md** : Overview, architecture, screenshots 3 breakpoints
2. **MOBILE_GUIDE.md** : Navigation onglets, gestures, drawer patterns
3. **RESPONSIVE_CHECKLIST.md** : Tests par breakpoint, device testing
4. **DEPLOYMENT.md** : Feature flag pour bascule progressive
5. **ARCHITECTURE_DIAGRAM.md** : Schémas adaptatifs (Mermaid)
---
## 💡 Notes Importantes
- **Mobile First** : Développer pour mobile en premier, puis enrichir desktop.
- **Persistent State** : Le toggle UI et les filtres actifs doivent persister via localStorage (sans browser storage, utiliser sessionStorage ou service state).
- **Zero Regression** : L'ancienne interface reste intacte et fonctionnelle.
- **Performance** : Virtual scroll adapté mobile (40+ items à l'écran), lazy-load images.
- **Accessibility** : 44x44px touch targets minimum, ARIA labels complets, keyboard nav.
- **Testing** : Visual regression sur breakpoints clés (375px / 768px / 1440px).
---
**Exécute maintenant ce plan** : crée les composants, adapte les routes/états, ajoute les styles Tailwind responsifs, branche la recherche et livre le MR conforme aux critères ci-dessus avec toggle UI et compatibilité 100% Desktop/Mobile.