Pote.Palette (Pote v3.0.0)

Copy Markdown View Source

Procedural palette generation.

generate/2 turns a seed into a deterministic list of RGB colors starting from a color harmony (Pote.Harmonies) and optionally enforcing a WCAG AA luminance ladder: when colors are sorted by relative luminance, each consecutive pair meets the contrast target.

The generator is pure: for the same seed and opts it always returns the same palette, which makes it suitable for themes that must be stable across runs.

Examples

iex> Pote.Palette.generate(42, count: 5) |> length()
5

iex> Pote.Palette.generate(42, count: 5) == Pote.Palette.generate(42, count: 5)
true

Summary

Functions

Generates a deterministic palette from seed.

Returns true when consecutive colors in palette (sorted by relative luminance) have a WCAG 2.1 contrast ratio of at least target (default: 4.5, the AA threshold for normal text).

Types

base()

@type base() :: :harmonious | :analogous | :complementary

rgb()

@type rgb() :: Pote.rgb()

Functions

generate(seed, opts \\ [])

@spec generate(
  integer(),
  keyword()
) :: [rgb()]

Generates a deterministic palette from seed.

Options

  • :count - number of colors to return (default: 5, min 2)
  • :base - starting harmony:
    • :harmonious (default) - triad, the classic balanced set
    • :analogous - adjacent hues on the wheel
    • :complementary - base + opposite
  • :wcag_aa - when true, consecutive colors in luminance order satisfy the :contrast_target ratio (default: false)
  • :contrast_target - WCAG ratio to enforce (default: 4.5)

WCAG note

Enforcing a ratio between every pair of colors is mathematically impossible for count >= 4 (WCAG's max ratio is 21:1, so 4.5^4 ≈ 410 would be required). Instead we guarantee the usable property: when colors are sorted by relative luminance, each consecutive pair meets the target — a "luminance ladder" that makes any two adjacent palette entries readable against each other.

Examples

iex> Pote.Palette.generate(7, count: 3) |> length()
3

iex> Pote.Palette.generate(7, wcag_aa: true) |> Pote.Palette.wcag_aa?()
true

wcag_aa?(palette, target \\ 4.5)

@spec wcag_aa?([rgb()], float()) :: boolean()

Returns true when consecutive colors in palette (sorted by relative luminance) have a WCAG 2.1 contrast ratio of at least target (default: 4.5, the AA threshold for normal text).

This is the property generate/2 guarantees with wcag_aa: true (see the WCAG note above).

Examples

iex> Pote.Palette.wcag_aa?([{255, 255, 255}, {0, 0, 0}])
true

iex> Pote.Palette.wcag_aa?([{255, 255, 255}, {255, 255, 255}])
false