132 lines
6.5 KiB
Markdown
132 lines
6.5 KiB
Markdown
# Red Bear OS — Default TUI Skin Palette
|
|
|
|
`redbear-tui-theme` is the **single source of truth** for the Red Bear brand colours used by every TUI application on Red Bear OS:
|
|
|
|
- `tlc` (file manager)
|
|
- `cub` (package manager)
|
|
- `redbear-info` (system dashboard)
|
|
- `redbear-netctl-console` (network control)
|
|
- `redbear-wifictl`, `redbear-btctl` (device control)
|
|
- `redbear-mtr`, `redbear-traceroute`, `redbear-nmap`, `redbear-hwutils` (diagnostics)
|
|
- any future TUI app
|
|
|
|
The palette is pure-Rust (no `ratatui` dep at the core), builds offline, and ships with both dark and light presets.
|
|
|
|
## Quick start
|
|
|
|
```toml
|
|
# Cargo.toml
|
|
[dependencies]
|
|
redbear-tui-theme = { path = "../../../tui/redbear-tui-theme/source" }
|
|
```
|
|
|
|
```rust
|
|
use redbear_tui_theme::{REDBEAR_DARK, Theme};
|
|
|
|
// Render a selection row.
|
|
let bg = REDBEAR_DARK.selection_bg; // #3652A0
|
|
let fg = REDBEAR_DARK.selection_fg; // #F4F4F4
|
|
|
|
// Or pick a theme from the environment (REDBEAR_TUI_THEME or COLORFGBG).
|
|
let theme = Theme::from_env();
|
|
```
|
|
|
|
## What's in the palette
|
|
|
|
The `Theme` struct has **33 slots** organized into six families:
|
|
|
|
| Family | Slots | Purpose |
|
|
|---|---|---|
|
|
| Surface | `background`, `surface`, `overlay_bg`, `title_bg`, `status_bg`, `gauge_bg` | 6 slots; 3-tier raised surface; chrome bars |
|
|
| Text | `text`, `muted`, `dim`, `border` | 4 slots; body text + de-emphasis |
|
|
| Accent | `accent`, `accent_soft`, `title_accent`, `pink` | 4 slots; brand red + secondary accents |
|
|
| Semantic | `success`, `warning`, `error`, `info` | 4 slots; status colours (must pair with glyphs) |
|
|
| File types | `directory`, `executable`, `symlink`, `device`, `device_warn`, `hidden` | 6 slots; tlc file-type colours |
|
|
| Selection | `selection_{bg,fg}`, `cursor_{bg,fg}`, `marked_{bg,fg}`, `buttonbar_{bg,fg}` | 8 slots; tlc selection/cursor/marked/buttonbar |
|
|
|
|
All 33 slots are sourced from the shared `Theme` — no consumer hard-codes brand hex values.
|
|
|
|
## Brand red
|
|
|
|
`#B52430` is the Red Bear OS brand red. It is **identical** in both dark and light themes. This matches the convention of macOS, KDE, GNOME, and Windows: the brand stays constant; only the background flips.
|
|
|
|
## WCAG 2.1 AA contrast (verified)
|
|
|
|
| Pair | Dark ratio | Light ratio | Pass |
|
|
|---|---|---|---|
|
|
| `text` on `background` | 17.51 | 15.86 | AA-body ✓ |
|
|
| `text` on `accent` | 5.86 | 6.44 | AA-body ✓ |
|
|
| `muted` on `background` | 8.33 | 5.82 | AA-body ✓ |
|
|
| `border` on `background` | 4.53 | 2.27 | AA-body (dark) / AA-large (light) |
|
|
| `dim` on `background` | 2.91 | 3.81 | **Intentionally below AA-body** (de-emphasis) |
|
|
|
|
The only intentional AA-body failure is `dim`/`hidden`. By design: de-emphasis is the function. Apps must not use `dim` for body text.
|
|
|
|
## Color-blindness
|
|
|
|
- `success` vs `error`: distinguishable for all three common deficiencies.
|
|
- `warning` vs `error`: **confusable** for protanopia and deuteranopia. **Mitigation**: every warning must be accompanied by a `⚠` glyph prefix, every error by `✗`.
|
|
- `info` vs `success`: confusable for tritanopia. **Mitigation**: keep `info` and `success` on separate lines in status bars.
|
|
- `pink` is for highlights (favorites, active link). **Mitigation**: when used, also prepend `★` (U+2605).
|
|
|
|
Apps render these as styles with `Modifier::BOLD` on the semantic colours; the styles module (planned v0.2) will provide ready-made `success_style()`, `warning_style()`, etc. as one-liners.
|
|
|
|
## 256-color + 16-color fallback
|
|
|
|
For terminals that don't support truecolor, the `fallback` module provides:
|
|
|
|
- `fallback_256(rgb: Rgb) -> u8` — closest XTerm-256 index (0..=255)
|
|
- `fallback_16_name(rgb: Rgb) -> &'static str` — closest ANSI-16 name
|
|
|
|
`fallback_256` uses a weighted Euclidean distance in sRGB space (small luminance penalty to keep the returned colour visually close). Verified mappings:
|
|
|
|
| Slot | Truecolor | 256-idx | 16-name |
|
|
|---|---|---|---|
|
|
| `background` | `#0E0E12` | 233 | Black |
|
|
| `text` | `#F4F4F4` | 255 | Bright White |
|
|
| `accent` | `#B52430` | 125 or 9 | Bright Red |
|
|
| `success` | `#74C793` | 114 | Bright Black |
|
|
| `warning` | `#FFBF57` | 215 | Bright Yellow |
|
|
|
|
## Migrating an existing TUI app
|
|
|
|
1. Add the dep to `Cargo.toml`:
|
|
```toml
|
|
redbear-tui-theme = { path = "../../../tui/redbear-tui-theme/source" }
|
|
```
|
|
2. Replace local `Color::Rgb(r, g, b)` constants with `REDBEAR_DARK.<slot>` (or `Rgb(r,g,b)` if you need a custom value).
|
|
3. Convert to your TUI lib's colour type: `ratatui::style::Color::Rgb(t.bg.0, t.bg.1, t.bg.2)`.
|
|
4. Replace any local `Theme` struct with `pub use redbear_tui_theme::Theme;`.
|
|
5. Add `redbear-tui-theme` to the cookbook's cascade list in `local/scripts/rebuild-cascade.sh`.
|
|
|
|
## Build
|
|
|
|
The crate has zero required dependencies. It builds offline:
|
|
|
|
```bash
|
|
cd local/recipes/tui/redbear-tui-theme/source
|
|
cargo build --release
|
|
cargo test # 11 unit tests (palette + fallback) + 1 doc test
|
|
```
|
|
|
|
The recipe lives at `local/recipes/tui/redbear-tui-theme/recipe.toml` and
|
|
stages the resulting `libredbear_tui_theme.rlib` into
|
|
`${COOKBOOK_STAGE}/usr/lib/` so the cookbook's repo artifact check passes.
|
|
The recipe is symlinked into the cookbook search path at
|
|
`recipes/tui/redbear-tui-theme` (per `local/AGENTS.md` "Local recipe priority
|
|
vs upstream WIP"). Downstream TUI apps depend on the crate via a Cargo
|
|
`path` dependency — they do **not** install it as a binary.
|
|
|
|
## Downstream consumers (as of 2026-06-13)
|
|
|
|
| App | Status | Notes |
|
|
|---|---|---|
|
|
| `tlc` | ✅ wired | `tlc/source/Cargo.toml` adds `redbear-tui-theme = { path = "../../../tui/redbear-tui-theme/source" }`. The 22-field `Theme` struct in `src/terminal/color.rs` is preserved (TOML skin deserializer still works); `DEFAULT_THEME` and `LIGHT_THEME` are now built from the shared `REDBEAR_DARK`/`REDBEAR_LIGHT` via a const `as_color(rgb)` adapter. |
|
|
| `cub` | ✅ wired | `local/recipes/system/cub/source/cub/src/tui/theme.rs` is now a 33-field `RedBearTheme` newtype constructed from `redbear_tui_theme::REDBEAR_DARK` via a const `as_color(rgb)` adapter. The 19 `*_style()` methods are preserved as inherent methods; all 33 slots are sourced from the shared palette. 2 new tests verify byte-identical brand red and 19 non-empty styles. |
|
|
| `redbear-info` | 🚧 TODO | `local/recipes/system/redbear-info/source/src/tui.rs` uses the legacy ANSI-16 palette (`Color::Red`, `Color::DarkGray`, etc.). Migration is non-trivial because the file uses semantic colors only, not slot names. |
|
|
| `redbear-netctl-console` | 🚧 TODO | `local/recipes/system/redbear-netctl-console/source/src/ui.rs` uses the legacy ANSI-16 palette. Same migration story as `redbear-info`. |
|
|
|
|
## License
|
|
|
|
MIT — same as Red Bear OS.
|