Raxol. UI. ColorIntent
(Raxol v2.6.1)
View Source
A color intent — (hue, chroma, prominence), not a literal color — that
rides the same fg:/bg: slots literal colors occupy in a style map or a
cell tuple. Resolved to bytes exactly once, at the render choke point
(Raxol.UI.ColorResolver), against the ground that is actually known at
that point (terminal background, capability tier, region/focus state).
See docs/core/RENDERING.md's "Region prominence" section for the
resolution model. This module is the struct only — no resolution
logic lives here; that stays in Raxol.UI.ColorResolver so this module has
no dependency on Raxol.UI.Theming.Salience's solver internals.
Fields
:h- hue in degrees (0..360), ornilfor an achromatic intent.:c- chroma (0.0= neutral / no color, i.e. achromatic).:tier- aRaxol.UI.Theming.Salience.tier/0(:alarm,:recede,:differentiate,:baseline,:anchor), ornil.:prominence- an explicit scalar0.0..1.0(component-ownp), ornil.:role- a semantic role atom for ANSI-16 slot pinning (e.g.:error,:accent), consumed byRaxol.UI.Theming.Ansi16Salience. Not consulted by the truecolor resolution path.:floor- the legibility floor class::none(pure fade, the default),:ui(Raxol.UI.Harness.Prominence.floor_ratio/0,3.0),:text(WCAG AA normal text,4.5), or{:ratio, float()}for an explicit override.
tier and prominence are two entries to the same axis — a component
states either ("I am :recede chrome") or ("I am this row at 0.6").
When tier is set, prominence (if also set) is the component's own p
on the fade line from that tier's full-strength target. When tier is
unset, prominence fades from the baseline-tier target. A bare
%ColorIntent{} therefore resolves as a baseline-tier neutral at full
prominence.
The {:fixed, color} escape hatch
{:fixed, color} is not a struct — it is a plain 2-tuple wrapper
convention recognized directly by Raxol.UI.ColorResolver. It exempts
color (a literal) from ALL resolution and region fading: the resolver
unwraps it to the literal, byte-identical, unconditionally. This is the "I
really mean these exact bytes" hatch (e.g. syntax-highlight themes under
screenshot goldens). It composes with nothing — a fixed color glares
through region dims and modal fades by design; that is what "fixed" means.
# a literal, participates in region fading (once regions land)
fg: "#c1712c"
# the same literal, exempt from all fading forever
fg: {:fixed, "#c1712c"}Backward compatibility
Literal colors (hex strings, {r, g, b} tuples, ANSI atoms, 256-palette
integers) remain valid in every slot a ColorIntent can occupy — the cell
tuple already carries heterogeneous terms, so intents ride the existing
slots with no shape change. Raxol.UI.ColorResolver passes literals
through unchanged: an app that never triggers an attr-less fg/bg default,
never focuses a region, and never opens an overlay renders
byte-identically to no-resolver, by construction.
Summary
Functions
Wraps color in the {:fixed, color} escape-hatch convention -- exempts
it from all resolution/fading in Raxol.UI.ColorResolver. See moduledoc.
True if term is the {:fixed, _} escape-hatch wrapper.
Types
@type floor_class() :: :none | :ui | :text | {:ratio, float()}
@type t() :: %Raxol.UI.ColorIntent{ c: float(), floor: floor_class(), h: (0..360 | float()) | nil, prominence: float() | nil, role: atom() | nil, tier: Raxol.UI.Theming.Salience.tier() | nil }
Functions
Wraps color in the {:fixed, color} escape-hatch convention -- exempts
it from all resolution/fading in Raxol.UI.ColorResolver. See moduledoc.
True if term is the {:fixed, _} escape-hatch wrapper.