Raxol.UI.Theming.Palette (Raxol v2.6.1)

View Source

Single canonical home for Raxol's palette PRIMITIVES: the color VALUES that theming, terminal rendering, and UI components pull from -- as opposed to the color-manipulation ALGORITHMS (HSL conversion, harmony, gradients, accessibility suggestion, contrast calculation), which stay where they are (Raxol.Style.Colors.*, Raxol.UI.Theming.Salience).

Why this module exists

A full-codebase audit (docs/proposals/palette-inventory.md) found the same conceptual color defined independently, with DIFFERENT values, in many places -- most strikingly at least four conflicting "the standard ANSI 16 colors" conventions (6+ literal copies) and at least five unrelated "the default semantic theme" token sets. This module does not silently pick a winner (that would change runtime behaviour for whichever call sites are later pointed at it) -- it PRESERVES every existing value under a clearly attributed name, so future migration work can make an informed choice call site by call site. See the inventory doc for the full duplicate/conflict catalogue, file:line citations, and a ranked list of the call sites most worth migrating.

This module is additive only: nothing in the tree calls into it yet. Existing modules keep their own copies until migrated one at a time.

Sections

  • Named colors -- CSS-ish web color names, merged from the two sources that agreed with each other byte-for-byte.
  • WCAG-safe fallbacks -- black/white, duplicated ~15x verbatim elsewhere.
  • The near-black surface convention -- #1E1E1E, duplicated 3x elsewhere.
  • ANSI 16 basic palette -- 4 documented, mutually conflicting variants.
  • ANSI 256 cube / grayscale -- generation constants; 2 conflicting cube formulas, 1 uncontested grayscale ramp.
  • Platform terminal palettes -- linux/mac/windows, uncontested.
  • Semantic default-theme families -- 7 conflicting token sets, each preserved exactly under the name of the module it came from.
  • Salience / H-K tier anchors -- delegates to the live source (Raxol.UI.Theming.SalienceTheme) rather than copying literals, so it can never drift. The darcula-family reference bake is a byte-exact test fixture in test/raxol/ui/theming/salience_test.exs and is deliberately NOT reproduced here -- it is generated by Salience.solve/3's floating-point math, not stored as a literal.
  • Effect accent palettes -- BorderBeam's 7 variants (ANSI + CSS flavors).

Non-goals

This module does not implement color conversion, blending, contrast calculation, or theme resolution -- see Raxol.Style.Colors.Color, Raxol.Style.Colors.Formats, Raxol.Style.Colors.Utilities, Raxol.UI.Theming.Theme, and Raxol.Core.Theming.ThemeRegistry for those. It also does not attempt to catalog the 10 named community themes already well-organized in Raxol.Core.Theming.ThemeRegistry (dracula, nord, monokai, gruvbox, solarized, tokyo_night, one_dark, catppuccin, synthwave84) -- that module already serves that role; duplicating it here would just add a fifth copy to a category that already has too many.

Summary

Functions

Returns one of the 4 conflicting ANSI 16-color conventions found in the codebase, as a 16-element list of {r, g, b} tuples in ansi_16_names/0 order. Defaults to :xterm, the convention with the most independent copies. See inventory §5.1 for the full comparison table.

Like ansi_16/1, but keyed by color name instead of positional index.

The 16 ANSI color names in SGR 30-37/90-97 order, shared by every ansi_16/1 variant.

The known ANSI 16-color convention variant names, for iteration/tests.

Generates the 216-entry ANSI 256-color cube (indices 16-231) under the given step formula. Returns [{index, {r, g, b}}].

Generates the 24-entry ANSI 256-color grayscale ramp (indices 232-255). Returns [{index, {level, level, level}}]. Unlike the cube, every source in the codebase agrees on this formula -- there is only one variant.

The WCAG-safe black fallback, as reused independently 15+ times across the codebase.

The BorderBeam effect's muted inner-glow accent color for a variant.

The BorderBeam effect's ANSI-atom accent palette for a variant (terminal rendering path).

The BorderBeam effect's CSS hex accent palette for a variant (LiveView/web rendering path).

Looks up one named color. Returns nil for an unknown name.

All named colors as a name => hex map.

The near-black surface value shared (independently) by three unrelated call sites.

Same value as near_black_surface/0, as the RGB tuple form used by theme_integration.ex.

Returns the platform-flavored 16-color terminal palette as [{index, {r, g, b}}], matching each OS's real terminal default colors (as opposed to any of the ansi_16/1 conventions, which are all synthetic/idealized).

RGB-tuple-flavored sibling of semantic_defaults/1 for the one family stored that way.

The semantic (name, hue, chroma, tier) seed table the salience/H-K color system solves against a ground lightness. Delegates to Raxol.UI.Theming.SalienceTheme.seeds/0 (not copied) so this can never drift from the live source.

The reference near-black ground OKLCH lightness the salience tier deltas were derived against. Delegates to Raxol.UI.Theming.Salience.reference_ground/0 (not copied).

The known semantic-default family names, for iteration/tests.

Returns one of the 7 independently-defined "default semantic theme" token sets found in the codebase, exactly as defined at its source. Token keys and even the set of tokens differ between families by design -- these are not meant to be interchangeable, only auditable side by side.

