diff --git a/app/components/CustomThemeSelector.tsx b/app/components/CustomThemeSelector.tsx index c64d55e22..cdeb83503 100644 --- a/app/components/CustomThemeSelector.tsx +++ b/app/components/CustomThemeSelector.tsx @@ -68,13 +68,13 @@ export function themeInputFromCustomTheme( customTheme: CustomTheme, ): ThemeInput { return { - baseHue: customTheme["--base-h"] ?? DEFAULT_THEME_INPUT.baseHue, + baseHue: customTheme["--_base-h"] ?? DEFAULT_THEME_INPUT.baseHue, baseChroma: - (customTheme["--base-c-1"] ?? 0) / BASE_CHROMA_MULTIPLIERS[1] || + (customTheme["--_base-c-1"] ?? 0) / BASE_CHROMA_MULTIPLIERS[1] || DEFAULT_THEME_INPUT.baseChroma, - accentHue: customTheme["--acc-h"] ?? DEFAULT_THEME_INPUT.accentHue, + accentHue: customTheme["--_acc-h"] ?? DEFAULT_THEME_INPUT.accentHue, accentChroma: - (customTheme["--acc-c-1"] ?? 0) / ACCENT_CHROMA_MULTIPLIERS[1] || + (customTheme["--_acc-c-1"] ?? 0) / ACCENT_CHROMA_MULTIPLIERS[1] || DEFAULT_THEME_INPUT.accentChroma, }; } diff --git a/app/db/tables.ts b/app/db/tables.ts index 0b1b44538..0300fd0b2 100644 --- a/app/db/tables.ts +++ b/app/db/tables.ts @@ -52,6 +52,13 @@ export const CUSTOM_THEME_VARS = [ "--_acc-c-3", "--_acc-c-4", "--_acc-c-5", + "--_second-h", + "--_second-c-0", + "--_second-c-1", + "--_second-c-2", + "--_second-c-3", + "--_second-c-4", + "--_second-c-5", ] as const; export type CustomThemeVar = (typeof CUSTOM_THEME_VARS)[number]; export type CustomTheme = Record; diff --git a/app/styles/vars.css b/app/styles/vars.css index 286ad4038..dfdf68939 100644 --- a/app/styles/vars.css +++ b/app/styles/vars.css @@ -26,6 +26,14 @@ html { --_acc-c-4: 0.2616; --_acc-c-5: 0.1344; + --_second-h: 90; + --_second-c-0: 0.05295305624247283; + --_second-c-1: 0.10680119733498437; + --_second-c-2: 0.0816; + --_second-c-3: 0.06; + --_second-c-4: 0.10814382461004245; + --_second-c-5: 0.06493861022758024; + --_radius-box: 3; --_radius-field: 2; --_radius-selector: 2; @@ -76,9 +84,15 @@ html.dark { --color-accent: oklch(52.262% var(--_acc-c-1) var(--_acc-h)); --color-accent-high: oklch(83.419% var(--_acc-c-2) var(--_acc-h)); - --color-second-low: oklch(from var(--color-accent-low) l c calc(h + 180)); - --color-second: oklch(from var(--color-accent) l c calc(h + 180)); - --color-second-high: oklch(from var(--color-accent-high) l c calc(h + 180)); + --color-second-low: oklch( + from var(--color-accent-low) l var(--_second-c-0) var(--_second-h) + ); + --color-second: oklch( + from var(--color-accent) l var(--_second-c-1) var(--_second-h) + ); + --color-second-high: oklch( + from var(--color-accent-high) l var(--_second-c-2) var(--_second-h) + ); --color-text-accent: var(--color-accent-high); --color-text-second: var(--color-second-high); @@ -120,9 +134,15 @@ html.light { --color-accent: oklch(52.919% var(--_acc-c-4) var(--_acc-h)); --color-accent-high: oklch(31.777% var(--_acc-c-5) var(--_acc-h)); - --color-second-low: oklch(from var(--color-accent-low) l c calc(h + 180)); - --color-second: oklch(from var(--color-accent) l c calc(h + 180)); - --color-second-high: oklch(from var(--color-accent-high) l c calc(h + 180)); + --color-second-low: oklch( + from var(--color-accent-low) l var(--_second-c-0) var(--_second-h) + ); + --color-second: oklch( + from var(--color-accent) l var(--_second-c-1) var(--_second-h) + ); + --color-second-high: oklch( + from var(--color-accent-high) l var(--_second-c-2) var(--_second-h) + ); --color-text-accent: var(--color-accent); --color-text-second: var(--color-second); diff --git a/app/utils/oklch-gamut.ts b/app/utils/oklch-gamut.ts index c4f01ccba..fb3783981 100644 --- a/app/utils/oklch-gamut.ts +++ b/app/utils/oklch-gamut.ts @@ -292,6 +292,17 @@ export function clampThemeToGamut(input: ThemeInput): CustomTheme { }, ); + const secondaryHue = (input.accentHue + 180) % 360; + const secondaryHueRadians = secondaryHue * (Math.PI / 180); + + const clampedSecondaryChromas = ACCENT_LIGHTNESS_VALUES.map( + (lightness, index) => { + const desiredChroma = + input.accentChroma * ACCENT_CHROMA_MULTIPLIERS[index]; + return clampChromaForColor(lightness, desiredChroma, secondaryHueRadians); + }, + ); + return { "--_base-h": input.baseHue, "--_base-c-0": clampedBaseChromas[0], @@ -309,5 +320,12 @@ export function clampThemeToGamut(input: ThemeInput): CustomTheme { "--_acc-c-3": clampedAccentChromas[3], "--_acc-c-4": clampedAccentChromas[4], "--_acc-c-5": clampedAccentChromas[5], + "--_second-h": secondaryHue, + "--_second-c-0": clampedSecondaryChromas[0], + "--_second-c-1": clampedSecondaryChromas[1], + "--_second-c-2": clampedSecondaryChromas[2], + "--_second-c-3": clampedSecondaryChromas[3], + "--_second-c-4": clampedSecondaryChromas[4], + "--_second-c-5": clampedSecondaryChromas[5], }; }