240 lines
6.7 KiB
Markdown
240 lines
6.7 KiB
Markdown
# 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 `<html>` : 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
|
||
<!-- Backgrounds -->
|
||
<div class="bg-card">Carte</div>
|
||
<div class="bg-surface1">Surface niveau 1</div>
|
||
<div class="bg-surface2">Surface niveau 2</div>
|
||
|
||
<!-- Text -->
|
||
<p class="text-main">Texte principal</p>
|
||
<p class="text-muted">Texte secondaire</p>
|
||
|
||
<!-- Borders -->
|
||
<div class="border border-border">Bordure</div>
|
||
|
||
<!-- Interactive -->
|
||
<button class="bg-primary text-white hover:bg-brand-700">
|
||
Action
|
||
</button>
|
||
|
||
<!-- Links -->
|
||
<a class="text-link hover:text-link-hover">Lien</a>
|
||
```
|
||
|
||
### ⚠️ À ÉVITER
|
||
|
||
```html
|
||
<!-- ❌ Couleurs hardcodées -->
|
||
<div class="bg-slate-100 text-gray-900">...</div>
|
||
<div class="dark:bg-gray-800">...</div>
|
||
|
||
<!-- ✅ Utiliser les tokens -->
|
||
<div class="bg-surface1 text-main">...</div>
|
||
```
|
||
|
||
## 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)
|