The WCAG-safe white fallback, as reused independently 15+ times across the codebase.

Types

ansi_16_variant()

@type ansi_16_variant() :: :xterm | :vga | :gnome_terminal | :pure_pastel

ansi_256_cube_formula()

@type ansi_256_cube_formula() :: :xterm_accurate | :naive_linear

border_beam_variant()

@type border_beam_variant() ::
  :colorful | :mono | :ocean | :sunset | :electric | :neon | :matrix

hex()

@type hex() :: String.t()

platform()

@type platform() :: :linux | :mac | :windows

rgb()

@type rgb() :: {0..255, 0..255, 0..255}

semantic_family()

@type semantic_family() ::
  :dracula_ide
  | :dracula_ide_dark
  | :brand_light
  | :material_dark
  | :material_high_contrast
  | :web_tailwind
  | :web_bootstrap
  | :renderer_defaults

Functions

ansi_16(variant \\ :xterm)

@spec ansi_16(ansi_16_variant()) :: [rgb()]

Returns one of the 4 conflicting ANSI 16-color conventions found in the codebase, as a 16-element list of {r, g, b} tuples in ansi_16_names/0 order. Defaults to :xterm, the convention with the most independent copies. See inventory §5.1 for the full comparison table.

ansi_16_named(variant \\ :xterm)

@spec ansi_16_named(ansi_16_variant()) :: %{required(atom()) => rgb()}

Like ansi_16/1, but keyed by color name instead of positional index.

ansi_16_names()

@spec ansi_16_names() :: [atom()]

The 16 ANSI color names in SGR 30-37/90-97 order, shared by every ansi_16/1 variant.

ansi_16_variants()

@spec ansi_16_variants() :: [ansi_16_variant()]

The known ANSI 16-color convention variant names, for iteration/tests.

ansi_256_cube(formula)

@spec ansi_256_cube(ansi_256_cube_formula()) :: [{16..231, rgb()}]

Generates the 216-entry ANSI 256-color cube (indices 16-231) under the given step formula. Returns [{index, {r, g, b}}].

ansi_256_grayscale()

@spec ansi_256_grayscale() :: [{232..255, rgb()}]

Generates the 24-entry ANSI 256-color grayscale ramp (indices 232-255). Returns [{index, {level, level, level}}]. Unlike the cube, every source in the codebase agrees on this formula -- there is only one variant.

black()

@spec black() :: hex()

The WCAG-safe black fallback, as reused independently 15+ times across the codebase.

effect_accent(atom1, atom2, variant)

@spec effect_accent(:border_beam, :glow | :bloom, border_beam_variant()) :: atom()

The BorderBeam effect's muted inner-glow accent color for a variant.

effect_palette(atom, variant)

@spec effect_palette(:border_beam, border_beam_variant()) :: [atom()]

The BorderBeam effect's ANSI-atom accent palette for a variant (terminal rendering path).

effect_palette_css(atom, variant)

@spec effect_palette_css(:border_beam, border_beam_variant()) :: [hex()]

The BorderBeam effect's CSS hex accent palette for a variant (LiveView/web rendering path).

named_color(name)

@spec named_color(atom()) :: hex() | nil

Looks up one named color. Returns nil for an unknown name.

named_colors()

@spec named_colors() :: %{required(atom()) => hex()}

All named colors as a name => hex map.

near_black_surface()

@spec near_black_surface() :: hex()

The near-black surface value shared (independently) by three unrelated call sites.

near_black_surface_rgb()

@spec near_black_surface_rgb() :: rgb()

Same value as near_black_surface/0, as the RGB tuple form used by theme_integration.ex.

platform_palette(atom)

@spec platform_palette(platform()) :: [{0..15, rgb()}]

Returns the platform-flavored 16-color terminal palette as [{index, {r, g, b}}], matching each OS's real terminal default colors (as opposed to any of the ansi_16/1 conventions, which are all synthetic/idealized).

renderer_defaults()

@spec renderer_defaults() :: %{required(atom()) => rgb()}

RGB-tuple-flavored sibling of semantic_defaults/1 for the one family stored that way.

salience_darcula_seeds()

@spec salience_darcula_seeds() :: [map()]

The semantic (name, hue, chroma, tier) seed table the salience/H-K color system solves against a ground lightness. Delegates to Raxol.UI.Theming.SalienceTheme.seeds/0 (not copied) so this can never drift from the live source.

salience_reference_ground()

@spec salience_reference_ground() :: float()

The reference near-black ground OKLCH lightness the salience tier deltas were derived against. Delegates to Raxol.UI.Theming.Salience.reference_ground/0 (not copied).

semantic_default_families()

@spec semantic_default_families() :: [semantic_family()]

The known semantic-default family names, for iteration/tests.

semantic_defaults(atom)

@spec semantic_defaults(semantic_family()) :: %{required(atom()) => hex()}

Returns one of the 7 independently-defined "default semantic theme" token sets found in the codebase, exactly as defined at its source. Token keys and even the set of tokens differ between families by design -- these are not meant to be interchangeable, only auditable side by side.

white()

@spec white() :: hex()

The WCAG-safe white fallback, as reused independently 15+ times across the codebase.