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

@@ -295,7 +295,7 @@ onSearched = debounce(onSearched, 500)
pt-16
pb-[6.4rem]
ml-56
bg-white
bg-surface
xl:ml-64
w-88
xl:block
@@ -309,7 +309,7 @@ onSearched = debounce(onSearched, 500)
px-4
pt-8
pb-2
border border-gray-200 border-solid
border border-line-default border-solid
height-full
"
>
@@ -322,7 +322,7 @@ onSearched = debounce(onSearched, 500)
@input="onSearched()"
>
<template #right>
<BaseIcon name="MagnifyingGlassIcon" class="h-5 text-gray-400" />
<BaseIcon name="MagnifyingGlassIcon" class="h-5 text-subtle" />
</template>
</BaseInput>
</div>
@@ -341,7 +341,7 @@ onSearched = debounce(onSearched, 500)
pb-2
mb-1 mb-2
text-sm
border-b border-gray-200 border-solid
border-b border-line-default border-solid
"
>
{{ $t('general.sort_by') }}
@@ -402,7 +402,7 @@ onSearched = debounce(onSearched, 500)
class="
h-full
overflow-y-scroll
border-l border-gray-200 border-solid
border-l border-line-default border-solid
base-scroll
"
>
@@ -412,9 +412,9 @@ onSearched = debounce(onSearched, 500)
:id="'invoice-' + invoice.id"
:to="`/admin/invoices/${invoice.id}/view`"
:class="[
'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-l-transparent',
'flex justify-between side-invoice p-4 cursor-pointer hover:bg-hover-strong items-center border-l-4 border-l-transparent',
{
'bg-gray-100 border-l-4 border-l-primary-500 border-solid':
'bg-surface-tertiary border-l-4 border-l-primary-500 border-solid':
hasActiveUrl(invoice.id),
},
]"
@@ -430,7 +430,7 @@ onSearched = debounce(onSearched, 500)
not-italic
font-normal
leading-5
text-black
text-heading
capitalize
truncate
"
@@ -444,7 +444,7 @@ onSearched = debounce(onSearched, 500)
not-italic
font-medium
leading-5
text-gray-600
text-body
"
>
{{ invoice.invoice_number }}
@@ -465,7 +465,7 @@ onSearched = debounce(onSearched, 500)
not-italic
font-semibold
leading-8
text-right text-gray-900
text-right text-heading
block
"
:amount="invoice.total"
@@ -477,7 +477,7 @@ onSearched = debounce(onSearched, 500)
not-italic
font-normal
leading-5
text-right text-gray-600
text-right text-body
est-date
"
>
@@ -491,7 +491,7 @@ onSearched = debounce(onSearched, 500)
</div>
<p
v-if="!invoiceList?.length && !isLoading"
class="flex justify-center px-4 mt-5 text-sm text-gray-600"
class="flex justify-center px-4 mt-5 text-sm text-body"
>
{{ $t('invoices.no_matching_invoices') }}
</p>
@@ -507,7 +507,7 @@ onSearched = debounce(onSearched, 500)
class="
flex-1
border border-gray-400 border-solid
bg-white
bg-surface
rounded-md
frame-style
"