diff --git a/src/lib/__tests__/color.test.ts b/src/lib/__tests__/color.test.ts index e3bdb1c..222af79 100644 --- a/src/lib/__tests__/color.test.ts +++ b/src/lib/__tests__/color.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from "vitest"; -import { adjustAccentColor, type ColorResult } from "../color"; +import { adjustAccentColor } from "../color"; /** * adjustAccentColor のユニットテスト diff --git a/src/lib/color.ts b/src/lib/color.ts index 02ab06b..6f11f76 100644 --- a/src/lib/color.ts +++ b/src/lib/color.ts @@ -21,14 +21,10 @@ const TARGET_MIN_LIGHTNESS = 45; const TARGET_MAX_LIGHTNESS = 85; const HOVER_LIGHTEN_AMOUNT = 0.1; -/** - * Adjusts the given color to be suitable for use as an accent color in a dark theme. - * Ensures sufficient saturation and appropriate lightness. - * @param color Hex string or RGB object/array - */ -export function adjustAccentColor(color: string | [number, number, number] | { r: number; g: number; b: number }): ColorResult { - let c; +type ColorInput = string | [number, number, number] | { r: number; g: number; b: number }; +function parseColor(color: ColorInput) { + let c; if (Array.isArray(color)) { c = colord({ r: color[0], g: color[1], b: color[2] }); } else { @@ -39,26 +35,32 @@ export function adjustAccentColor(color: string | [number, number, number] | { r if (!c.isValid()) { c = colord(DEFAULT_ACCENT_COLOR); } + return c; +} - // Adjust saturation: if too low, saturate +function ensureSaturation(c: ReturnType) { const s = c.toHsl().s; if (s < MIN_SATURATION_FOR_HIGH_BOOST) { - c = c.saturate(HIGH_SATURATION_BOOST); + return c.saturate(HIGH_SATURATION_BOOST); } else if (s < MIN_SATURATION_FOR_LOW_BOOST) { - c = c.saturate(LOW_SATURATION_BOOST); + return c.saturate(LOW_SATURATION_BOOST); } + return c; +} - // Adjust lightness for dark mode context - // Should be bright enough to glow, but not white +function adjustLightness(c: ReturnType) { const l = c.toHsl().l; if (l < TARGET_MIN_LIGHTNESS) { // Lift to at least TARGET_MIN_LIGHTNESS - c = c.lighten((TARGET_MIN_LIGHTNESS - l) / 100); + return c.lighten((TARGET_MIN_LIGHTNESS - l) / 100); } else if (l > TARGET_MAX_LIGHTNESS) { // Dim to at most TARGET_MAX_LIGHTNESS - c = c.darken((l - TARGET_MAX_LIGHTNESS) / 100); + return c.darken((l - TARGET_MAX_LIGHTNESS) / 100); } + return c; +} +function generateColorResult(c: ReturnType): ColorResult { const hex = c.toHex(); const rgb = c.toRgb(); const rgbString = `${rgb.r}, ${rgb.g}, ${rgb.b}`; @@ -72,3 +74,15 @@ export function adjustAccentColor(color: string | [number, number, number] | { r accentHover: hover, }; } + +/** + * Adjusts the given color to be suitable for use as an accent color in a dark theme. + * Ensures sufficient saturation and appropriate lightness. + * @param color Hex string or RGB object/array + */ +export function adjustAccentColor(color: ColorInput): ColorResult { + let c = parseColor(color); + c = ensureSaturation(c); + c = adjustLightness(c); + return generateColorResult(c); +}