Skip to main content

zero_tui/
theme.rs

1//! Theme — phosphor / mono / high-contrast.
2//!
3//! Color use is strict: phosphor for positive / engine output, amber
4//! for caution / pending / shadow, red for alert / blocked / loss,
5//! muted olive for dampened / pinned / disabled, cool grey for
6//! metadata. See spec §4.2.
7
8use ratatui::style::Color;
9use zero_operator_state::label::ColorHint;
10
11#[derive(Debug, Clone, Copy)]
12pub struct Theme {
13    pub primary: Color,
14    pub caution: Color,
15    pub alert: Color,
16    pub muted: Color,
17    pub metadata: Color,
18}
19
20impl Theme {
21    #[must_use]
22    pub const fn phosphor() -> Self {
23        Self {
24            primary: Color::Indexed(148),
25            caution: Color::Indexed(214),
26            alert: Color::Indexed(196),
27            muted: Color::Indexed(100),
28            metadata: Color::Indexed(244),
29        }
30    }
31
32    /// Resolve a renderer-agnostic [`ColorHint`] to a concrete
33    /// theme color. `Phosphor`→primary, `Amber`→caution, `Red`
34    /// →alert, `MutedOlive`→muted. Keeps the operator-state crate
35    /// free of ratatui while the widget stays theme-aware.
36    #[must_use]
37    pub const fn resolve_hint(&self, hint: ColorHint) -> Color {
38        match hint {
39            ColorHint::Phosphor => self.primary,
40            ColorHint::Amber => self.caution,
41            ColorHint::Red => self.alert,
42            ColorHint::MutedOlive => self.muted,
43        }
44    }
45}
46
47impl Default for Theme {
48    fn default() -> Self {
49        Self::phosphor()
50    }
51}