You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.1 KiB

import colors from "./colors.json";
import { hslToHex, hexToHsl, contrastRatio } from "./colors";
import { clamp } from "./math";
type Pallette = {
bg: string;
fg: string;
red: string;
green: string;
shade1: string;
shade2: string;
shade3: string;
shade4: string;
};
const MIN_CONTRAST = 3.0;
const FALLBACK_WHITE = "#ffffff";
const bg = colors.bg ?? "#0f0f10";
const fg = colors.fg ?? "#e6e6e6";
const redHue = colors.accentRedHue ?? 0;
const greenHue = colors.accentGreenHue ?? 140;
const sat = colors.accentSaturation ?? 65;
const light = colors.accentLightness ?? 60;
const steps = colors.shadeSteps ?? 4;
// generate accents
// ensure reasonable contrast with bg; if too low, nudge lightness
const fixContrast = (
ref: string,
hue: number,
sat: number,
lightness: number,
) => {
let cur = hslToHex(hue, sat, lightness);
let ctr = contrastRatio(cur, ref);
let l = lightness;
let tries = 0;
while (ctr < MIN_CONTRAST && tries < 10) {
l = clamp(l + 6, 0, 100); // make lighter
cur = hslToHex(hue, sat, l);
ctr = contrastRatio(cur, ref);
tries++;
}
return cur;
};
const red = fixContrast(bg, redHue, sat, light);
const green = fixContrast(bg, greenHue, sat, light);
// generate 4 darker shades from fg towards bg by lightness interpolation
const { h: fgH, s: fgS, l: fgL } = hexToHsl(fg);
const { s: bgS, l: bgL } = hexToHsl(bg);
const shades: string[] = [];
for (let i = 1; i <= steps; i++) {
const t = i / (steps + 1); // fraction towards bg
const l = fgL + (bgL - fgL) * t;
const s = fgS + (bgS - fgS) * t;
const h = fgH; // keep fg hue
shades.push(hslToHex(h, s, l));
}
const pallette: Pallette = {
bg,
fg,
red,
green,
shade1: shades[0] ?? FALLBACK_WHITE,
shade2: shades[1] ?? FALLBACK_WHITE,
shade3: shades[2] ?? FALLBACK_WHITE,
shade4: shades[3] ?? FALLBACK_WHITE,
};
function* createPalletteGenerator() {
const keys = Object.keys(pallette) as (keyof Pallette)[];
for (let key of keys) {
yield [key, pallette[key]];
}
}
const palletteGenerator = createPalletteGenerator();
export { pallette, palletteGenerator };
export type { Pallette };