feat(frontend): add light mode with runtime theme toggle

- globals.css: split theme tokens into :root (light default) + .dark
  overrides; switch @theme inline → @theme so utilities reference
  var(--color-*) and a runtime class swap actually re-skins the UI
  (inline inlines literal values and ignores .dark overrides)
- layout.tsx: drop the beforeInteractive inline theme script (it caused
  hydration instability); theme is applied client-side only
- top-nav: apply persisted theme on mount, default light, toggle
  updates <html> class + localStorage
- glass-intense: light variant (white card on light canvas); chart grid
  line uses var(--color-border); attachment chip uses bg-glass-bg
- Verified in static export: toggle dark↔light both directions,
  chatbot panel renders clean in both themes
This commit is contained in:
asepharyana
2026-08-03 07:20:09 +07:00
parent 831254bb71
commit 9abb09dd33
5 changed files with 98 additions and 36 deletions
+1 -7
View File
@@ -1,6 +1,5 @@
import type { Metadata } from "next";
import { Inter, JetBrains_Mono } from "next/font/google";
import Script from "next/script";
import { Toaster } from "@/components/ui/sonner";
import "./globals.css";
@@ -27,14 +26,9 @@ export default function RootLayout({
return (
<html
lang="en"
className={`${inter.variable} ${jetbrainsMono.variable} dark h-full antialiased`}
className={`${inter.variable} ${jetbrainsMono.variable} h-full antialiased`}
suppressHydrationWarning
>
<head>
<Script id="theme-script" strategy="beforeInteractive">
{`try{const t=localStorage.getItem('theme')||'dark';document.documentElement.classList.add(t)}catch(e){}`}
</Script>
</head>
<body className="min-h-full flex flex-col">
{children}
<Toaster position="bottom-right" richColors closeButton />