a tool for shared writing and social publishing
1import { parse, ColorSpace, sRGB, distance, OKLab, to } from "colorjs.io/fn";
2
3// define the color defaults for everything
4export const ThemeDefaults = {
5 "theme/page-background": "#FDFCFA",
6 "theme/card-background": "#FFFFFF",
7 "theme/primary": "#272727",
8 "theme/highlight-1": "#FFFFFF",
9 "theme/highlight-2": "#EDD280",
10 "theme/highlight-3": "#FFCDC3",
11
12 //everywhere else, accent-background = accent-1 and accent-text = accent-2.
13 // we just need to create a migration pipeline before we can change this
14 "theme/accent-text": "#FFFFFF",
15 "theme/accent-background": "#57822B",
16 "theme/accent-contrast": "#57822B",
17};
18
19// Compares two RGB color strings in OKLab space and returns both the overall
20// perceptual distance and the chroma (hue/saturation) difference.
21//
22// Why both? Dark colors are compressed in OKLab lightness, so two colors can
23// have a small overall distance yet be clearly distinguishable by hue (e.g.
24// dark blue vs black). Checking chromaDiff lets callers tell apart "two
25// similar grays" from "a dark chromatic color next to a gray/black".
26export function compareColors(color1: string, color2: string) {
27 ColorSpace.register(sRGB);
28 ColorSpace.register(OKLab);
29
30 let parsedColor1 = parse(`rgb(${color1})`);
31 let parsedColor2 = parse(`rgb(${color2})`);
32
33 let [, a1, b1] = to(parsedColor1, "oklab").coords;
34 let [, a2, b2] = to(parsedColor2, "oklab").coords;
35
36 return {
37 distance: distance(parsedColor1, parsedColor2, "oklab"),
38 chromaDiff: Math.sqrt((a1 - a2) ** 2 + (b1 - b2) ** 2),
39 };
40}