From af9300d5e3c899a86872c3ed727dc8557ce7c41d Mon Sep 17 00:00:00 2001 From: debont80 Date: Tue, 23 Jun 2026 13:10:53 -0400 Subject: [PATCH] Replace accent presets with the sunset-to-sea family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swap Toffee/Slate/Evergreen/Lavender for rose/coral/amber/teal — four ramps sharing one lightness/saturation curve (src/renderer/src/theme.ts). Default accent is now teal. Updates ACCENT_COLORS (src/shared/ipc.ts), the settings default + stale-value coercion (src/main/settings.ts), the dev/store fallbacks (main.tsx, store/settings.ts), and the native window background to match the new pageBackground.light (src/main/index.ts). Co-Authored-By: Claude Opus 4.8 --- src/main/index.ts | 2 +- src/main/settings.ts | 7 +- src/renderer/src/main.tsx | 2 +- src/renderer/src/store/settings.ts | 2 +- src/renderer/src/theme.ts | 212 +++++++++++++---------------- src/shared/ipc.ts | 2 +- 6 files changed, 104 insertions(+), 123 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 29dda86..68bddb2 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -63,7 +63,7 @@ let mainWindow: BrowserWindow | null = null // src/renderer/src/theme.ts. Set as the window's NATIVE background so the // one-frame compositor repaint (when a tooltip/dropdown overlay first paints on // Windows) shows the app's current color instead of a mismatched white flash. -const THEME_BACKGROUND = { light: '#f6f1ef', dark: '#161618' } as const +const THEME_BACKGROUND = { light: '#f7f7f8', dark: '#161618' } as const // 'system' isn't a real background — resolve it against the OS's current // preference (nativeTheme.themeSource defaults to 'system', so this tracks it diff --git a/src/main/settings.ts b/src/main/settings.ts index e185f7b..9f33c88 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -23,7 +23,7 @@ const DEFAULTS: Settings = { maxConcurrent: 2, filenameTemplate: '%(title)s.%(ext)s', theme: 'light', - accentColor: 'toffee', + accentColor: 'teal', clipboardWatch: true, downloadOptions: DEFAULT_DOWNLOAD_OPTIONS, proxy: '', @@ -106,6 +106,11 @@ export function getSettings(): Settings { if (!downloadOptionsEqual(sanitized, cur.downloadOptions)) { s.set('downloadOptions', sanitized) } + // Coerce an accentColor left over from a renamed/removed preset (e.g. an old + // 'toffee' or 'indigo' default) onto the current default, so it resolves cleanly. + if (!(ACCENT_COLORS as readonly string[]).includes(cur.accentColor)) { + s.set('accentColor', DEFAULTS.accentColor) + } return s.store } diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx index ec9606f..45e7133 100644 --- a/src/renderer/src/main.tsx +++ b/src/renderer/src/main.tsx @@ -18,7 +18,7 @@ if (import.meta.env.DEV && !window.api) { maxConcurrent: 2, filenameTemplate: '%(title)s.%(ext)s', theme: 'light', - accentColor: 'toffee', + accentColor: 'teal', clipboardWatch: true, downloadOptions: DEFAULT_DOWNLOAD_OPTIONS, proxy: '', diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts index ce5fbe8..bcd9cd5 100644 --- a/src/renderer/src/store/settings.ts +++ b/src/renderer/src/store/settings.ts @@ -12,7 +12,7 @@ const FALLBACK: Settings = { maxConcurrent: 2, filenameTemplate: '%(title)s.%(ext)s', theme: 'light', - accentColor: 'toffee', + accentColor: 'teal', clipboardWatch: true, downloadOptions: DEFAULT_DOWNLOAD_OPTIONS, proxy: '', diff --git a/src/renderer/src/theme.ts b/src/renderer/src/theme.ts index f29fcf5..7c65b5f 100644 --- a/src/renderer/src/theme.ts +++ b/src/renderer/src/theme.ts @@ -6,88 +6,87 @@ import { } from '@fluentui/react-components' import type { AccentColor } from '@shared/ipc' -// Toffee-brown brand ramp. The product palette (50–950) is remapped onto -// Fluent's 16-stop BrandVariants (10 = darkest … 160 = lightest) so the LIGHT -// primary lands on toffee-600 (#825e4a) at index 80, and the DARK primary on a -// lightened toffee-400 (#b5917d) — applied via toffeeDarkOverrides below. -const toffee: BrandVariants = { - 10: '#17100d', - 20: '#201713', - 30: '#2e211a', - 40: '#412f25', - 50: '#4f3a2d', - 60: '#614638', - 70: '#735140', - 80: '#825e4a', - 90: '#946b54', - 100: '#a2755d', - 110: '#b5917d', - 120: '#c7ac9e', - 130: '#d3bcae', - 140: '#dac8be', - 150: '#ece3df', - 160: '#f6f1ef' +// "Sunset-to-sea" accent family. All four ramps are built the same way — one +// shared lightness/saturation curve mapped onto Fluent's 16 BrandVariants stops: +// a deep near-black floor (idx 10), a white-text-safe LIGHT primary at idx 80, a +// bright DARK-mode lift at idx 110 (applied via buildDarkOverrides), and a near- +// white top (idx 160). The idx-80 primaries are tuned to equal luminance so none +// reads louder than the rest. Hues are three analogous warms — rose → coral → +// amber — plus teal as the cool complement that anchors the set. +const rose: BrandVariants = { + 10: '#20090f', + 20: '#3b0e1a', + 30: '#581124', + 40: '#75132d', + 50: '#921637', + 60: '#ae1941', + 70: '#c91e4c', + 80: '#dc2a5a', + 90: '#e34670', + 100: '#eb6186', + 110: '#f17e9d', + 120: '#f197af', + 130: '#f0b0c1', + 140: '#f0c9d3', + 150: '#f2dfe4', + 160: '#f8f2f3' } -// Additional accent presets (Phase E). Each ramp reuses toffee's exact -// lightness curve at a different hue, so they read as siblings rather than -// arbitrary colors — only `buildDarkOverrides` below differs from toffee's -// hand-tuned dark lift. -const slate: BrandVariants = { - 10: '#0f1215', - 20: '#15191e', - 30: '#1e242a', - 40: '#2b323b', - 50: '#343d48', - 60: '#404c59', - 70: '#4b5968', - 80: '#566576', - 90: '#617387', - 100: '#6b7e94', - 110: '#8998a9', - 120: '#a6b2bf', - 130: '#b7c0cb', - 140: '#c4cbd4', - 150: '#e1e5ea', - 160: '#f1f2f5' +const coral: BrandVariants = { + 10: '#210e08', + 20: '#39150b', + 30: '#541c0d', + 40: '#6f230e', + 50: '#8a2a0f', + 60: '#a43111', + 70: '#bc3915', + 80: '#d3421a', + 90: '#e85831', + 100: '#f07554', + 110: '#f5957a', + 120: '#f4a893', + 130: '#f3bdae', + 140: '#f1d0c7', + 150: '#f3e3de', + 160: '#f8f3f1' } -const evergreen: BrandVariants = { - 10: '#0d1712', - 20: '#12211a', - 30: '#1a2e25', - 40: '#254134', - 50: '#2d4f3f', - 60: '#37624e', - 70: '#40735b', - 80: '#498368', - 90: '#549576', - 100: '#5ca382', - 110: '#7cb69b', - 120: '#9dc8b4', - 130: '#afd2c2', - 140: '#bedacd', - 150: '#deede6', - 160: '#eff6f3' +const amber: BrandVariants = { + 10: '#221907', + 20: '#342507', + 30: '#463107', + 40: '#593d06', + 50: '#6b4905', + 60: '#7d5506', + 70: '#8d6007', + 80: '#9c6b0a', + 90: '#c8890a', + 100: '#f4a60a', + 110: '#f7b634', + 120: '#f8c359', + 130: '#f3ce83', + 140: '#f0daad', + 150: '#f1e7d3', + 160: '#f9f6f1' } -const lavender: BrandVariants = { - 10: '#120e16', - 20: '#191320', - 30: '#231b2d', - 40: '#32273f', - 50: '#3d2f4d', - 60: '#4b3a5f', - 70: '#58446f', - 80: '#644e7e', - 90: '#725890', - 100: '#7d619e', - 110: '#9781b1', - 120: '#b1a0c5', - 130: '#c0b2d0', - 140: '#cbc0d8', - 150: '#e5dfec', - 160: '#f2f0f6' +const teal: BrandVariants = { + 10: '#091f20', + 20: '#0a2d2e', + 30: '#0b3c3e', + 40: '#0c4b4d', + 50: '#0d595c', + 60: '#0e686b', + 70: '#117578', + 80: '#148185', + 90: '#18a8ad', + 100: '#19d2d9', + 110: '#33e4ea', + 120: '#5ce6ea', + 130: '#86e6e9', + 140: '#afe7e9', + 150: '#d3edee', + 160: '#f2f8f8' } // Rounder corners — buttons/inputs ~10px, cards ~16px. NOT pills. @@ -101,32 +100,8 @@ const friendlyRadii = { // Dark mode keeps Fluent's NEUTRAL (charcoal) surfaces and uses the accent // ramp only for buttons/links. The default dark brand is too low-contrast on // near-black, so lift the brand to ramp-110 and flip on-brand text to dark for -// legible buttons. Toffee's lift was hand-tuned (hover/pressed/stroke shades -// don't land exactly on ramp stops); newer presets use buildDarkOverrides, -// which derives the same shape directly from each ramp's own stops. -const toffeeDarkOverrides = { - colorBrandBackground: '#b5917d', - colorBrandBackgroundHover: '#c19f8c', - colorBrandBackgroundPressed: '#a2755d', - colorBrandBackgroundSelected: '#b5917d', - colorNeutralForegroundOnBrand: '#1c1611', - colorCompoundBrandBackground: '#b5917d', - colorCompoundBrandBackgroundHover: '#c19f8c', - colorCompoundBrandBackgroundPressed: '#a2755d', - colorCompoundBrandForeground1: '#c7ac9e', - colorCompoundBrandForeground1Hover: '#d3bcae', - colorCompoundBrandForeground1Pressed: '#b5917d', - colorCompoundBrandStroke: '#b5917d', - colorCompoundBrandStrokeHover: '#c19f8c', - colorBrandForeground1: '#c7ac9e', - colorBrandForeground2: '#d3bcae', - colorBrandForegroundLink: '#c7ac9e', - colorBrandForegroundLinkHover: '#d3bcae', - colorBrandForegroundLinkPressed: '#b5917d', - colorBrandStroke1: '#b5917d', - colorBrandStroke2: '#5f4636' -} as const - +// legible buttons. buildDarkOverrides derives that whole shape — hover/pressed/ +// stroke shades and all — directly from each ramp's own stops. function buildDarkOverrides(ramp: BrandVariants): Record { return { colorBrandBackground: ramp[110], @@ -174,10 +149,10 @@ function buildPreset( } export const ACCENT_PRESETS: Record = { - toffee: buildPreset('Toffee', toffee, toffeeDarkOverrides), - slate: buildPreset('Slate', slate, buildDarkOverrides(slate)), - evergreen: buildPreset('Evergreen', evergreen, buildDarkOverrides(evergreen)), - lavender: buildPreset('Lavender', lavender, buildDarkOverrides(lavender)) + rose: buildPreset('Rose', rose, buildDarkOverrides(rose)), + coral: buildPreset('Coral', coral, buildDarkOverrides(coral)), + amber: buildPreset('Amber', amber, buildDarkOverrides(amber)), + teal: buildPreset('Teal', teal, buildDarkOverrides(teal)) } export const ACCENT_OPTIONS: { value: AccentColor; label: string; swatch: string }[] = ( @@ -189,29 +164,30 @@ export const ACCENT_OPTIONS: { value: AccentColor; label: string; swatch: string })) export function getTheme(accent: AccentColor, mode: 'light' | 'dark'): Theme { - const preset = ACCENT_PRESETS[accent] ?? ACCENT_PRESETS.toffee + const preset = ACCENT_PRESETS[accent] ?? ACCENT_PRESETS.teal return mode === 'dark' ? preset.dark : preset.light } -// Page background behind the app shell. Light: warm toffee paper. Dark: neutral -// charcoal (NOT brown) — the accent shows up only on buttons/links, independent -// of which preset is chosen. +// Page background behind the app shell. Light: a clean, barely-cool off-white. +// Dark: neutral charcoal. Intentionally accent-INDEPENDENT — the accent shows up +// only on buttons/links, so this stays neutral whichever preset is chosen. +// Keep light/dark in sync with THEME_BACKGROUND in src/main/index.ts. export const pageBackground = { - light: '#f6f1ef', + light: '#f7f7f8', dark: '#161618' } // Per-kind thumbnail tints. Video vs audio differ by ramp DEPTH rather than a -// competing hue, keeping the monochrome-warm Studio look. Theme-aware (light/ -// dark) but intentionally NOT accent-aware — these sit on the neutral card -// surface and shouldn't shift hue when the user picks a different accent. +// competing hue, keeping a monochrome look. Theme-aware (light/dark) but +// intentionally NOT accent-aware — a fixed neutral grey that sits quietly on the +// card surface under any of the accent presets, warm or cool. export const thumbColors = { light: { - video: { bg: '#ece3df', fg: '#825e4a' }, - audio: { bg: '#dac8be', fg: '#5f4636' } + video: { bg: '#eeeef0', fg: '#5e616a' }, + audio: { bg: '#e2e2e6', fg: '#4a4d55' } }, dark: { - video: { bg: '#252025', fg: '#c7ac9e' }, - audio: { bg: '#2b2620', fg: '#b5917d' } + video: { bg: '#26262a', fg: '#b5b6bd' }, + audio: { bg: '#2c2c31', fg: '#a0a1aa' } } } as const diff --git a/src/shared/ipc.ts b/src/shared/ipc.ts index 4e2711c..5789414 100644 --- a/src/shared/ipc.ts +++ b/src/shared/ipc.ts @@ -77,7 +77,7 @@ export const COOKIE_BROWSERS = ['chrome', 'edge', 'firefox', 'brave', 'opera', ' export type CookieBrowser = (typeof COOKIE_BROWSERS)[number] /** Accent color presets for the brand ramp (see src/renderer/src/theme.ts). */ -export const ACCENT_COLORS = ['toffee', 'slate', 'evergreen', 'lavender'] as const +export const ACCENT_COLORS = ['rose', 'coral', 'amber', 'teal'] as const export type AccentColor = (typeof ACCENT_COLORS)[number] /** UI color theme: an explicit mode, or 'system' to follow the OS preference. */