Redesign header UI with dropdown menu for vault filter and theme toggle

This commit is contained in:
Bruno Charest 2026-03-21 12:28:20 -04:00
parent ae46e62902
commit 25c7533409
3 changed files with 182 additions and 27 deletions

View File

@ -94,9 +94,15 @@
document.documentElement.setAttribute("data-theme", theme); document.documentElement.setAttribute("data-theme", theme);
localStorage.setItem("obsigate-theme", theme); localStorage.setItem("obsigate-theme", theme);
const icon = document.getElementById("theme-icon"); // Update theme button icon and label
if (icon) { const themeBtn = document.getElementById("theme-toggle");
icon.setAttribute("data-lucide", theme === "dark" ? "moon" : "sun"); const themeLabel = document.getElementById("theme-label");
if (themeBtn && themeLabel) {
const icon = themeBtn.querySelector("i");
if (icon) {
icon.setAttribute("data-lucide", theme === "dark" ? "moon" : "sun");
}
themeLabel.textContent = theme === "dark" ? "Sombre" : "Clair";
safeCreateIcons(); safeCreateIcons();
} }
@ -114,6 +120,32 @@
applyTheme(current === "dark" ? "light" : "dark"); applyTheme(current === "dark" ? "light" : "dark");
} }
function initHeaderMenu() {
const menuBtn = document.getElementById("header-menu-btn");
const menuDropdown = document.getElementById("header-menu-dropdown");
if (!menuBtn || !menuDropdown) return;
menuBtn.addEventListener("click", (e) => {
e.stopPropagation();
menuBtn.classList.toggle("active");
menuDropdown.classList.toggle("active");
});
// Close menu when clicking outside
document.addEventListener("click", (e) => {
if (!menuDropdown.contains(e.target) && e.target !== menuBtn) {
menuBtn.classList.remove("active");
menuDropdown.classList.remove("active");
}
});
// Prevent menu from closing when clicking inside
menuDropdown.addEventListener("click", (e) => {
e.stopPropagation();
});
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// API helpers // API helpers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -948,6 +980,7 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function init() { async function init() {
initTheme(); initTheme();
initHeaderMenu();
document.getElementById("theme-toggle").addEventListener("click", toggleTheme); document.getElementById("theme-toggle").addEventListener("click", toggleTheme);
document.getElementById("header-logo").addEventListener("click", goHome); document.getElementById("header-logo").addEventListener("click", goHome);
initSearch(); initSearch();

View File

@ -12,11 +12,43 @@
<!-- CodeMirror 6 --> <!-- CodeMirror 6 -->
<script type="module"> <script type="module">
import { EditorView, basicSetup } from "https://esm.sh/@codemirror/basic-setup@0.20.0"; import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine } from "https://esm.sh/@codemirror/view@6.9.0";
import { EditorState } from "https://esm.sh/@codemirror/state@6.2.0"; import { EditorState } from "https://esm.sh/@codemirror/state@6.2.0";
import { defaultHighlightStyle, syntaxHighlighting, indentOnInput, bracketMatching, foldGutter, foldKeymap } from "https://esm.sh/@codemirror/language@6.6.0";
import { defaultKeymap, history, historyKeymap } from "https://esm.sh/@codemirror/commands@6.2.3";
import { searchKeymap, highlightSelectionMatches } from "https://esm.sh/@codemirror/search@6.3.0";
import { autocompletion, completionKeymap, closeBrackets, closeBracketsKeymap } from "https://esm.sh/@codemirror/autocomplete@6.5.0";
import { markdown } from "https://esm.sh/@codemirror/lang-markdown@6.1.0"; import { markdown } from "https://esm.sh/@codemirror/lang-markdown@6.1.0";
import { oneDark } from "https://esm.sh/@codemirror/theme-one-dark@6.1.0"; import { oneDark } from "https://esm.sh/@codemirror/theme-one-dark@6.1.0";
import { keymap } from "https://esm.sh/@codemirror/view@6.9.0";
const basicSetup = [
lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
dropCursor(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
bracketMatching(),
closeBrackets(),
autocompletion(),
rectangularSelection(),
crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...searchKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
])
];
window.CodeMirror = { EditorView, EditorState, basicSetup, markdown, oneDark, keymap }; window.CodeMirror = { EditorView, EditorState, basicSetup, markdown, oneDark, keymap };
</script> </script>
</head> </head>
@ -39,13 +71,27 @@
<input type="text" id="search-input" placeholder="Recherche..." autocomplete="off"> <input type="text" id="search-input" placeholder="Recherche..." autocomplete="off">
</div> </div>
<select id="vault-filter" class="search-vault-filter"> <div class="header-menu">
<option value="all">Toutes les vaults</option> <button class="header-menu-btn" id="header-menu-btn" title="Options">
</select> <i data-lucide="settings" style="width:18px;height:18px"></i>
</button>
<button class="theme-toggle" id="theme-toggle" title="Changer le thème"> <div class="header-menu-dropdown" id="header-menu-dropdown">
<i data-lucide="moon" id="theme-icon" style="width:18px;height:18px"></i> <div class="menu-section">
</button> <div class="menu-label">Vault</div>
<select id="vault-filter" class="menu-select">
<option value="all">Tous les vaults</option>
</select>
</div>
<div class="menu-divider"></div>
<div class="menu-section">
<div class="menu-label">Thème</div>
<button class="menu-theme-btn" id="theme-toggle">
<i data-lucide="sun" style="width:16px;height:16px"></i>
<span id="theme-label">Clair</span>
</button>
</div>
</div>
</div>
</header> </header>
<!-- Main --> <!-- Main -->

