Files
personotes/docs/THEMES_EXAMPLES.md

11 KiB

Exemples de Code - Système de Thèmes

Ce document contient des exemples pratiques pour travailler avec le système de thèmes.

Exemples Utilisateur

Changer de thème via la console du navigateur

// Appliquer le thème Dracula
window.themeManager.applyTheme('dracula');

// Appliquer le thème Nord
window.themeManager.applyTheme('nord');

// Obtenir le thème actuel
console.log(window.themeManager.getCurrentTheme());

// Obtenir la liste de tous les thèmes
console.log(window.themeManager.getThemes());

Vérifier quel thème est actif

// Méthode 1 : Via le ThemeManager
const currentTheme = window.themeManager.getCurrentTheme();
console.log('Thème actif:', currentTheme);

// Méthode 2 : Via l'attribut data-theme
const themeAttribute = document.documentElement.getAttribute('data-theme');
console.log('Thème actif:', themeAttribute);

// Méthode 3 : Via localStorage
const savedTheme = localStorage.getItem('app-theme');
console.log('Thème sauvegardé:', savedTheme);

Exemples Développeur

Créer un nouveau thème personnalisé

1. Définir les variables CSS dans themes.css

/* ===========================
   THEME: GITHUB DARK
   =========================== */
[data-theme="github-dark"] {
    --bg-primary: #0d1117;
    --bg-secondary: #161b22;
    --bg-tertiary: #21262d;
    --bg-elevated: #30363d;

    --border-primary: #30363d;
    --border-secondary: #21262d;

    --text-primary: #c9d1d9;
    --text-secondary: #8b949e;
    --text-muted: #484f58;

    --accent-primary: #58a6ff;
    --accent-primary-hover: #79c0ff;
    --accent-secondary: #1f6feb;
    --accent-secondary-hover: #388bfd;

    --success: #3fb950;
    --warning: #d29922;
    --error: #f85149;
}

/* Couleurs de prévisualisation */
.theme-card[data-theme="github-dark"] .theme-preview-color:nth-child(1) { background: #0d1117; }
.theme-card[data-theme="github-dark"] .theme-preview-color:nth-child(2) { background: #58a6ff; }
.theme-card[data-theme="github-dark"] .theme-preview-color:nth-child(3) { background: #1f6feb; }
.theme-card[data-theme="github-dark"] .theme-preview-color:nth-child(4) { background: #c9d1d9; }

2. Ajouter le thème dans theme-manager.js

// Dans le constructeur de ThemeManager
this.themes = [
    // ... thèmes existants
    {
        id: 'github-dark',
        name: 'GitHub Dark',
        icon: '🐙',
        description: 'Thème inspiré de GitHub avec des tons bleus et gris'
    }
];

3. Ajouter la carte dans index.html

<!-- GitHub Dark -->
<div class="theme-card" data-theme="github-dark" onclick="selectTheme('github-dark')">
    <div class="theme-card-header">
        <span class="theme-card-icon">🐙</span>
        <span class="theme-card-name">GitHub Dark</span>
    </div>
    <div class="theme-preview">
        <div class="theme-preview-color"></div>
        <div class="theme-preview-color"></div>
        <div class="theme-preview-color"></div>
        <div class="theme-preview-color"></div>
    </div>
    <p class="theme-description">Thème inspiré de GitHub avec des tons bleus et gris</p>
</div>

Écouter les changements de thème

// Créer un MutationObserver pour détecter les changements de thème
const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
        if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
            const newTheme = document.documentElement.getAttribute('data-theme');
            console.log('Thème changé vers:', newTheme);
            
            // Faire quelque chose lors du changement de thème
            // Par exemple, mettre à jour CodeMirror, Highlight.js, etc.
        }
    });
});

// Observer les changements sur l'élément <html>
observer.observe(document.documentElement, {
    attributes: true,
    attributeFilter: ['data-theme']
});

Créer un thème dynamique basé sur l'heure

function applyTimeBasedTheme() {
    const hour = new Date().getHours();
    
    if (hour >= 6 && hour < 18) {
        // Jour (6h-18h) - utiliser un thème plus lumineux
        window.themeManager.applyTheme('solarized-dark');
    } else if (hour >= 18 && hour < 22) {
        // Soirée (18h-22h) - utiliser un thème doux
        window.themeManager.applyTheme('one-dark');
    } else {
        // Nuit (22h-6h) - utiliser un thème très sombre
        window.themeManager.applyTheme('material-dark');
    }
}

// Appliquer au chargement
applyTimeBasedTheme();

// Vérifier toutes les heures
setInterval(applyTimeBasedTheme, 3600000);

Thème aléatoire au chargement

function applyRandomTheme() {
    const themes = window.themeManager.getThemes();
    const randomIndex = Math.floor(Math.random() * themes.length);
    const randomTheme = themes[randomIndex];
    
    window.themeManager.applyTheme(randomTheme.id);
    console.log('Thème aléatoire appliqué:', randomTheme.name);
}

// Utilisation
// applyRandomTheme();

Créer un raccourci clavier

// Ctrl+T pour ouvrir/fermer la modale de thèmes
document.addEventListener('keydown', (e) => {
    // Ctrl+T ou Cmd+T
    if ((e.ctrlKey || e.metaKey) && e.key === 't') {
        e.preventDefault();
        
        const modal = document.getElementById('theme-modal');
        if (modal.style.display === 'flex') {
            window.closeThemeModal();
        } else {
            window.openThemeModal();
        }
    }
});

