# Système de Théming ObsiViewer - Documentation ## Vue d'ensemble Système de théming double dimension : **7 thèmes × 2 modes = 14 combinaisons** - **Modes** : Light, Dark - **Thèmes** : Light (default), Dark (default), Obsidian, Nord, Notion, GitHub, Discord, Monokai ## Architecture ### 1. Tokens CSS (`src/styles/themes.css`) Tous les thèmes définissent un ensemble cohérent de tokens CSS : ```css /* Backgrounds */ --bg, --bg-main, --bg-muted --card, --card-bg, --elevated --sidebar-bg, --surface-1, --surface-2 /* Text */ --fg, --text-main, --text-muted, --muted /* Borders */ --border /* Brand & Accents */ --primary, --brand, --brand-700, --brand-800 --secondary, --accent /* Status */ --success, --warning, --danger, --info /* UI Elements */ --chip-bg, --link, --link-hover, --ring /* Editor (CodeMirror 6) */ --editor-bg, --editor-fg, --editor-selection --editor-gutter-bg, --editor-gutter-fg, --editor-cursor /* Shadows */ --shadow-color, --scrollbar-thumb ``` ### 2. Configuration Tailwind (`tailwind.config.js`) Tous les tokens sont mappés dans Tailwind : ```javascript colors: { bg: 'var(--bg)', 'bg-main': 'var(--bg-main)', fg: 'var(--fg)', surface1: 'var(--surface-1)', primary: 'var(--primary)', // ... etc } ``` ### 3. ThemeService (`src/app/core/services/theme.service.ts`) Service central qui gère : - Mode : `'system' | 'light' | 'dark'` - Thème : `'light' | 'dark' | 'obsidian' | 'nord' | 'notion' | 'github' | 'discord' | 'monokai'` - Application sur `` : classe `.dark` + attribut `data-theme` - Persistance dans localStorage - Observable `onPrefs$` pour réactivité ### 4. CodeMirror 6 (`src/app/core/codemirror-themes.ts`) Fonction `cm6ThemeFor(themeId, mode)` qui retourne les extensions CM6 appropriées pour chaque combinaison thème/mode. ### 5. Anti-FOUC (`index.html`) Script inline qui lit les préférences et applique le thème avant le chargement d'Angular : ```javascript (function () { const prefs = JSON.parse(localStorage.getItem('obsiviewer.preferences.v1') || '{}'); const isDark = prefs.mode === 'dark' || (prefs.mode === 'system' && prefersDark); html.classList.toggle('dark', isDark); html.setAttribute('data-theme', prefs.theme || 'light'); })(); ``` ## Matrice des Thèmes ### Light (Default) - **Light mode** : Blanc pur, texte gris foncé, accents bleus - **Dark mode** : N/A (thème light uniquement) ### Dark (Default) - **Light mode** : N/A (thème dark uniquement) - **Dark mode** : Fond bleu-gris foncé, texte clair, accents bleus clairs ### Obsidian - **Light mode** : Beige chaud (#fafaf8), texte anthracite, accents terre - **Dark mode** : Gris très foncé (#1e1e1e), texte clair, accents beiges ### Nord - **Light mode** : Blanc neigeux (#eceff4), texte bleu-gris, palette nordique pastel - **Dark mode** : Bleu-gris arctique (#2e3440), texte givré, palette nordique ### Notion - **Light mode** : Blanc pur, texte charbon, minimaliste - **Dark mode** : Noir profond (#171717), texte ivoire, contraste élevé ### GitHub - **Light mode** : Blanc, texte GitHub (#24292f), palette GitHub - **Dark mode** : Dimmed dark (#0d1117), palette GitHub dark ### Discord - **Light mode** : Gris très clair (#f6f7f9), texte foncé, violet Discord - **Dark mode** : Gris Discord (#2b2d31), texte clair, violet Discord ### Monokai - **Light mode** : Crème (#fbfbf7), texte foncé, accents verts/oranges atténués - **Dark mode** : Vert-gris foncé (#272822), texte clair, palette Monokai classique ## Utilisation dans les Composants ### Classes Tailwind recommandées ```html
Carte
Surface niveau 1
Surface niveau 2

Texte principal

Texte secondaire

Bordure
Lien ``` ### ⚠️ À ÉVITER ```html
...
...
...
``` ## Tests ### Checklist de validation Pour chaque combinaison (14 au total) : - [ ] **Sidebar** : Fond, hover, items actifs, badges - [ ] **Topbar** : Barre de recherche, focus, placeholder - [ ] **Liste des notes** : Items, hover, selected, path muted - [ ] **Page détail** : Titres, liens, listes, blockquotes, code, tables - [ ] **Mode édition** : Inputs, buttons, toolbars, CodeMirror - [ ] **Panneaux** : TOC, propriétés, tags - [ ] **Modales** : Fond, bordure, overlay - [ ] **Menus contextuels** : Dropdown, tooltips - [ ] **Toasts** : Fond, bordure, barre de progression - [ ] **Tables** : Headers, zebra, hover - [ ] **Chips/Tags** : Fond, texte, bordure, hover, selected - [ ] **Scrollbars** : Thumb, track - [ ] **Page Parameters** : Contrôles mode/thème - [ ] **Mobile** : Bottom nav, sheets, drawers ### Contraste Tous les thèmes doivent respecter WCAG AA : - Texte normal : ratio ≥ 4.5:1 - Texte large : ratio ≥ 3:1 ## Refactoring effectué ### Automatisé (script `refactor-colors.mjs`) - ✅ 66 fichiers mis à jour automatiquement - ✅ Remplacement de 232+ occurrences de couleurs hardcodées - ✅ Gestion des variantes : hover, focus, dark ### Restant (109 occurrences) Cas complexes nécessitant révision manuelle : - Composants avec logique conditionnelle - Styles inline dynamiques - Cas spécifiques métier ## Commandes utiles ```bash # Lancer le refactoring automatique node scripts/refactor-colors.mjs # Rechercher les couleurs hardcodées restantes grep -r "bg-slate-\|bg-gray-\|text-slate-\|text-gray-" src/ # Lancer l'application en mode dev npm run dev # Tests E2E npm run test:e2e ``` ## Prochaines étapes 1. ✅ Créer themes.css avec 14 variantes 2. ✅ Configurer Tailwind 3. ✅ Mettre à jour codemirror-themes.ts 4. ✅ Refactoring automatisé (68% des couleurs) 5. 🔄 Refactoring manuel des 109 occurrences restantes 6. ⏳ Tests matrice complète 7. ⏳ Validation contrastes 8. ⏳ Documentation utilisateur ## Notes techniques - **Persistance** : `localStorage` clé `obsiviewer.preferences.v1` - **Réactivité** : Observable `ThemeService.onPrefs$` - **SSR-safe** : Vérifications `typeof window !== 'undefined'` - **Performance** : Transitions CSS 150ms - **Accessibilité** : `color-scheme` CSS pour scrollbars natives ## Ressources - [Tailwind CSS Variables](https://tailwindcss.com/docs/customizing-colors#using-css-variables) - [CodeMirror 6 Theming](https://codemirror.net/docs/ref/#view.EditorView^theme) - [WCAG Contrast Guidelines](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html)