From e4ba84671922c3c2f283d383b988ef1d7de0a97d Mon Sep 17 00:00:00 2001 From: Jokin Date: Fri, 14 Aug 2026 13:20:47 +0200 Subject: [PATCH] Retone dark theme to warm gray #1a1a19 with layered surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dark palette was shadcn's cool zinc (#202023, hue ~286). Anchor it on #1a1a19 instead — cds gray-830, a warm near-neutral (hue 107) — and retone the whole dark neutral family to match, since a warm background under cool panels clashes. Lightness ramp is preserved; chromatic tokens (destructive, success, icon hues, accent formulas) and the light palette are untouched. Also introduce --chrome so the app isn't one flat tone: frame strips (tab bar, status bar, transfer bar, editor/manager header+footer, connection sidebar) now sit one step below the content panes, with popovers and hover above them — the standard dark-UI elevation order. Dark ramp: #151514 chrome, #1a1a19 content, #20201f card, #2e2e2d hover; the "darker" tone drops chrome to true black. Light gains only a zinc-50 chrome step. Co-Authored-By: Claude --- docs/architecture.md | 11 ++- .../connection-manager.html | 6 +- ui/src/app/editor-window/editor-window.html | 6 +- ui/src/app/status-bar/status-bar.ts | 2 +- ui/src/app/tab-bar/tab-bar.ts | 2 +- ui/src/app/transfer-bar/transfer-bar.html | 4 +- ui/src/index.html | 8 +- ui/src/styles.css | 95 +++++++++++-------- 8 files changed, 77 insertions(+), 57 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index b3732f7..06ef2ca 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -239,7 +239,16 @@ would float over editor windows). `ui/src/styles.css`: shadcn-style OKLCH tokens; dark values are duplicated in `:root[data-theme='dark']` AND a `prefers-color-scheme` media block (system -mode) — every dark token change goes in BOTH. Accent tones: one +mode) — every dark token change goes in BOTH. Light is the zinc family; the +dark neutrals are a **warm gray family (hue 107)** anchored on `#1a1a19` +(`--background`) — retoning one dark neutral means retoning them all, or warm +and cool surfaces clash. Surface elevation ramp, both themes: `--chrome` +(frame strips) sits *below* `--background` (content panes) < `--card` +(popovers/dialogs) < `--accent` (hover). Dark ramp `#151514` → `#1a1a19` → +`#20201f` → `#2e2e2d`; the "darker" tone drops `--chrome` to true black. +`bg-chrome` is on the tab bar, status bar, transfer bar, the editor/manager +header+footer strips and the manager's connection sidebar; panel-internal +toolbars deliberately stay on `--background`. Accent tones: one `--tone-h/--tone-c` line per tone + three formula blocks derive `--primary`, `--ring`, `--cursor-tint`; graphite = attribute removed = pristine zinc. `@theme inline` maps tokens to Tailwind utilities (`bg-primary`, diff --git a/ui/src/app/connection-manager/connection-manager.html b/ui/src/app/connection-manager/connection-manager.html index 18f2964..06e2f69 100644 --- a/ui/src/app/connection-manager/connection-manager.html +++ b/ui/src/app/connection-manager/connection-manager.html @@ -2,7 +2,7 @@
-
+
-
+
@for (job of transfers.jobs(); track job.id) {
diff --git a/ui/src/index.html b/ui/src/index.html index db3bd6c..ae1571a 100644 --- a/ui/src/index.html +++ b/ui/src/index.html @@ -14,11 +14,11 @@ src/bun/windows.ts) so forced themes are correct at first paint. --> diff --git a/ui/src/styles.css b/ui/src/styles.css index 07a4b8f..ca7077f 100644 --- a/ui/src/styles.css +++ b/ui/src/styles.css @@ -1,11 +1,17 @@ @import "tailwindcss"; -/* shadcn-style theme tokens (zinc placeholder palette — tweak freely). - The app follows the OS light/dark preference automatically. */ +/* shadcn-style theme tokens. Light stays the zinc family; the dark neutrals are a + warm gray family (hue ~107) anchored on #1a1a19 — see the dark blocks below. + The app follows the OS light/dark preference automatically. + + Surface elevation ramp (both themes): --chrome (frame strips: tab/transfer/status + bars, window toolbars) sits BELOW --background (content panes), which sits below + --card (popovers, dialogs), which sits below --accent (hover). */ :root { /* Native UI (scrollbars, form controls) follows the OS unless a theme is forced. */ color-scheme: light dark; --background: oklch(1 0 0); + --chrome: oklch(0.977 0.001 286.375); --foreground: oklch(0.141 0.005 285.823); --card: oklch(1 0 0); --card-foreground: oklch(0.141 0.005 285.823); @@ -41,24 +47,25 @@ :root[data-theme='dark'] { color-scheme: dark; - --background: oklch(0.245 0.005 285.9); - --foreground: oklch(0.985 0 0); - --card: oklch(0.274 0.006 286.033); - --card-foreground: oklch(0.985 0 0); - --primary: oklch(0.92 0.004 286.32); - --primary-foreground: oklch(0.21 0.006 285.885); - --secondary: oklch(0.33 0.01 285.9); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.33 0.01 285.9); - --muted-foreground: oklch(0.72 0.015 286.07); - --accent: oklch(0.33 0.01 285.9); - --accent-foreground: oklch(0.985 0 0); + --background: oklch(0.2178 0.002 107); + --chrome: oklch(0.1953 0.002 107); + --foreground: oklch(0.982 0.003 107); + --card: oklch(0.245 0.002 107); + --card-foreground: oklch(0.982 0.003 107); + --primary: oklch(0.92 0.004 107); + --primary-foreground: oklch(0.21 0.002 107); + --secondary: oklch(0.302 0.003 107); + --secondary-foreground: oklch(0.982 0.003 107); + --muted: oklch(0.302 0.003 107); + --muted-foreground: oklch(0.715 0.012 107); + --accent: oklch(0.302 0.003 107); + --accent-foreground: oklch(0.982 0.003 107); --destructive: oklch(0.704 0.191 22.216); - --destructive-foreground: oklch(0.985 0 0); + --destructive-foreground: oklch(0.982 0.003 107); --success: oklch(0.696 0.17 149.2); --border: oklch(1 0 0 / 14%); --input: oklch(1 0 0 / 18%); - --ring: oklch(0.552 0.016 285.938); + --ring: oklch(0.552 0.01 107); --icon-folder: oklch(0.75 0.11 250); --icon-link: oklch(0.74 0.09 190); --icon-image: oklch(0.76 0.11 295); @@ -69,24 +76,25 @@ @media (prefers-color-scheme: dark) { :root:not([data-theme='light']) { - --background: oklch(0.245 0.005 285.9); - --foreground: oklch(0.985 0 0); - --card: oklch(0.274 0.006 286.033); - --card-foreground: oklch(0.985 0 0); - --primary: oklch(0.92 0.004 286.32); - --primary-foreground: oklch(0.21 0.006 285.885); - --secondary: oklch(0.33 0.01 285.9); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.33 0.01 285.9); - --muted-foreground: oklch(0.72 0.015 286.07); - --accent: oklch(0.33 0.01 285.9); - --accent-foreground: oklch(0.985 0 0); + --background: oklch(0.2178 0.002 107); + --chrome: oklch(0.1953 0.002 107); + --foreground: oklch(0.982 0.003 107); + --card: oklch(0.245 0.002 107); + --card-foreground: oklch(0.982 0.003 107); + --primary: oklch(0.92 0.004 107); + --primary-foreground: oklch(0.21 0.002 107); + --secondary: oklch(0.302 0.003 107); + --secondary-foreground: oklch(0.982 0.003 107); + --muted: oklch(0.302 0.003 107); + --muted-foreground: oklch(0.715 0.012 107); + --accent: oklch(0.302 0.003 107); + --accent-foreground: oklch(0.982 0.003 107); --destructive: oklch(0.704 0.191 22.216); - --destructive-foreground: oklch(0.985 0 0); + --destructive-foreground: oklch(0.982 0.003 107); --success: oklch(0.696 0.17 149.2); --border: oklch(1 0 0 / 14%); --input: oklch(1 0 0 / 18%); - --ring: oklch(0.552 0.016 285.938); + --ring: oklch(0.552 0.01 107); --icon-folder: oklch(0.75 0.11 250); --icon-link: oklch(0.74 0.09 190); --icon-image: oklch(0.76 0.11 295); @@ -100,23 +108,25 @@ Near-black AMOLED palette. Duplicated for forced-dark and system-dark like the token blocks above — the extra attribute outranks them. */ :root[data-theme='dark'][data-dark-tone='darker'] { - --background: oklch(0.141 0.005 285.823); - --card: oklch(0.21 0.006 285.885); - --secondary: oklch(0.274 0.006 286.033); - --muted: oklch(0.274 0.006 286.033); - --muted-foreground: oklch(0.705 0.015 286.067); - --accent: oklch(0.274 0.006 286.033); + --background: oklch(0.141 0.002 107); + --chrome: oklch(0 0 0); + --card: oklch(0.21 0.002 107); + --secondary: oklch(0.274 0.003 107); + --muted: oklch(0.274 0.003 107); + --muted-foreground: oklch(0.705 0.012 107); + --accent: oklch(0.274 0.003 107); --border: oklch(1 0 0 / 12%); --input: oklch(1 0 0 / 15%); } @media (prefers-color-scheme: dark) { :root:not([data-theme='light'])[data-dark-tone='darker'] { - --background: oklch(0.141 0.005 285.823); - --card: oklch(0.21 0.006 285.885); - --secondary: oklch(0.274 0.006 286.033); - --muted: oklch(0.274 0.006 286.033); - --muted-foreground: oklch(0.705 0.015 286.067); - --accent: oklch(0.274 0.006 286.033); + --background: oklch(0.141 0.002 107); + --chrome: oklch(0 0 0); + --card: oklch(0.21 0.002 107); + --secondary: oklch(0.274 0.003 107); + --muted: oklch(0.274 0.003 107); + --muted-foreground: oklch(0.705 0.012 107); + --accent: oklch(0.274 0.003 107); --border: oklch(1 0 0 / 12%); --input: oklch(1 0 0 / 15%); } @@ -124,6 +134,7 @@ @theme inline { --color-background: var(--background); + --color-chrome: var(--chrome); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground);