feat: #65 systeme de themes — 15 themes x dark/light
- themes.js: 15 palettes (Defaut ObsiGate, GitHub, Linear, Spotify, Notion, Discord, Dracula, One Dark, Tokyo Night, Nord, Night Owl, Anthracite, Cyberpunk, Navy Elegance, Tons Terreux) - Chaque theme a un mode sombre ET clair - UI: grille de themes dans Configuration → Themes - Toggle Sombre/Clair par theme - Persistance localStorage (obsigate-theme + obsigate-theme-mode) - Preview visuel: barre de couleur + accent bouton - initThemes() appele au startup dans sync.js - Defaut ObsiGate conserve le theme actuel
This commit is contained in:
@@ -641,6 +641,9 @@ function initConfigModal() {
|
||||
|
||||
// Load saved frontend config on startup
|
||||
applyFrontendConfig();
|
||||
|
||||
// Init theme picker
|
||||
initThemePicker();
|
||||
}
|
||||
|
||||
function closeConfigModal() {
|
||||
@@ -1382,5 +1385,69 @@ export {
|
||||
initEditorPocBtn,
|
||||
loadAbout as initAboutSection,
|
||||
loadHiddenFilesSettings as initHiddenFilesConfig,
|
||||
initThemePicker,
|
||||
switchSidebarTab,
|
||||
};
|
||||
|
||||
// ── Theme Picker ─────────────────────────────────────────────────────
|
||||
function initThemePicker() {
|
||||
import('./themes.js').then(function(mod) {
|
||||
var THEMES = mod.THEMES;
|
||||
var applyTheme = mod.applyTheme;
|
||||
var getCurrentTheme = mod.getCurrentTheme;
|
||||
var getCurrentMode = mod.getCurrentMode;
|
||||
|
||||
var grid = document.getElementById('theme-grid');
|
||||
if (!grid) return;
|
||||
|
||||
var themeKeys = Object.keys(THEMES);
|
||||
|
||||
function renderCards() {
|
||||
var current = getCurrentTheme();
|
||||
var mode = getCurrentMode();
|
||||
grid.innerHTML = '';
|
||||
themeKeys.forEach(function(key) {
|
||||
var t = THEMES[key];
|
||||
var v = t.modes[mode];
|
||||
if (!v) return;
|
||||
var card = document.createElement('div');
|
||||
card.className = 'theme-card' + (key === current ? ' active' : '');
|
||||
card.innerHTML =
|
||||
'<div class="theme-card-preview">' +
|
||||
'<div class="theme-card-preview-bar" style="background:' + (v['--bg-sidebar'] || v['--bg-primary']) + '"></div>' +
|
||||
'<div class="theme-card-preview-body" style="background:' + (v['--bg-primary'] || '#000') + '">' +
|
||||
'<div class="theme-card-preview-btn" style="background:' + (v['--accent'] || '#58a6ff') + '"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="theme-card-name">' + t.name + '</div>' +
|
||||
'<div class="theme-card-desc">' + t.desc + '</div>';
|
||||
card.addEventListener('click', function() {
|
||||
applyTheme(key, mode);
|
||||
renderCards();
|
||||
});
|
||||
grid.appendChild(card);
|
||||
});
|
||||
// Mode toggle
|
||||
var toggle = document.createElement('div');
|
||||
toggle.className = 'theme-mode-toggle';
|
||||
var dBtn = elBtn('Sombre', 'dark', mode);
|
||||
var lBtn = elBtn('Clair', 'light', mode);
|
||||
toggle.appendChild(dBtn);
|
||||
toggle.appendChild(lBtn);
|
||||
grid.appendChild(toggle);
|
||||
}
|
||||
|
||||
function elBtn(label, m, currentMode) {
|
||||
var btn = document.createElement('button');
|
||||
btn.className = 'theme-mode-btn' + (m === currentMode ? ' active' : '');
|
||||
btn.textContent = label;
|
||||
btn.addEventListener('click', function() {
|
||||
applyTheme(getCurrentTheme(), m);
|
||||
renderCards();
|
||||
});
|
||||
return btn;
|
||||
}
|
||||
|
||||
renderCards();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user