ObsiViewer/docs/PROMPTS/Nimbus_Interface/ObsiViewer_NewInterface_Nimbus.md

25 KiB
Raw Blame History

🎯 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 :

<!-- 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 :

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 :

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)

// 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

// 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

// 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)

// 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)

<!-- 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)

<!-- 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)

<!-- 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)

<!-- 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)

<!-- 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)

// 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)

  • Layout 3 colonnes (sidebar fixe/resizable, liste, page+ToC)
  • Changement dossier/tag/tri reflété en URL
  • 1000+ items fluide (60fps virtual scroll)
  • ToC synchronisé + repliable
  • Tous les flux clavier-seuls possibles

Tablet (7681023px)

  • Navigation par onglets (Sidebar / List / Page)
  • Drawer sidebar (80vw, swipeable)
  • Bottom navigation sticky (4 icônes)
  • Contenu full-width par onglet
  • ToC inline collapsible

Mobile (<768px)

  • Drawer sidebar (80vw max)
  • Bottom nav (4 onglets)
  • Search bar compact (menu + search + filters)
  • List items optimisés (titre + date + excerpt)
  • Markdown full-screen
  • ToC overlay ou inline toggle
  • Touch targets ≥ 44x44px

Feature Flag

  • Toggle UI visible dans navbar
  • État persisté (localStorage)
  • Pas de perte d'état lors du switch
  • Legacy UI reste intacte

Accessibility

  • WCAG 2.1 AA sur tous les breakpoints
  • Keyboard navigation complète (Tab, Arrow, Enter)
  • ARIA labels pour navigation tactile
  • Focus visible partout
  • Zoom ≤ 200% sans horizontal scroll

Performance

  • TTI < 2.5s cold start
  • Scroll 60fps sur 1000+ items
  • Lighthouse Mobile ≥ 85 perf, ≥ 95 a11y
  • 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

# 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.