diff --git a/src/app/globals.css b/src/app/globals.css index 7d7b1bc..b17413b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,7 +4,7 @@ @import "tw-animate-css"; @import "shadcn/tailwind.css"; -@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); +@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *, [data-theme="oled"], [data-theme="oled"] *)); :root { color-scheme: light; @@ -54,7 +54,8 @@ --danger-background: #fdeeee; } -[data-theme="dark"] { +[data-theme="dark"], +[data-theme="oled"] { color-scheme: dark; --background: #070706; --foreground: #f3f3ef; @@ -101,6 +102,54 @@ --danger-background: #2c1514; } +[data-theme="oled"] { + --background: #000000; + --foreground: #e6e6e6; + --card: #0a0a0a; + --card-foreground: #e6e6e6; + --popover: #101010; + --popover-foreground: #e6e6e6; + --primary: #dedede; + --primary-foreground: #000000; + --secondary: #161616; + --secondary-foreground: #e6e6e6; + --muted: #181818; + --muted-foreground: #a3a3a3; + --subtle-foreground: #949494; + --accent: #222222; + --accent-foreground: #e6e6e6; + --border: #242424; + --input: #303030; + --ring: #8a8a8a; + --chart-1: #dedede; + --chart-2: #9e9e9e; + --chart-3: #626262; + --chart-4: #383838; + --chart-5: #242424; + --sidebar: #060606; + --sidebar-foreground: #e6e6e6; + --sidebar-primary: #dedede; + --sidebar-primary-foreground: #000000; + --sidebar-accent: #1e1e1e; + --sidebar-accent-foreground: #e6e6e6; + --sidebar-border: #242424; + --sidebar-ring: #8a8a8a; + --surface-subtle: #121212; + --field: #161616; + --inverse: #121212; + --inverse-foreground: #e6e6e6; + --success-background: #06110b; + --info-background: #060d13; + --warning-background: #130f06; + --danger-background: #140908; +} + +[data-theme="dark"] [data-sidebar-hover-target][aria-current="page"], +[data-theme="oled"] [data-sidebar-hover-target][aria-current="page"] { + background: var(--sidebar-accent); + color: var(--sidebar-accent-foreground); +} + @theme inline { --font-heading: "Geist Sans", ui-sans-serif, system-ui, sans-serif; --font-sans: "Geist Sans", ui-sans-serif, system-ui, sans-serif; @@ -298,6 +347,10 @@ ); } +[data-theme="oled"] .auth-shell-glow { + display: none; +} + @keyframes folio-dashboard-enter { from { opacity: 0; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 7180953..f03aa16 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -26,7 +26,7 @@ const themeBootstrap = ` (() => { try { const stored = localStorage.getItem("folio-theme"); - const preference = stored === "light" || stored === "dark" || stored === "system" + const preference = stored === "light" || stored === "dark" || stored === "oled" || stored === "system" ? stored : "light"; const resolved = preference === "system" @@ -35,9 +35,9 @@ const themeBootstrap = ` const root = document.documentElement; root.dataset.theme = resolved; root.dataset.themePreference = preference; - root.style.colorScheme = resolved; + root.style.colorScheme = resolved === "light" ? "light" : "dark"; document.querySelector('meta[name="theme-color"]') - ?.setAttribute("content", resolved === "dark" ? "#070706" : "#f7f7f5"); + ?.setAttribute("content", resolved === "oled" ? "#000000" : resolved === "dark" ? "#070706" : "#f7f7f5"); } catch { document.documentElement.dataset.theme = "light"; document.documentElement.dataset.themePreference = "light"; diff --git a/src/components/folio/app-shell.tsx b/src/components/folio/app-shell.tsx index 654e066..2b3183d 100644 --- a/src/components/folio/app-shell.tsx +++ b/src/components/folio/app-shell.tsx @@ -2,6 +2,7 @@ import { ChartNoAxesCombined, + FullMoon, Monitor, Package, } from "@/components/ui/icons"; @@ -435,6 +436,7 @@ function NavigationLink({ const themeOptions = [ { label: "Light", value: "light", icon: Sun03Icon }, { label: "Dark", value: "dark", icon: Moon02Icon }, + { label: "OLED", value: "oled", icon: FullMoon }, { label: "System", value: "system", icon: Monitor }, ] satisfies readonly { icon: NavigationIcon @@ -449,7 +451,9 @@ function ThemeMenu({ }) { const { preference, resolvedTheme, setPreference } = useTheme() const themeIconRef = useRef(null) - const ThemeIcon = resolvedTheme === "dark" ? Moon02Icon : Sun03Icon + const ThemeIcon = resolvedTheme === "light" ? Sun03Icon : Moon02Icon + const themeIconClassName = + "size-3.5 shrink-0 motion-safe:transition-transform motion-safe:duration-150 motion-safe:group-hover:scale-110 motion-safe:group-active:scale-95 [&_svg]:size-full" const selectedLabel = themeOptions.find((option) => option.value === preference)?.label ?? "Light" @@ -480,12 +484,16 @@ function ThemeMenu({ onPointerLeave={stopIconAnimation} type="button" > -