Harmonies & Palette Generation
Color Harmonies
All harmonies are implemented as hue rotations on the normalized hex value — saturation and lightness are unchanged.
complement(color)
string — a #rrggbb color
The complementary color — a 180° hue rotation.
triadic(color)
[string, string, string]
3 colors evenly spaced 120° apart on the color wheel.
analogous(color, angle?)
[string, string, string]
3 neighboring colors — the input plus one rotated -angle and one rotated +angle. angle defaults to 30.
splitComplementary(color)
[string, string, string]
The base color plus two colors at 150° and 210° — a softer alternative to the direct complement.
tetradic(color)
[string, string, string, string]
4 colors evenly spaced 90° apart on the color wheel.
import { triadic, analogous, tetradic } from 'color-value-tools'
triadic('#6c3483') // ['#6c3483', '#836d34', '#34836d']
analogous('#6c3483', 45) // ['#343783', '#6c3483', '#83345e']
tetradic('#6c3483') // ['#6c3483', '#834534', '#4b8334', '#347283']Palette Generation
colorShades(color, steps?)
string[]
A light-to-dark scale by sweeping HSL lightness from 100 to 0 at the color's own hue/saturation. steps defaults to 9.
monochromatic(color, steps?)
string[]
A scale at fixed lightness with varying saturation. steps defaults to 5.
tints(color, steps?)
string[]
Mixes the color toward white in Oklab — equivalent to interpolateColors(color, '#ffffff', steps, { space: 'oklab' }). steps defaults to 5.
shades(color, steps?)
string[]
Mixes the color toward black in Oklab. steps defaults to 5.
tones(color, steps?, gray?)
string[]
Mixes the color toward a gray of your choice in Oklab. steps defaults to 5; gray defaults to '#808080'.
randomColor(options?)
function randomColor(options?: {
hRange?: [number, number] // default: [0, 360]
sRange?: [number, number] // default: [40, 90]
lRange?: [number, number] // default: [30, 70]
}): stringstring — a #rrggbb color
Picks a uniformly random value inside each of the three HSL ranges (options sets independent min/max for hue, saturation, and lightness). Each call returns a different color — useful for demo data, avatars, or chart palettes, not for deterministic output.
import { randomColor } from 'color-value-tools'
randomColor() // e.g. '#2a9d8a' — anywhere in the default ranges
randomColor({ hRange: [200, 260], sRange: [60, 80], lRange: [40, 60] }) // e.g. '#2b64bf' — blues onlyLazy generation
generateTints(color, steps, opts?)
Generator<string>
Lazy, generator-function equivalent of tints — yields one color at a time instead of building the whole array upfront. opts: { format?: 'hex' | 'rgb' | 'hsl' }.
generateShades(color, steps, opts?)
Generator<string>
Lazy, generator-function equivalent of shades. Same signature shape as generateTints.
import { generateTints } from 'color-value-tools'
// Stop early without computing the remaining steps
const first5: string[] = []
for (const tint of generateTints('#e74c3c', 100)) {
first5.push(tint)
if (first5.length === 5) break
}