Replace accent presets with the sunset-to-sea family
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 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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: '',
|
||||
|
||||
@@ -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: '',
|
||||
|
||||
+94
-118
@@ -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<string, string> {
|
||||
return {
|
||||
colorBrandBackground: ramp[110],
|
||||
@@ -174,10 +149,10 @@ function buildPreset(
|
||||
}
|
||||
|
||||
export const ACCENT_PRESETS: Record<AccentColor, AccentPreset> = {
|
||||
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
|
||||
|
||||
+1
-1
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user