Add dark mode with CSS custom property theme system

Define 13 semantic color tokens (surface, text, border, hover) with
light/dark values in themes.css. Register with Tailwind via @theme inline.
Migrate all 335 Vue files from hardcoded gray/white classes to semantic
tokens. Add theme toggle (sun/moon/system) in user avatar dropdown.
Replace @tailwindcss/forms with custom form reset using theme vars.
Add status badge and alert tokens for dark mode. Theme-aware chart
grid/labels, skeleton placeholders, and editor. Inline script in
<head> prevents flash of wrong theme on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Darko Gjorgjijoski
2026-04-04 02:05:00 +02:00
parent 7fbe3d85a3
commit 88adfe0e50
221 changed files with 1265 additions and 982 deletions

View File

@@ -55,7 +55,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-rounded & {
border-radius: 6px;
@@ -72,7 +72,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@@ -87,7 +87,7 @@ const classObject = computed(() => {
.base-content-placeholders-heading__title {
width: 85%;
margin-bottom: 10px;
background: #ccc;
background: var(--color-surface-muted);
position: relative;
overflow: hidden;
min-height: 15px;
@@ -107,7 +107,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@@ -117,7 +117,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-rounded & {
border-radius: 6px;
@@ -134,7 +134,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@@ -151,7 +151,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-rounded & {
border-radius: 6px;
@@ -168,7 +168,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
@@ -190,7 +190,7 @@ const classObject = computed(() => {
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
background: var(--color-surface-muted);
.base-content-placeholders-is-animated &::before {
content: '';
@@ -200,7 +200,7 @@ const classObject = computed(() => {
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
background: linear-gradient(to right, transparent 0%, var(--color-hover-strong) 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}