feat: full dark mode with :root.dark and dark: classes

layout.css
- Change .dark → :root.dark so variable overrides match Tailwind's
  :root, :host specificity and actually take effect
- Add global dark mode styles for input/select/textarea elements

All .svelte files:
- bg-white → bg-white dark:bg-gray-100 (cards, tables, containers)
- text-white → text-white dark:text-gray-950 (button text)
- Add dark:bg-gray-950 to main page containers (dashboard, account,
  license-keys, proclamations, proclamations/[id])
- Add dark:border-gray-300 to bordered elements (cards, tables, forms)
- Add dark:bg-gray-200 to secondary backgrounds (table headers,
  address form, price badges)
- Add dark:hover:bg-gray-300 / dark:hover:bg-gray-700 to hover states
  (sidebar nav links, clear button, admin categories table)
This commit is contained in:
NeilClack
2026-07-07 10:00:00 -05:00
parent 03ecfbd635
commit d97ed88031
13 changed files with 44 additions and 32 deletions
@@ -23,7 +23,7 @@
} }
</script> </script>
<div class="flex h-full min-h-0 flex-col gap-8 p-6"> <div class="flex h-full min-h-0 flex-col gap-8 p-6 dark:bg-gray-950">
<h1 class="text-2xl font-semibold text-gray-900">Account</h1> <h1 class="text-2xl font-semibold text-gray-900">Account</h1>
<!-- Email (read-only) --> <!-- Email (read-only) -->
@@ -93,7 +93,7 @@
<div> <div>
<button <button
type="submit" type="submit"
class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700" class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white dark:text-gray-950 transition-colors hover:bg-blue-700"
> >
Save Profile Save Profile
</button> </button>
@@ -107,7 +107,7 @@
<h2 class="text-lg font-medium text-gray-900">Addresses</h2> <h2 class="text-lg font-medium text-gray-900">Addresses</h2>
<button <button
type="button" type="button"
class="rounded-lg bg-green-600 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-green-700" class="rounded-lg bg-green-600 px-3 py-1.5 text-sm font-medium text-white dark:text-gray-950 transition-colors hover:bg-green-700"
onclick={() => (showAddressForm = !showAddressForm)} onclick={() => (showAddressForm = !showAddressForm)}
> >
{showAddressForm ? 'Cancel' : 'Add Address'} {showAddressForm ? 'Cancel' : 'Add Address'}
@@ -129,7 +129,7 @@
<form <form
method="POST" method="POST"
action="?/addAddress" action="?/addAddress"
class="mb-6 max-w-lg rounded-lg border border-gray-200 bg-gray-50 p-4" class="mb-6 max-w-lg rounded-lg border border-gray-200 dark:border-gray-300 bg-gray-50 dark:bg-gray-200 p-4"
> >
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
<div> <div>
@@ -192,7 +192,7 @@
<div> <div>
<button <button
type="submit" type="submit"
class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700" class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white dark:text-gray-950 transition-colors hover:bg-blue-700"
> >
Save Address Save Address
</button> </button>
@@ -204,7 +204,7 @@
{#if data.user.profile?.addresses && data.user.profile.addresses.length > 0} {#if data.user.profile?.addresses && data.user.profile.addresses.length > 0}
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
{#each data.user.profile.addresses as address} {#each data.user.profile.addresses as address}
<div class="rounded-lg border border-gray-200 bg-white p-4"> <div class="rounded-lg border border-gray-200 bg-white dark:bg-gray-100 p-4">
<p class="text-sm text-gray-900">{address.street}</p> <p class="text-sm text-gray-900">{address.street}</p>
<p class="text-sm text-gray-600"> <p class="text-sm text-gray-600">
{address.city}, {address.state} {address.postalCode} {address.city}, {address.state} {address.postalCode}
@@ -43,7 +43,7 @@
</script> </script>
<Window> <Window>
<form method="POST" class="border shadow-lg p-6 rounded-xl"> <form method="POST" class="border shadow-lg p-6 rounded-xl dark:bg-gray-100 dark:border-gray-300">
<p class="mx-auto text-center my-4 italic">Please finish setting up your profile</p> <p class="mx-auto text-center my-4 italic">Please finish setting up your profile</p>
{#if data.user?.image} {#if data.user?.image}
<img src={data.user?.image} class="rounded-full w-[8rem] mx-auto" alt="Profile" /> <img src={data.user?.image} class="rounded-full w-[8rem] mx-auto" alt="Profile" />
@@ -4,13 +4,13 @@
let { data }: PageProps = $props(); let { data }: PageProps = $props();
</script> </script>
<div class="flex h-full min-h-0 flex-col gap-6 p-6"> <div class="flex h-full min-h-0 flex-col gap-6 p-6 dark:bg-gray-950">
<h1 class="text-2xl font-semibold text-gray-900">Welcome, {data.firstName}!</h1> <h1 class="text-2xl font-semibold text-gray-900">Welcome, {data.firstName}!</h1>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3"> <div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<a <a
href="/license-keys" href="/license-keys"
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm transition-shadow hover:shadow-md" class="rounded-lg border border-gray-200 bg-white dark:bg-gray-100 p-6 shadow-sm transition-shadow hover:shadow-md"
> >
<p class="text-sm font-medium text-gray-500">Active License Keys</p> <p class="text-sm font-medium text-gray-500">Active License Keys</p>
<p class="mt-2 text-3xl font-bold text-gray-900">{data.activeKeys}</p> <p class="mt-2 text-3xl font-bold text-gray-900">{data.activeKeys}</p>
@@ -19,7 +19,7 @@
<a <a
href="/admin/proclamations" href="/admin/proclamations"
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm transition-shadow hover:shadow-md" class="rounded-lg border border-gray-200 bg-white dark:bg-gray-100 p-6 shadow-sm transition-shadow hover:shadow-md"
> >
<p class="text-sm font-medium text-gray-500">Proclamations</p> <p class="text-sm font-medium text-gray-500">Proclamations</p>
<p class="mt-2 text-3xl font-bold text-gray-900">{data.proclamationCount}</p> <p class="mt-2 text-3xl font-bold text-gray-900">{data.proclamationCount}</p>
@@ -28,7 +28,7 @@
<a <a
href="/account" href="/account"
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm transition-shadow hover:shadow-md" class="rounded-lg border border-gray-200 bg-white dark:bg-gray-100 p-6 shadow-sm transition-shadow hover:shadow-md"
> >
<p class="text-sm font-medium text-gray-500">Account</p> <p class="text-sm font-medium text-gray-500">Account</p>
<p class="mt-2 text-lg font-semibold text-gray-900">Manage Profile</p> <p class="mt-2 text-lg font-semibold text-gray-900">Manage Profile</p>
@@ -4,13 +4,13 @@
let { data }: PageProps = $props(); let { data }: PageProps = $props();
</script> </script>
<div class="flex h-full min-h-0 flex-col gap-6 p-6"> <div class="flex h-full min-h-0 flex-col gap-6 p-6 dark:bg-gray-950">
<h1 class="text-2xl font-semibold text-gray-900">License Keys</h1> <h1 class="text-2xl font-semibold text-gray-900">License Keys</h1>
{#if data.licenseKeys.length > 0} {#if data.licenseKeys.length > 0}
<div class="overflow-x-auto rounded-lg border border-gray-200"> <div class="overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-300">
<table class="min-w-full divide-y divide-gray-200"> <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-300">
<thead class="bg-gray-50"> <thead class="bg-gray-50 dark:bg-gray-200">
<tr> <tr>
<th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"> <th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
Key Key
@@ -23,7 +23,7 @@
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 dark:divide-gray-300 bg-white dark:bg-gray-100">
{#each data.licenseKeys as key} {#each data.licenseKeys as key}
<tr> <tr>
<td class="whitespace-nowrap px-6 py-4 font-mono text-sm text-gray-900"> <td class="whitespace-nowrap px-6 py-4 font-mono text-sm text-gray-900">
@@ -34,7 +34,7 @@
} }
</script> </script>
<div class="flex h-full min-h-0 flex-col gap-6 p-6"> <div class="flex h-full min-h-0 flex-col gap-6 p-6 dark:bg-gray-950">
<h1 class="text-2xl font-semibold text-gray-900">Proclamations</h1> <h1 class="text-2xl font-semibold text-gray-900">Proclamations</h1>
<!-- Filters --> <!-- Filters -->
@@ -66,7 +66,7 @@
</div> </div>
<button <button
type="button" type="button"
class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700" class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white dark:text-gray-950 transition-colors hover:bg-blue-700"
onclick={applyFilters} onclick={applyFilters}
> >
Search Search
@@ -74,7 +74,7 @@
{#if data.search || data.categoryId} {#if data.search || data.categoryId}
<button <button
type="button" type="button"
class="rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50" class="rounded-lg border border-gray-300 dark:border-gray-400 px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 dark:hover:bg-gray-300"
onclick={clearFilters} onclick={clearFilters}
> >
Clear Clear
@@ -88,7 +88,7 @@
{#each data.proclamations as proclamation} {#each data.proclamations as proclamation}
<a <a
href="/proclamations/{proclamation.id}" href="/proclamations/{proclamation.id}"
class="flex flex-col rounded-lg border border-gray-200 bg-white p-5 shadow-sm transition-shadow hover:shadow-md" class="flex flex-col rounded-lg border border-gray-200 dark:border-gray-300 bg-white dark:bg-gray-100 p-5 shadow-sm transition-shadow hover:shadow-md"
> >
<h2 class="text-lg font-medium text-gray-900">{proclamation.name}</h2> <h2 class="text-lg font-medium text-gray-900">{proclamation.name}</h2>
<p class="mt-1 text-sm text-gray-500">{displayCategoryName(proclamation.category)}</p> <p class="mt-1 text-sm text-gray-500">{displayCategoryName(proclamation.category)}</p>
@@ -10,7 +10,7 @@
); );
</script> </script>
<div class="mx-auto flex h-full min-h-0 w-full max-w-3xl flex-col gap-6 p-6"> <div class="mx-auto flex h-full min-h-0 w-full max-w-3xl flex-col gap-6 p-6 dark:bg-gray-950">
<a <a
href="/proclamations" href="/proclamations"
class="text-sm text-blue-600 hover:text-blue-800 hover:underline" class="text-sm text-blue-600 hover:text-blue-800 hover:underline"
@@ -31,7 +31,7 @@
{data.proclamation.solfeggioFrequency.name} {data.proclamation.solfeggioFrequency.name}
</p> </p>
</div> </div>
<div class="rounded-lg border border-gray-200 bg-gray-50 px-4 py-2"> <div class="rounded-lg border border-gray-200 dark:border-gray-300 bg-gray-50 dark:bg-gray-200 px-4 py-2">
<p class="text-xs font-medium text-gray-500">Price</p> <p class="text-xs font-medium text-gray-500">Price</p>
<p class="text-sm font-semibold text-gray-900"> <p class="text-sm font-semibold text-gray-900">
${data.proclamation.price.toFixed(2)} ${data.proclamation.price.toFixed(2)}
@@ -39,7 +39,7 @@
</div> </div>
</div> </div>
<div class="prose max-w-none rounded-lg border border-gray-200 bg-white p-6"> <div class="prose max-w-none rounded-lg border border-gray-200 dark:border-gray-300 bg-white dark:bg-gray-100 p-6">
{@html data.proclamation.content} {@html data.proclamation.content}
</div> </div>
</div> </div>
+3 -3
View File
@@ -29,7 +29,7 @@
href={link.href} href={link.href}
class="rounded px-3 py-1.5 text-sm font-medium transition-colors {isActive(link.href) class="rounded px-3 py-1.5 text-sm font-medium transition-colors {isActive(link.href)
? 'bg-blue-50 text-blue-700' ? 'bg-blue-50 text-blue-700'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'}" : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900 dark:hover:bg-gray-300 dark:hover:text-gray-100'}"
> >
{link.label} {link.label}
</a> </a>
@@ -40,7 +40,7 @@
href="/admin" href="/admin"
class="rounded px-3 py-1.5 text-sm font-medium transition-colors {isActive('/admin') class="rounded px-3 py-1.5 text-sm font-medium transition-colors {isActive('/admin')
? 'bg-blue-50 text-blue-700' ? 'bg-blue-50 text-blue-700'
: 'text-gray-700 hover:bg-gray-50 hover:text-gray-900'}" : 'text-gray-700 hover:bg-gray-50 hover:text-gray-900 dark:hover:bg-gray-300 dark:hover:text-gray-100'}"
> >
Admin Panel Admin Panel
</a> </a>
@@ -52,7 +52,7 @@
'/admin/' + model.slug '/admin/' + model.slug
) )
? 'bg-blue-50 text-blue-700' ? 'bg-blue-50 text-blue-700'
: 'text-blue-600 hover:bg-gray-50 hover:text-blue-800'}" : 'text-blue-600 hover:bg-gray-50 hover:text-blue-800 dark:hover:bg-gray-300 dark:hover:text-gray-100'}"
> >
{model.displayName} {model.displayName}
</a> </a>
@@ -24,7 +24,7 @@
<tbody> <tbody>
{#if data.categories} {#if data.categories}
{#each data.categories as category, i (category.id)} {#each data.categories as category, i (category.id)}
<tr class="hover:bg-gray-300"> <tr class="hover:bg-gray-300 dark:hover:bg-gray-700">
<td class="hidden">{i}</td> <td class="hidden">{i}</td>
<td>{category.name}</td> <td>{category.name}</td>
{#if category.parentId} {#if category.parentId}
+1 -1
View File
@@ -19,6 +19,6 @@
</svelte:head> </svelte:head>
<TopBar userRoleId={data.userRoleId} /> <TopBar userRoleId={data.userRoleId} />
<div class="flex min-h-0 flex-1 px-8"> <div class="flex min-h-0 flex-1 px-8 dark:bg-gray-950 dark:text-gray-100">
{@render children()} {@render children()}
</div> </div>
+1 -1
View File
@@ -30,7 +30,7 @@
/> />
<button <button
type="submit" type="submit"
class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700" class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white dark:text-gray-950 transition-colors hover:bg-blue-700"
> >
Send Reset Link Send Reset Link
</button> </button>
+13 -1
View File
@@ -76,8 +76,9 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Dark mode — invert the gray scale */ /* Dark mode — invert the gray scale */
/* Use :root.dark so specificity matches Tailwind's :root, :host */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
.dark { :root.dark {
--color-gray-50: #030712; --color-gray-50: #030712;
--color-gray-100: #111827; --color-gray-100: #111827;
--color-gray-200: #1f2937; --color-gray-200: #1f2937;
@@ -90,6 +91,17 @@
--color-gray-900: #f9fafb; --color-gray-900: #f9fafb;
} }
/* ------------------------------------------------------------------ */
/* Dark mode form elements */
/* ------------------------------------------------------------------ */
:root.dark input,
:root.dark select,
:root.dark textarea {
background-color: #1f2937;
color: #f9fafb;
border-color: #374151;
}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Force-disable transitions, animations, and remaining decoration */ /* Force-disable transitions, animations, and remaining decoration */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
+1 -1
View File
@@ -32,7 +32,7 @@
<input type="email" name="email" placeholder="Email Address" required class="mb-2" /> <input type="email" name="email" placeholder="Email Address" required class="mb-2" />
<input type="password" name="password" placeholder="Password" required class="mb-2" /> <input type="password" name="password" placeholder="Password" required class="mb-2" />
<input type="password" name="password2" placeholder="Verify Password" required class="mb-2" /> <input type="password" name="password2" placeholder="Verify Password" required class="mb-2" />
<button type="submit" class="mx-auto rounded-full bg-blue-600 px-6 py-2 text-white" <button type="submit" class="mx-auto rounded-full bg-blue-600 px-6 py-2 text-white dark:text-gray-950"
>Submit</button >Submit</button
> >
</form> </form>
+1 -1
View File
@@ -32,7 +32,7 @@
/> />
<button <button
type="submit" type="submit"
class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700" class="rounded-lg bg-blue-600 px-4 py-2 font-medium text-white dark:text-gray-950 transition-colors hover:bg-blue-700"
> >
Reset Password Reset Password
</button> </button>