feat(dashboard): add light/dark theme with sidebar toggle (#81)
This commit was merged in pull request #81.
This commit is contained in:
@@ -61,6 +61,77 @@
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
/* ── Light theme tokens ──
|
||||
Applied when the user has explicitly chosen light (`data-theme="light"`)
|
||||
OR when their OS prefers light AND they have made no explicit choice. */
|
||||
:root[data-theme="light"] {
|
||||
--bg-primary: #f5f7fb;
|
||||
--bg-secondary: #ffffff;
|
||||
--bg-card: rgba(255, 255, 255, 0.85);
|
||||
--bg-card-solid: #ffffff;
|
||||
--bg-card-hover: #f1f5fb;
|
||||
--bg-elevated: #f8fafc;
|
||||
|
||||
--text-primary: #0c1426;
|
||||
--text-secondary: #475569;
|
||||
--text-tertiary: #8a9bb4;
|
||||
|
||||
--accent: #0070d4;
|
||||
--accent-hover: #0080f0;
|
||||
--accent-muted: rgba(0, 112, 212, 0.10);
|
||||
--accent-glow: 0 0 20px rgba(0, 112, 212, 0.10);
|
||||
|
||||
--border: #e2e8f0;
|
||||
--border-bright: #cbd5e1;
|
||||
--border-accent: rgba(0, 112, 212, 0.30);
|
||||
|
||||
--danger: #dc2626;
|
||||
--danger-bg: rgba(220, 38, 38, 0.08);
|
||||
--warning: #d97706;
|
||||
--warning-bg: rgba(217, 119, 6, 0.08);
|
||||
--success: #16a34a;
|
||||
--success-bg: rgba(22, 163, 74, 0.08);
|
||||
--info: #2563eb;
|
||||
--info-bg: rgba(37, 99, 235, 0.08);
|
||||
--orange: #ea580c;
|
||||
--orange-bg: rgba(234, 88, 12, 0.08);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root:not([data-theme="dark"]) {
|
||||
--bg-primary: #f5f7fb;
|
||||
--bg-secondary: #ffffff;
|
||||
--bg-card: rgba(255, 255, 255, 0.85);
|
||||
--bg-card-solid: #ffffff;
|
||||
--bg-card-hover: #f1f5fb;
|
||||
--bg-elevated: #f8fafc;
|
||||
|
||||
--text-primary: #0c1426;
|
||||
--text-secondary: #475569;
|
||||
--text-tertiary: #8a9bb4;
|
||||
|
||||
--accent: #0070d4;
|
||||
--accent-hover: #0080f0;
|
||||
--accent-muted: rgba(0, 112, 212, 0.10);
|
||||
--accent-glow: 0 0 20px rgba(0, 112, 212, 0.10);
|
||||
|
||||
--border: #e2e8f0;
|
||||
--border-bright: #cbd5e1;
|
||||
--border-accent: rgba(0, 112, 212, 0.30);
|
||||
|
||||
--danger: #dc2626;
|
||||
--danger-bg: rgba(220, 38, 38, 0.08);
|
||||
--warning: #d97706;
|
||||
--warning-bg: rgba(217, 119, 6, 0.08);
|
||||
--success: #16a34a;
|
||||
--success-bg: rgba(22, 163, 74, 0.08);
|
||||
--info: #2563eb;
|
||||
--info-bg: rgba(37, 99, 235, 0.08);
|
||||
--orange: #ea580c;
|
||||
--orange-bg: rgba(234, 88, 12, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ── Reset & Base ── */
|
||||
|
||||
@@ -396,6 +467,44 @@ code {
|
||||
background: rgba(0, 200, 255, 0.06);
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
border-top: 1px solid var(--border);
|
||||
color: var(--text-secondary);
|
||||
padding: 11px 18px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 11px;
|
||||
font-family: var(--font-body);
|
||||
font-size: 13.5px;
|
||||
font-weight: 500;
|
||||
transition: color 0.2s, background 0.2s;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
color: var(--accent);
|
||||
background: var(--accent-muted);
|
||||
}
|
||||
|
||||
.theme-toggle svg {
|
||||
flex-shrink: 0;
|
||||
opacity: 0.75;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.theme-toggle:hover svg {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .theme-toggle {
|
||||
justify-content: center;
|
||||
padding: 11px 0;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .sidebar-header {
|
||||
padding: 22px 0;
|
||||
justify-content: center;
|
||||
@@ -3889,3 +3998,33 @@ tbody tr:last-child td {
|
||||
.copyable code, .copyable .mono { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.code-snippet-wrapper { position: relative; }
|
||||
.code-snippet-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; gap: 8px; }
|
||||
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════
|
||||
LIGHT THEME — surface overrides for the few hardcoded dark
|
||||
colors that don't go through CSS custom properties.
|
||||
═══════════════════════════════════════════════════════════════ */
|
||||
|
||||
:root[data-theme="light"] .main-content {
|
||||
background-image: radial-gradient(circle at 1px 1px, rgba(100, 116, 139, 0.18) 1px, transparent 0);
|
||||
}
|
||||
:root[data-theme="light"] .code-block {
|
||||
background: #f8fafc;
|
||||
color: #0c1426;
|
||||
}
|
||||
:root[data-theme="light"] .graph-stab-overlay {
|
||||
background: radial-gradient(ellipse at center, rgba(245, 247, 251, 0.92) 0%, rgba(245, 247, 251, 0.98) 100%);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root:not([data-theme="dark"]) .main-content {
|
||||
background-image: radial-gradient(circle at 1px 1px, rgba(100, 116, 139, 0.18) 1px, transparent 0);
|
||||
}
|
||||
:root:not([data-theme="dark"]) .code-block {
|
||||
background: #f8fafc;
|
||||
color: #0c1426;
|
||||
}
|
||||
:root:not([data-theme="dark"]) .graph-stab-overlay {
|
||||
background: radial-gradient(ellipse at center, rgba(245, 247, 251, 0.92) 0%, rgba(245, 247, 251, 0.98) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user