feat: add dark/light theme toggle with system preference support (#18)

Add theme switching with three modes (system/light/dark) using Tailwind v4
class-based dark mode. Theme preference is persisted in localStorage and
defaults to the system's prefers-color-scheme. All components updated with
dark: variants for consistent dark mode rendering including SVG elements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shahondin1624
2026-03-12 12:54:04 +01:00
parent 79c14378a2
commit 60f3d8eeda
22 changed files with 418 additions and 181 deletions

View File

@@ -7,13 +7,13 @@
const statusConfig = $derived.by(() => {
switch (result.status) {
case ResultStatus.SUCCESS:
return { label: 'Success', bg: 'bg-green-100', text: 'text-green-800', border: 'border-green-200' };
return { label: 'Success', bg: 'bg-green-100 dark:bg-green-900/30', text: 'text-green-800 dark:text-green-300', border: 'border-green-200 dark:border-green-800' };
case ResultStatus.PARTIAL:
return { label: 'Partial', bg: 'bg-amber-100', text: 'text-amber-800', border: 'border-amber-200' };
return { label: 'Partial', bg: 'bg-amber-100 dark:bg-amber-900/30', text: 'text-amber-800 dark:text-amber-300', border: 'border-amber-200 dark:border-amber-800' };
case ResultStatus.FAILED:
return { label: 'Failed', bg: 'bg-red-100', text: 'text-red-800', border: 'border-red-200' };
return { label: 'Failed', bg: 'bg-red-100 dark:bg-red-900/30', text: 'text-red-800 dark:text-red-300', border: 'border-red-200 dark:border-red-800' };
default:
return { label: 'Unknown', bg: 'bg-gray-100', text: 'text-gray-800', border: 'border-gray-200' };
return { label: 'Unknown', bg: 'bg-gray-100 dark:bg-gray-800', text: 'text-gray-800 dark:text-gray-300', border: 'border-gray-200 dark:border-gray-700' };
}
});
@@ -42,12 +42,12 @@
{statusConfig.label}
</span>
{#if qualityLabel}
<span class="rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">
<span class="rounded-full bg-blue-100 dark:bg-blue-900/40 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:text-blue-300">
{qualityLabel}
</span>
{/if}
{#if sourceLabel}
<span class="rounded-full bg-purple-100 px-2.5 py-0.5 text-xs font-medium text-purple-800">
<span class="rounded-full bg-purple-100 dark:bg-purple-900/40 px-2.5 py-0.5 text-xs font-medium text-purple-800 dark:text-purple-300">
{sourceLabel}
</span>
{/if}
@@ -58,17 +58,17 @@
{/if}
{#if result.failureReason}
<p class="mt-2 text-sm text-red-700">Reason: {result.failureReason}</p>
<p class="mt-2 text-sm text-red-700 dark:text-red-400">Reason: {result.failureReason}</p>
{/if}
{#if result.artifacts.length > 0}
<div class="mt-3 border-t {statusConfig.border} pt-3">
<p class="mb-1.5 text-xs font-medium text-gray-600">Artifacts</p>
<p class="mb-1.5 text-xs font-medium text-gray-600 dark:text-gray-400">Artifacts</p>
<ul class="space-y-1">
{#each result.artifacts as artifact (artifact)}
<li class="flex items-center gap-2 text-sm">
<span class="text-gray-400">&#128196;</span>
<span class="font-mono text-xs text-gray-700">{artifact}</span>
<span class="text-gray-400 dark:text-gray-500">&#128196;</span>
<span class="font-mono text-xs text-gray-700 dark:text-gray-300">{artifact}</span>
</li>
{/each}
</ul>