color.ts

 1import chroma, { Scale } from "chroma-js";
 2import { ColorToken } from "../tokens";
 3
 4export type Color = string;
 5export type ColorRampStep = { value: Color; type: "color"; description: string };
 6export type ColorRamp = {
 7  [index: number]: ColorRampStep;
 8};
 9
10export function colorRamp(
11  color: Color | [Color, Color],
12  options?: { steps?: number; increment?: number; }
13): ColorRamp {
14  let scale: Scale;
15  if (Array.isArray(color)) {
16    const [startColor, endColor] = color;
17    scale = chroma.scale([startColor, endColor]);
18  } else {
19    let hue = Math.round(chroma(color).hsl()[0]);
20    let startColor = chroma.hsl(hue, 0.88, 0.96);
21    let endColor = chroma.hsl(hue, 0.68, 0.12);
22    scale = chroma
23      .scale([startColor, color, endColor])
24      .domain([0, 0.5, 1])
25      .mode("hsl")
26      .gamma(1)
27      // .correctLightness(true)
28      .padding([0, 0]);
29  }
30
31  const ramp: ColorRamp = {};
32  const steps = options?.steps || 10;
33  const increment = options?.increment || 100;
34
35  scale.colors(steps, "hex").forEach((color, ix) => {
36    const step = ix * increment;
37    ramp[step] = {
38      value: color,
39      description: `Step: ${step}`,
40      type: "color",
41    };
42  });
43
44  return ramp;
45}
46
47export function withOpacity(color: ColorToken, opacity: number): ColorToken {
48  return {
49    ...color,
50    value: chroma(color.value).alpha(opacity).hex()
51  };
52}