fix: retirer bouton dark/light mode du sidebar, ajouter dans Settings
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

- Sidebar: retrait du bouton 🌓 (dark/light) + bouton 🚪 logout
- Settings → Account → Preferences: nouveau sélecteur de thème (Dark/Light)
- Persistance localStorage 'fd_theme' — appliqué au chargement de chaque page
- initTheme() dans base.html + applyTheme() dans settings.html
- toggleTheme() conservé dans le JS mais plus utilisé dans l'UI
This commit is contained in:
2026-07-13 17:08:30 -04:00
parent c1f854a54a
commit e22efc1d9c
2 changed files with 107 additions and 9 deletions
+48 -9
View File
@@ -326,14 +326,6 @@
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><line x1="9" y1="15" x2="15" y2="15"/></svg>
</button>
</div>
<div style="display: flex; gap: 4px; margin-top: 4px;">
{% if user %}
<a href="/auth/logout" class="sidebar-footer-btn" style="flex:1; justify-content:center;">🚪</a>
{% else %}
<a href="/auth/login" class="sidebar-footer-btn" style="flex:1; justify-content:center;">🔑</a>
{% endif %}
<button class="sidebar-footer-btn" style="width:36px; justify-content:center;" @click="toggleTheme()">🌓</button>
</div>
</div>
</div><!-- /sidebar-scroll -->
</aside>
@@ -954,7 +946,37 @@
const html = document.documentElement;
const current = html.getAttribute('data-theme');
html.setAttribute('data-theme', current === 'dark' ? 'light' : 'dark');
localStorage.setItem('theme', current === 'dark' ? 'light' : 'dark');
localStorage.setItem('fd_theme', current === 'dark' ? 'light' : 'dark');
if (current === 'dark') {
// Switching to light
html.style.setProperty('--bg-primary', '#FFFFFF');
html.style.setProperty('--bg-secondary', '#F7F6F3');
html.style.setProperty('--bg-tertiary', '#EDECE9');
html.style.setProperty('--text', '#37352F');
html.style.setProperty('--text-secondary', '#6B6966');
html.style.setProperty('--text-dim', '#9B9A97');
html.style.setProperty('--border', '#E0DFDC');
html.style.setProperty('--border-strong', '#CCCBC8');
} else {
// Switching to dark — remove overrides, use CSS defaults
['bg-primary','bg-secondary','bg-tertiary','text','text-secondary','text-dim','border','border-strong'].forEach(function(v) {
html.style.removeProperty('--'+v);
});
}
},
initTheme() {
var saved = localStorage.getItem('fd_theme') || 'dark';
if (saved === 'light') {
document.documentElement.setAttribute('data-theme', 'light');
document.documentElement.style.setProperty('--bg-primary', '#FFFFFF');
document.documentElement.style.setProperty('--bg-secondary', '#F7F6F3');
document.documentElement.style.setProperty('--bg-tertiary', '#EDECE9');
document.documentElement.style.setProperty('--text', '#37352F');
document.documentElement.style.setProperty('--text-secondary', '#6B6966');
document.documentElement.style.setProperty('--text-dim', '#9B9A97');
document.documentElement.style.setProperty('--border', '#E0DFDC');
document.documentElement.style.setProperty('--border-strong', '#CCCBC8');
}
}
};
}
@@ -978,6 +1000,23 @@
if (active) active.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
}, 300);
});
// Apply saved theme on page load
(function() {
var saved = localStorage.getItem('fd_theme') || 'dark';
if (saved === 'light') {
var h = document.documentElement;
h.setAttribute('data-theme', 'light');
h.style.setProperty('--bg-primary', '#FFFFFF');
h.style.setProperty('--bg-secondary', '#F7F6F3');
h.style.setProperty('--bg-tertiary', '#EDECE9');
h.style.setProperty('--text', '#37352F');
h.style.setProperty('--text-secondary', '#6B6966');
h.style.setProperty('--text-dim', '#9B9A97');
h.style.setProperty('--border', '#E0DFDC');
h.style.setProperty('--border-strong', '#CCCBC8');
}
})();
</script>
<script src="/static/js/app.js?v=2.4.6" defer></script>
{% block scripts %}{% endblock %}
+59
View File
@@ -193,6 +193,38 @@
</button>
</div>
</div>
<!-- Preferences -->
<div class="setting-group">
<h3>Preferences</h3>
<div class="setting-row">
<div>
<div class="setting-label">Theme</div>
<div class="setting-desc">Choose between light and dark appearance</div>
</div>
<div class="setting-control">
<select x-model="theme" @change="applyTheme()" style="background:var(--bg-tertiary);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:13px;padding:6px 10px;outline:none;">
<option value="dark">🌙 Dark</option>
<option value="light">☀️ Light</option>
</select>
</div>
</div>
<div class="setting-row">
<div>
<div class="setting-label">Default view</div>
<div class="setting-desc">Workspace view mode when opening a workspace</div>
</div>
<div class="setting-control">
<select x-model="defaultView" @change="saveDefaultView()" style="background:var(--bg-tertiary);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:13px;padding:6px 10px;outline:none;">
<option value="tree">🌳 Tree</option>
<option value="list">📋 List</option>
<option value="details">📊 Details</option>
<option value="title">🏷️ Title</option>
<option value="content">📝 Content</option>
</select>
</div>
</div>
</div>
</div>
<!-- Notifications -->
@@ -511,6 +543,8 @@ document.addEventListener('alpine:init', function() {
userIsAdmin: {{ 'true' if user.get('is_admin') else 'false' }},
// Gitea
giteaLinked: false,
// Theme
theme: localStorage.getItem('fd_theme') || 'dark',
// Account form
accountForm: {login:'{{ user.login or "" }}', full_name:'{{ user.full_name or "" }}', email:'{{ user.email or "" }}', password:''},
accountSaving: false,
@@ -723,6 +757,31 @@ document.addEventListener('alpine:init', function() {
if (r.ok) { this.avatarUrl = ''; }
},
applyTheme() {
localStorage.setItem('fd_theme', this.theme);
document.documentElement.setAttribute('data-theme', this.theme);
if (this.theme === 'light') {
document.documentElement.style.setProperty('--bg-primary', '#FFFFFF');
document.documentElement.style.setProperty('--bg-secondary', '#F7F6F3');
document.documentElement.style.setProperty('--bg-tertiary', '#EDECE9');
document.documentElement.style.setProperty('--text', '#37352F');
document.documentElement.style.setProperty('--text-secondary', '#6B6966');
document.documentElement.style.setProperty('--text-dim', '#9B9A97');
document.documentElement.style.setProperty('--border', '#E0DFDC');
document.documentElement.style.setProperty('--border-strong', '#CCCBC8');
} else {
document.documentElement.style.removeProperty('--bg-primary');
document.documentElement.style.removeProperty('--bg-secondary');
document.documentElement.style.removeProperty('--bg-tertiary');
document.documentElement.style.removeProperty('--text');
document.documentElement.style.removeProperty('--text-secondary');
document.documentElement.style.removeProperty('--text-dim');
document.documentElement.style.removeProperty('--border');
document.documentElement.style.removeProperty('--border-strong');
document.documentElement.setAttribute('data-theme', 'dark');
}
},
saveDefaultView() {
localStorage.setItem('fd_default_view', this.defaultView);
}