authorgravatar for maria@kuuro.netmaria <maria@kuuro.net> 2026-09-01 22:28:43-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-01 22:28:43-04:00
log8401f4d85887786fbb773d3fd41b8f07a77624b8
tree5bd9f32a5c620774acbb473235095d6676e1559c
parent0e1570bde5b64458449a45989f1b56d6fd651883
signature Signed by PGP key B5690EEEBB952194

fix(web): darken neutral control surfaces (#9064)

Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>

5 files changed, 28 insertions(+), 14 deletions(-)

apps/web/src/components/chat/ComposerBanner.tsx+1-1
......@@ -11,7 +11,7 @@ export type ComposerBannerVariant = "default" | "error" | "info" | "success" | "
1111
1212const surfaceColors = cn(
1313 "[--chat-composer-attached-surface:var(--chat-composer-glass-surface,var(--card))]",
14 "dark:[--chat-composer-attached-surface:var(--chat-composer-glass-surface,color-mix(in_srgb,var(--background)_96%,var(--color-white)))]",
14 "dark:[--chat-composer-attached-surface:var(--chat-composer-glass-surface,var(--surface-raised))]",
1515 "[html[data-theme-id]_&]:[--chat-composer-attached-surface:var(--app-theme-surface-raised)]",
1616);
1717
apps/web/src/components/chat/ComposerSurface.tsx+2-2
......@@ -15,7 +15,7 @@ function Shell({
1515 className={cn(
1616 "group/composer-surface relative isolate mx-auto w-full max-w-3xl",
1717 "[--chat-composer-drawer-inset:1.375rem] [--chat-composer-glass-surface:var(--card)] [--chat-composer-outline:rgb(0_0_0/8%)]",
18 "dark:[--chat-composer-glass-surface:color-mix(in_srgb,var(--background)_96%,var(--color-white))] dark:[--chat-composer-highlight:rgb(255_255_255/3%)] dark:[--chat-composer-outline:color-mix(in_srgb,var(--color-white)_5%,transparent)]",
18 "dark:[--chat-composer-glass-surface:var(--surface-raised)] dark:[--chat-composer-highlight:rgb(255_255_255/3%)] dark:[--chat-composer-outline:color-mix(in_srgb,var(--color-white)_5%,transparent)]",
1919 "[html[data-theme-id]_&]:[--chat-composer-glass-surface:var(--app-theme-surface-raised)] [html[data-theme-id]_&]:[--chat-composer-outline:var(--app-theme-toolbar-border)]",
2020 "dark:[html[data-theme-id]:not([data-theme-id=t3-chat])_&]:[--chat-composer-highlight:color-mix(in_srgb,var(--app-theme-input)_12%,transparent)] dark:[html[data-theme-id]:not([data-theme-id=t3-chat])_&]:[--chat-composer-outline:color-mix(in_srgb,var(--app-theme-input)_30%,var(--background))]",
2121 "dark:[html[data-theme-id=t3-chat]_&]:[--chat-composer-highlight:color-mix(in_srgb,#432d48_12%,transparent)] dark:[html[data-theme-id=t3-chat]_&]:[--chat-composer-outline:#241e28]",
......@@ -86,7 +86,7 @@ function ContextStrip({ className, ...props }: ComponentProps<"div">) {
8686 className={cn(
8787 "group/composer-context relative isolate mx-auto -mt-4 flex w-[calc(100%-2*var(--chat-composer-drawer-inset))] items-center gap-2 overflow-x-clip overflow-y-visible ps-1 pe-2 pt-5 pb-1",
8888 "before:absolute before:inset-0 before:-z-1 before:rounded-b-[16px] before:border before:border-(--chat-composer-outline) before:mask-[linear-gradient(to_bottom,transparent_0_1rem,black_1rem)] before:shadow-[0_12px_28px_-18px_rgb(0_0_0/40%)]",
89 "dark:before:border-white/7 dark:before:bg-[linear-gradient(to_bottom,transparent_0_1rem,rgb(0_0_0/18%)_1rem,transparent_calc(1rem+10px)),linear-gradient(rgb(255_255_255/2%),rgb(255_255_255/2%))] dark:before:shadow-[0_14px_32px_-18px_rgb(0_0_0/75%)]",
89 "dark:before:border-white/7 dark:before:bg-[linear-gradient(to_bottom,transparent_0_1rem,rgb(0_0_0/18%)_1rem,transparent_calc(1rem+10px)),linear-gradient(rgb(255_255_255/1%),rgb(255_255_255/1%))] dark:before:shadow-[0_14px_32px_-18px_rgb(0_0_0/75%)]",
9090 "group-has-data-[composer-banner-surface=attached]/composer-surface:before:bg-[color-mix(in_srgb,var(--chat-composer-glass-surface)_var(--glass-opacity),transparent)] group-has-data-[composer-banner-surface=attached]/composer-surface:before:backdrop-blur-(--glass-blur) group-has-data-[composer-banner-surface=attached]/composer-surface:before:backdrop-saturate-(--glass-saturation)",
9191 "not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:bg-[color-mix(in_srgb,var(--chat-composer-glass-surface)_var(--glass-opacity),transparent)] not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:backdrop-blur-(--glass-blur) not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:backdrop-saturate-(--glass-saturation)",
9292 className,
apps/web/src/index.css+6-6
......@@ -979,19 +979,19 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil
979979
980980 @variant dark {
981981 color-scheme: dark;
982 /* Keep the workspace in the same neutral-black family as sidebar v2.
983 Surfaces lift from this base instead of starting from a milky gray. */
982 /* Keep controls and floating surfaces close to the neutral-black canvas.
983 Borders and hover states provide separation without milky gray fills. */
984984 --background: var(--color-neutral-950);
985 --surface-raised: var(--secondary);
985 --surface-raised: color-mix(in srgb, var(--background) 97%, var(--color-white));
986986 --foreground: var(--color-neutral-100);
987987 --card: color-mix(in srgb, var(--background) 97%, var(--color-white));
988988 --card-foreground: var(--color-neutral-100);
989 --popover: color-mix(in srgb, var(--background) 94%, var(--color-white));
989 --popover: color-mix(in srgb, var(--background) 97%, var(--color-white));
990990 --popover-foreground: var(--color-neutral-100);
991991 --primary: oklch(0.571 0.21 264);
992 --secondary: --alpha(var(--color-white) / 4%);
992 --secondary: --alpha(var(--color-white) / 3%);
993993 --secondary-foreground: var(--color-neutral-100);
994 --muted: --alpha(var(--color-white) / 4%);
994 --muted: --alpha(var(--color-white) / 3%);
995995 --muted-foreground: color-mix(in srgb, var(--color-neutral-500) 90%, var(--color-white));
996996 --accent: --alpha(var(--color-white) / 4%);
997997 --accent-foreground: var(--color-neutral-100);
apps/web/src/themePalette.test.ts+14
......@@ -11,6 +11,7 @@ import {
1111 getThemePreferenceMode,
1212 isKnownThemePreference,
1313 getCustomThemes,
14 getStandardThemeColors,
1415 getStoredCustomThemeCollection,
1516 invalidateCustomThemes,
1617 installCustomTheme,
......@@ -134,6 +135,19 @@ describe("theme files", () => {
134135 expect(asHex(dark.error)).not.toBe(asHex(darkDefaults.error));
135136 });
136137
138 it("keeps stock dark controls in the neutral-black surface hierarchy", () => {
139 expectThemeColors(getStandardThemeColors("dark"), {
140 canvas: "#0a0a0a",
141 surface: "#111111",
142 surfaceRaised: "#111111",
143 surfaceOverlay: "#111111",
144 toolbarControl: "#111111",
145 secondary: "#111111",
146 muted: "#111111",
147 accentSurface: "#141414",
148 });
149 });
150
137151 it("derives readable, distinctive vivid palettes from exact seeds", () => {
138152 const seeds: ReadonlyArray<["light" | "dark", string, string]> = [
139153 ["light", "#f4f9f2", "#1d8a4e"],
apps/web/src/themePalette.ts+5-5
......@@ -402,12 +402,12 @@ const T3_CODE_DARK_THEME_COLORS: ThemeColors = {
402402 toolbar: "#0a0a0a",
403403 toolbarForeground: "#f5f5f5",
404404 toolbarBorder: "#191919",
405 toolbarControl: "#191919",
405 toolbarControl: "#111111",
406406 toolbarControlForeground: "#f5f5f5",
407407 toolbarControlHover: "#141414",
408408 surface: "#111111",
409 surfaceRaised: "#141414",
410 surfaceOverlay: "#191919",
409 surfaceRaised: "#111111",
410 surfaceOverlay: "#111111",
411411 text: "#f5f5f5",
412412 textMuted: "#818181",
413413 border: "#191919",
......@@ -415,9 +415,9 @@ const T3_CODE_DARK_THEME_COLORS: ThemeColors = {
415415 focus: "#346bf1",
416416 accent: "#346bf1",
417417 accentForeground: "#ffffff",
418 secondary: "#141414",
418 secondary: "#111111",
419419 secondaryForeground: "#f5f5f5",
420 muted: "#141414",
420 muted: "#111111",
421421 mutedForeground: "#818181",
422422 placeholder: "#818181",
423423 secondaryLabel: "#818181",