@cssints/rybitten

RYBitten colours for cssints, computed at build time. RYBitten (by meodai, David Aerne in its licence; MIT) turns red-yellow-blue coordinates into RGB through a cube: the eight corners of a colour model (white, red, yellow, orange, blue, violet, green, black). It ships 36 of them, from Boutet (1708) and Goethe to Itten, Munsell and Albers, so the same hue is another colour in each. color(hue, options) gives one hex colour, wheel(steps, options) and shades(hue, lightness, options) return plain DTCG data (a colour group, steps "1" to "N") that you pass to createTokens yourself, and overrides(group) turns a group into the override object of createGlobalTheme. The package has no runtime and no scope(): like @cssints/ramp and the sets of @cssints/tokens, a group is data, so it goes under any name, sits beside other tokens in one call, and its steps get @property rules, themes and check.contrast from cssints.

// tokens.ts
import { createGlobalTheme, createTokens, media } from "cssints" with { type: "cssints" };
import { overrides, shades, wheel } from "@cssints/rybitten";

export const t = createTokens({
  hue: wheel(12, { cube: "itten" }),
  paper: shades(0, [1, 0.96, 0], { cube: "itten", saturation: 0 }),
});

// the paper and the ink swap in the dark
createGlobalTheme(t, media("(prefers-color-scheme: dark)"), {
  paper: overrides(shades(0, [0, 0.04, 1], { cube: "itten", saturation: 0 })),
});
// text.ts
import { bg, check, cn, color } from "cssints" with { type: "cssints" };

import { t } from "./tokens.ts";

check.contrast(t.paper._3, t.paper._1, { min: 12 }); // the ink on the paper, light and dark
export const text = cn(color(t.hue._9), bg(t.paper._1));

The sheet of text.ts:

@property --hue-9 {
  syntax: "<color>";
  inherits: true;
  initial-value: #1699da;
}
@property --paper-1 {
  syntax: "<color>";
  inherits: true;
  initial-value: #fdf6ed;
}
@layer _.k {
  @media (prefers-color-scheme: dark) {
    :root {
      --paper-1: #1d1c1c;
      --paper-2: #1e1d1d;
      --paper-3: #fdf6ed;
    }
  }
}
@layer _.a {
  ._14bfx2y {
    color: var(--hue-9);
  }
  ._1j4wng5 {
    background-color: var(--paper-1);
  }
}

The functions

A group is not a contrast ramp: the colours of a cube are what its makers painted, and no ratio is promised. For a colour that must pass check.contrast, use a hue of the wheel as the base of an @cssints/ramp contrast ramp, which finds the step with the ratio you need (the docs site does this for its accent, see below), or check the pair as above.

Cubes

cubes is RYBitten's own map (import { cubes } from "rybitten/cubes"): itten (the default), munsell, bezold, goethe, albers, apple90s, harris, cmy, ... with title, author, year and reference. The hue 240 in four of them:

Cube Blue Paper Ink
itten #1699da #fdf6ed #1d1c1c
munsell #3b8fab #e4dac5 #2e2c26
albers #1161aa #e7ebed #000001
goethe #5f9dbf #efebe1 #08090d

Limits

Credits

Colour maths and the historical cubes are RYBitten by meodai (David Aerne; MIT), a dependency of this package, whose licence is reproduced in LICENSE here. The cubes cite their historical sources: see RYBitten's README.

cd packages/rybitten && bun run test        # the colours and the errors, then a module through the engine (check.contrast passes, a hue on paper fails)
cd packages/rybitten && bun run typecheck   # the type test (test/types/rybitten.ts)