View File

@ -157,19 +157,11 @@ a:hover {
pointer-events: none; pointer-events: none;
} }
.search-vault-filter { .header-menu {
padding: 6px 10px; position: relative;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--search-bg);
color: var(--text-primary);
font-family: 'JetBrains Mono', monospace;
font-size: 0.8rem;
outline: none;
cursor: pointer;
} }
.theme-toggle { .header-menu-btn {
background: none; background: none;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 8px; border-radius: 8px;
@ -180,10 +172,90 @@ a:hover {
align-items: center; align-items: center;
transition: color 200ms ease, border-color 200ms ease; transition: color 200ms ease, border-color 200ms ease;
} }
.theme-toggle:hover { .header-menu-btn:hover {
color: var(--accent); color: var(--accent);
border-color: var(--accent); border-color: var(--accent);
} }
.header-menu-btn.active {
color: var(--accent);
border-color: var(--accent);
background: var(--tag-bg);
}
.header-menu-dropdown {
display: none;
position: absolute;
top: calc(100% + 8px);
right: 0;
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
min-width: 220px;
z-index: 100;
padding: 8px;
}
.header-menu-dropdown.active {
display: block;
}
.menu-section {
padding: 8px;
}
.menu-label {
font-family: 'JetBrains Mono', monospace;
font-size: 0.7rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 6px;
font-weight: 600;
}
.menu-select {
width: 100%;
padding: 6px 10px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--search-bg);
color: var(--text-primary);
font-family: 'JetBrains Mono', monospace;
font-size: 0.8rem;
outline: none;
cursor: pointer;
transition: border-color 200ms ease;
}
.menu-select:hover, .menu-select:focus {
border-color: var(--accent);
}
.menu-divider {
height: 1px;
background: var(--border);
margin: 4px 0;
}
.menu-theme-btn {
width: 100%;
background: none;
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
cursor: pointer;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 8px;
font-family: 'JetBrains Mono', monospace;
font-size: 0.8rem;
transition: all 200ms ease;
}
.menu-theme-btn:hover {
background: var(--bg-hover);
border-color: var(--accent);
color: var(--accent);
}
/* --- Main body --- */ /* --- Main body --- */
.main-body { .main-body {
@ -938,9 +1010,13 @@ body.resizing-v {
font-size: 0.8rem; font-size: 0.8rem;
} }
.search-vault-filter { .header-menu-btn {
font-size: 0.7rem; padding: 5px 8px;
padding: 4px 6px; }
.header-menu-dropdown {
right: -8px;
min-width: 200px;
} }
.sidebar { .sidebar {