fix(theme): support full dynamic Light Mode and Dark Mode with CSS variables and storage sync

This commit is contained in:
asepharyana committed 2026-08-21 11:13:05 +07:00
1 parent 62116be88d
commit aedfb022f3
16 files changed
+464 -348

No files matched your search

+24 -24
View File
@@ -91,13 +91,13 @@ export default function CommandMenu() {
return (
<button
onClick={() => setOpen(true)}
className="hidden md:flex items-center gap-2 px-3 py-1.5 bg-[#141517] hover:bg-[#1b1d20] border border-[#23252a] hover:border-[#383b42] text-xs text-[#8a8f98] hover:text-[#d0d6e0] rounded-lg transition-all shadow-inner"
className="hidden md:flex items-center gap-2 px-3 py-1.5 bg-[var(--bg-surface)] hover:bg-[var(--bg-elevated)] border border-[var(--border-color)] hover:border-[var(--brand)] text-xs text-[var(--text-muted)] hover:text-[var(--text-primary)] rounded-lg transition-all shadow-sm"
>
<svg className="w-3.5 h-3.5 text-[#62666d]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg className="w-3.5 h-3.5 text-[var(--text-dim)]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<span>Search documentation...</span>
<kbd className="ml-2 font-mono bg-[#08090a] px-1.5 py-0.5 rounded border border-[#1f2022] text-[10px] text-[#62666d]">
<span>Search docs...</span>
<kbd className="ml-2 font-mono bg-[var(--bg-elevated)] px-1.5 py-0.5 rounded border border-[var(--border-color)] text-[10px] text-[var(--text-dim)]">
⌘K
</kbd>
</button>
@@ -108,15 +108,15 @@ export default function CommandMenu() {
<div className="fixed inset-0 z-50 flex items-start justify-center pt-20 px-4">
{/* Backdrop */}
<div
className="fixed inset-0 bg-black/70 backdrop-blur-sm transition-opacity"
className="fixed inset-0 bg-black/60 dark:bg-black/80 backdrop-blur-sm transition-opacity"
onClick={() => setOpen(false)}
/>
{/* Modal */}
<div className="relative w-full max-w-2xl bg-[#0f1011] border border-[#27292d] rounded-xl shadow-2xl overflow-hidden animate-fade-in">
<div className="relative w-full max-w-2xl bg-[var(--bg-surface)] border border-[var(--border-color)] rounded-xl shadow-2xl overflow-hidden animate-fade-in">
{/* Search input bar */}
<div className="flex items-center gap-3 px-4 py-3.5 border-b border-[#1f2022] bg-[#141517]">
<svg className="w-5 h-5 text-[#7170ff] shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<div className="flex items-center gap-3 px-4 py-3.5 border-b border-[var(--border-color)] bg-[var(--bg-elevated)]">
<svg className="w-5 h-5 text-[#5e6ad2] dark:text-[#7170ff] shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<input
@@ -126,14 +126,14 @@ export default function CommandMenu() {
onChange={(e) => setQuery(e.target.value)}
onKeyDown={handleKeyNavigation}
placeholder="Type to search (titles, keywords, concepts)..."
className="w-full bg-transparent text-[#f7f8f8] placeholder-[#62666d] text-sm focus:outline-none"
className="w-full bg-transparent text-[var(--text-primary)] placeholder-[var(--text-dim)] text-sm focus:outline-none"
/>
{loading && (
<div className="w-4 h-4 border-2 border-[#5e6ad2] border-t-transparent rounded-full animate-spin shrink-0" />
)}
<button
onClick={() => setOpen(false)}
className="text-xs text-[#62666d] hover:text-[#d0d6e0] bg-[#1b1d20] px-1.5 py-0.5 rounded border border-[#27292d]"
className="text-xs text-[var(--text-muted)] hover:text-[var(--text-primary)] bg-[var(--bg-surface)] px-1.5 py-0.5 rounded border border-[var(--border-color)]"
>
ESC
</button>
@@ -143,14 +143,14 @@ export default function CommandMenu() {
<div className="max-h-96 overflow-y-auto p-2">
{query.trim() === "" ? (
<div className="px-3 py-6 text-center">
<p className="text-xs text-[#8a8f98]">Search full-text, semantic embeddings, and CTF writeups.</p>
<div className="flex justify-center gap-2 mt-3 text-[11px] text-[#62666d]">
<span>Navigation: <kbd className="bg-[#141517] px-1 py-0.5 rounded border border-[#1f2022]">↑</kbd> <kbd className="bg-[#141517] px-1 py-0.5 rounded border border-[#1f2022]">↓</kbd></span>
<span>Select: <kbd className="bg-[#141517] px-1 py-0.5 rounded border border-[#1f2022]">↵</kbd></span>
<p className="text-xs text-[var(--text-muted)]">Search full-text, semantic embeddings, and CTF writeups.</p>
<div className="flex justify-center gap-2 mt-3 text-[11px] text-[var(--text-dim)]">
<span>Navigation: <kbd className="bg-[var(--bg-elevated)] px-1 py-0.5 rounded border border-[var(--border-color)]">↑</kbd> <kbd className="bg-[var(--bg-elevated)] px-1 py-0.5 rounded border border-[var(--border-color)]">↓</kbd></span>
<span>Select: <kbd className="bg-[var(--bg-elevated)] px-1 py-0.5 rounded border border-[var(--border-color)]">↵</kbd></span>
</div>
</div>
) : results.length === 0 && !loading ? (
<div className="px-4 py-8 text-center text-xs text-[#8a8f98]">
<div className="px-4 py-8 text-center text-xs text-[var(--text-muted)]">
No documents matching &quot;{query}&quot;
</div>
) : (
@@ -164,27 +164,27 @@ export default function CommandMenu() {
onMouseEnter={() => setSelectedIndex(index)}
className={`flex items-start justify-between gap-3 px-3 py-2.5 rounded-lg cursor-pointer transition-all ${
isSelected
? "bg-[#5e6ad2]/15 border border-[#5e6ad2]/40 text-[#f7f8f8]"
: "hover:bg-[#141517] text-[#d0d6e0] border border-transparent"
? "bg-[#5e6ad2]/15 border border-[#5e6ad2]/40 text-[var(--text-primary)]"
: "hover:bg-[var(--bg-elevated)] text-[var(--text-secondary)] border border-transparent"
}`}
>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<span className="text-xs px-1.5 py-0.25 bg-[#191a1b] border border-[#23252a] rounded text-[#7170ff] font-mono">
<span className="text-xs px-1.5 py-0.25 bg-[var(--bg-elevated)] border border-[var(--border-color)] rounded text-[#5e6ad2] dark:text-[#7170ff] font-mono">
{hit.section}
</span>
<span className={`text-sm font-medium ${isSelected ? "text-[#7170ff]" : "text-[#f7f8f8]"} truncate`}>
<span className={`text-sm font-medium ${isSelected ? "text-[#5e6ad2] dark:text-[#7170ff]" : "text-[var(--text-primary)]"} truncate`}>
{hit.title}
</span>
</div>
{hit.snippet && (
<p
className="text-xs text-[#8a8f98] mt-1 line-clamp-1 [&>mark]:bg-[#5e6ad2]/30 [&>mark]:text-[#f7f8f8] [&>mark]:rounded [&>mark]:px-0.5"
className="text-xs text-[var(--text-muted)] mt-1 line-clamp-1 [&>mark]:bg-[#5e6ad2]/30 [&>mark]:text-[var(--text-primary)] [&>mark]:rounded [&>mark]:px-0.5"
dangerouslySetInnerHTML={{ __html: hit.snippet }}
/>
)}
</div>
<span className="text-[11px] text-[#62666d] shrink-0 self-center">
<span className="text-[11px] text-[var(--text-dim)] shrink-0 self-center">
{hit.slug}
</span>
</li>
@@ -195,12 +195,12 @@ export default function CommandMenu() {
</div>
{/* Footer */}
<div className="flex items-center justify-between px-4 py-2.5 border-t border-[#1f2022] bg-[#0c0d0e] text-[11px] text-[#62666d]">
<span>Tip: Press <kbd className="bg-[#141517] px-1 py-0.5 rounded border border-[#1f2022]">Hybrid</kbd> search is enabled by default</span>
<div className="flex items-center justify-between px-4 py-2.5 border-t border-[var(--border-color)] bg-[var(--bg-elevated)] text-[11px] text-[var(--text-dim)]">
<span>Tip: Press <kbd className="bg-[var(--bg-surface)] px-1 py-0.5 rounded border border-[var(--border-color)]">Hybrid</kbd> search is enabled</span>
<Link
href={`/search?q=${encodeURIComponent(query)}`}
onClick={() => setOpen(false)}
className="hover:text-[#7170ff] transition-colors"
className="hover:text-[#5e6ad2] dark:hover:text-[#7170ff] transition-colors"
>
Open full search page →
</Link>