// Ctrl+Shift+T pour passer au thème suivant
document.addEventListener('keydown', (e) => {
    if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'T') {
        e.preventDefault();
        
        const themes = window.themeManager.getThemes();
        const currentTheme = window.themeManager.getCurrentTheme();
        const currentIndex = themes.findIndex(t => t.id === currentTheme);
        const nextIndex = (currentIndex + 1) % themes.length;
        
        window.themeManager.applyTheme(themes[nextIndex].id);
        console.log('Thème suivant:', themes[nextIndex].name);
    }
});

Adapter CodeMirror au thème

// Mapper les thèmes de l'app aux thèmes CodeMirror
const codemirrorThemeMap = {
    'material-dark': 'material-darker',
    'monokai-dark': 'monokai',
    'dracula': 'dracula',
    'one-dark': 'one-dark',
    'solarized-dark': 'solarized dark',
    'nord': 'nord'
};

// Observer les changements de thème
const observer = new MutationObserver(() => {
    const currentTheme = window.themeManager.getCurrentTheme();
    const cmTheme = codemirrorThemeMap[currentTheme] || 'material-darker';
    
    // Si vous utilisez CodeMirror
    if (window.editor && typeof window.editor.setOption === 'function') {
        window.editor.setOption('theme', cmTheme);
        console.log('CodeMirror thème changé vers:', cmTheme);
    }
});

observer.observe(document.documentElement, {
    attributes: true,
    attributeFilter: ['data-theme']
});

Exporter/Importer les préférences utilisateur

// Exporter les préférences
function exportPreferences() {
    const prefs = {
        theme: window.themeManager.getCurrentTheme(),
        timestamp: new Date().toISOString()
    };
    
    const blob = new Blob([JSON.stringify(prefs, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'project-notes-preferences.json';
    a.click();
    URL.revokeObjectURL(url);
}

// Importer les préférences
function importPreferences(file) {
    const reader = new FileReader();
    reader.onload = (e) => {
        try {
            const prefs = JSON.parse(e.target.result);
            if (prefs.theme) {
                window.themeManager.applyTheme(prefs.theme);
                console.log('Préférences importées:', prefs);
            }
        } catch (error) {
            console.error('Erreur lors de l\'importation:', error);
        }
    };
    reader.readAsText(file);
}

Créer un prévisualisateur de thème en direct

// Créer une fonction pour prévisualiser un thème sans le sauvegarder
function previewTheme(themeId) {
    // Sauvegarder le thème actuel
    const originalTheme = window.themeManager.getCurrentTheme();
    
    // Appliquer temporairement le nouveau thème
    document.documentElement.setAttribute('data-theme', themeId);
    
    // Retourner une fonction pour annuler
    return () => {
        document.documentElement.setAttribute('data-theme', originalTheme);
    };
}

// Utilisation
const cancelPreview = previewTheme('dracula');

// Après quelques secondes, annuler
setTimeout(() => {
    cancelPreview();
}, 3000);

Intégration avec d'autres bibliothèques

Highlight.js

// Adapter le thème Highlight.js
const highlightThemeMap = {
    'material-dark': 'atom-one-dark',
    'monokai-dark': 'monokai',
    'dracula': 'dracula',
    'one-dark': 'atom-one-dark',
    'solarized-dark': 'solarized-dark',
    'nord': 'nord'
};

function updateHighlightTheme(themeId) {
    const hlTheme = highlightThemeMap[themeId] || 'atom-one-dark';
    const linkElement = document.querySelector('link[href*="highlight.js"]');
    
    if (linkElement) {
        linkElement.href = `https://cdn.jsdelivr.net/npm/highlight.js@11.9.0/styles/${hlTheme}.min.css`;
    }
}

Marked.js (déjà intégré)

Le système de thèmes fonctionne automatiquement avec Marked.js car il utilise les variables CSS globales.

Débogage

Afficher toutes les variables CSS actives

// Obtenir toutes les variables CSS définies sur :root
function getCurrentThemeVariables() {
    const root = document.documentElement;
    const styles = getComputedStyle(root);
    const variables = {};
    
    // Liste des variables de thème
    const varNames = [
        '--bg-primary', '--bg-secondary', '--bg-tertiary', '--bg-elevated',
        '--border-primary', '--border-secondary',
        '--text-primary', '--text-secondary', '--text-muted',
        '--accent-primary', '--accent-secondary',
        '--success', '--warning', '--error'
    ];
    
    varNames.forEach(varName => {
        variables[varName] = styles.getPropertyValue(varName).trim();
    });
    
    return variables;
}

// Afficher
console.table(getCurrentThemeVariables());

Vérifier si un thème est chargé

function isThemeLoaded(themeId) {
    // Appliquer temporairement le thème
    const originalTheme = document.documentElement.getAttribute('data-theme');
    document.documentElement.setAttribute('data-theme', themeId);
    
    // Vérifier si les variables CSS sont définies
    const primaryBg = getComputedStyle(document.documentElement)
        .getPropertyValue('--bg-primary').trim();
    
    // Restaurer le thème original
    document.documentElement.setAttribute('data-theme', originalTheme);
    
    return primaryBg !== '';
}

// Vérifier tous les thèmes
window.themeManager.getThemes().forEach(theme => {
    console.log(theme.name, ':', isThemeLoaded(theme.id) ? '✅' : '❌');
});

Conclusion

Ces exemples couvrent la plupart des cas d'usage courants. Pour plus d'informations, consultez :

  • docs/THEMES.md - Documentation technique complète
  • docs/GUIDE_THEMES.md - Guide utilisateur
  • frontend/src/theme-manager.js - Code source du gestionnaire