Redesign header UI with dropdown menu for vault filter and theme toggle
This commit is contained in:
parent
ae46e62902
commit
25c7533409
@ -94,9 +94,15 @@
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
localStorage.setItem("obsigate-theme", theme);
|
||||
|
||||
const icon = document.getElementById("theme-icon");
|
||||
if (icon) {
|
||||
icon.setAttribute("data-lucide", theme === "dark" ? "moon" : "sun");
|
||||
// Update theme button icon and label
|
||||
const themeBtn = document.getElementById("theme-toggle");
|
||||
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();
|
||||
}
|
||||
|
||||
@ -114,6 +120,32 @@
|
||||
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
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -948,6 +980,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
async function init() {
|
||||
initTheme();
|
||||
initHeaderMenu();
|
||||
document.getElementById("theme-toggle").addEventListener("click", toggleTheme);
|
||||
document.getElementById("header-logo").addEventListener("click", goHome);
|
||||
initSearch();
|
||||
|
||||
@ -12,11 +12,43 @@
|
||||
|
||||
<!-- CodeMirror 6 -->
|
||||
<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 { 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 { 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 };
|
||||
</script>
|
||||
</head>
|
||||
@ -39,13 +71,27 @@
|
||||
<input type="text" id="search-input" placeholder="Recherche..." autocomplete="off">
|
||||
</div>
|
||||
|
||||
<select id="vault-filter" class="search-vault-filter">
|
||||
<option value="all">Toutes les vaults</option>
|
||||
</select>
|
||||
|
||||
<button class="theme-toggle" id="theme-toggle" title="Changer le thème">
|
||||
<i data-lucide="moon" id="theme-icon" style="width:18px;height:18px"></i>
|
||||
</button>
|
||||
<div class="header-menu">
|
||||
<button class="header-menu-btn" id="header-menu-btn" title="Options">
|
||||
<i data-lucide="settings" style="width:18px;height:18px"></i>
|
||||
</button>
|
||||
<div class="header-menu-dropdown" id="header-menu-dropdown">
|
||||
<div class="menu-section">
|
||||
<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>
|
||||
|
||||
<!-- Main -->
|
||||
|
||||
@ -157,19 +157,11 @@ a:hover {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.search-vault-filter {
|
||||
padding: 6px 10px;
|
||||
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;
|
||||
.header-menu {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
.header-menu-btn {
|
||||
background: none;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
@ -180,10 +172,90 @@ a:hover {
|
||||
align-items: center;
|
||||
transition: color 200ms ease, border-color 200ms ease;
|
||||
}
|
||||
.theme-toggle:hover {
|
||||
.header-menu-btn:hover {
|
||||
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 {
|
||||
@ -938,9 +1010,13 @@ body.resizing-v {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.search-vault-filter {
|
||||
font-size: 0.7rem;
|
||||
padding: 4px 6px;
|
||||
.header-menu-btn {
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
.header-menu-dropdown {
|
||||
right: -8px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user