feat: wire up class-based dark mode for Tailwind v4

- app.css: add @custom-variant dark so Tailwind v4 respects .dark class
  on <html> instead of always following OS prefers-color-scheme.
- app.html: remove hardcoded class="light" (now set dynamically).
- +layout.svelte: toggle .dark/.light on <html> when ae_loc.theme_mode changes.
- e_app_theme.svelte: related theme toggle changes.
This commit is contained in:
Scott Idem
2026-03-06 17:32:30 -05:00
parent bdf3260c74
commit 9fc72b4671
4 changed files with 19 additions and 9 deletions

View File

@@ -1,5 +1,11 @@
@import 'tailwindcss';
/* Enable class-based dark mode for Tailwind v4.
Without this, Tailwind v4 defaults to @media (prefers-color-scheme: dark),
which ignores the .dark class on <html> and always follows the OS setting.
This makes the dark/light toggle in e_app_theme.svelte actually work. */
@custom-variant dark (&:where(.dark, .dark *));
@import '@skeletonlabs/skeleton';

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en" class="light" data-theme="">
<html lang="en" data-theme="">
<head>
<meta charset="utf-8" />

View File

@@ -149,13 +149,7 @@ if ($ae_loc.app_cfg.theme_mode == 'light') {
$ae_loc.theme_mode = 'light';
}
if ($ae_loc.theme_mode == 'light') {
document.documentElement.classList.remove('dark');
document.documentElement.classList.add('light');
} else if ($ae_loc.theme_mode == 'dark') {
document.documentElement.classList.remove('light');
document.documentElement.classList.add('dark');
}
// DOM sync is handled reactively by the layout effect in +layout.svelte
}}
title="Change light and dark mode"
>

View File

@@ -161,9 +161,19 @@
$effect(() => {
if (!browser) return;
// Theme DOM update
// Theme name — controls which Skeleton color palette is active
document.documentElement.setAttribute('data-theme', $ae_loc?.theme_name ?? 'nouveau');
// Dark/light class — controls Tailwind v4 class-based dark mode variant.
// @custom-variant dark in app.css registers this; without it the class does nothing.
if ($ae_loc?.theme_mode === 'dark') {
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('light');
} else {
document.documentElement.classList.add('light');
document.documentElement.classList.remove('dark');
}
// Hydration overlay timer
if ($ae_loc?.account_id) {
const timer = setTimeout(() => is_hydrating = false, 500);