aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Drach <zackdrach@gmail.com>2026-05-18 04:32:34 -0700
committerGitHub <noreply@github.com>2026-05-18 14:32:34 +0300
commit29e8817e1fb417968c6a5061af547139495b2e49 (patch)
treec739bdc202e991d36ebad6743afefedfc8527231
parentfb94fff98dbcd88d9332a182dea4040c5de84fff (diff)
feat: Support 16-bit terminal themes (#146)
Add a terminal theme that inherits the terminal default background and uses the host terminal's 16-color ANSI palette for UI colors. refs #140
-rw-r--r--docs/next/CONFIGURATION.md3
-rw-r--r--docs/next/README.md2
-rw-r--r--src/app/state.rs24
-rw-r--r--src/config/theme.rs2
-rw-r--r--src/main.rs5
-rw-r--r--src/ui/panes.rs31
6 files changed, 33 insertions, 34 deletions
diff --git a/docs/next/CONFIGURATION.md b/docs/next/CONFIGURATION.md
index e988e72e..003fd102 100644
--- a/docs/next/CONFIGURATION.md
+++ b/docs/next/CONFIGURATION.md
@@ -216,7 +216,7 @@ command = "notify-send herdr 'custom command ran'"
## theme
-herdr ships with 17 built-in color themes. set one in config:
+herdr ships with 18 built-in color themes. set one in config:
```toml
[theme]
@@ -229,6 +229,7 @@ name = "tokyo-night"
|------|-------------|
| `catppuccin` | soft pastel mocha palette (default) |
| `catppuccin-latte` | light catppuccin palette |
+| `terminal` | use your terminal's 16-color ANSI palette |
| `tokyo-night` | blue-purple aesthetic |
| `tokyo-night-day` | light tokyo night palette |
| `dracula` | purple/pink/green classic |
diff --git a/docs/next/README.md b/docs/next/README.md
index 16649d6e..808cc1a8 100644
--- a/docs/next/README.md
+++ b/docs/next/README.md
@@ -137,7 +137,7 @@ not a gui window, not a web dashboard, not electron. herdr runs inside whatever
- **tabs** — first-class in the socket api and cli
- **mouse-native** — click panes/tabs/workspaces/agents, drag borders, select text to copy, right-click menus; not keyboard-only
- **notifications** — sounds and toasts for background events; tab-aware suppression
-- **17 built-in themes** — catppuccin, tokyo night, gruvbox, one, solarized, kanagawa, rosé pine, vesper, and light variants for the main palettes
+- **18 built-in themes** — catppuccin, terminal, tokyo night, gruvbox, one, solarized, kanagawa, rosé pine, vesper, and light variants for the main palettes
- **session persistence** — pane processes survive client detach; sessions restore after full restart
## agents can use herdr too
diff --git a/src/app/state.rs b/src/app/state.rs
index 1a2bbddf..72630749 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -121,6 +121,28 @@ impl Palette {
}
}
+ /// Terminal 16-color theme.
+ pub fn terminal() -> Self {
+ Self {
+ accent: Color::Blue,
+ panel_bg: Color::Reset,
+ surface0: Color::Reset,
+ surface1: Color::DarkGray,
+ surface_dim: Color::DarkGray,
+ overlay0: Color::Gray,
+ overlay1: Color::White,
+ text: Color::Reset,
+ subtext0: Color::Gray,
+ mauve: Color::Gray,
+ green: Color::Green,
+ yellow: Color::Yellow,
+ red: Color::LightRed,
+ blue: Color::Blue,
+ teal: Color::Cyan,
+ peach: Color::Yellow,
+ }
+ }
+
/// Tokyo Night — blue-purple aesthetic.
pub fn tokyo_night() -> Self {
Self {
@@ -456,6 +478,7 @@ impl Palette {
match name.to_lowercase().replace([' ', '_'], "-").as_str() {
"catppuccin" | "catppuccin-mocha" => Some(Self::catppuccin()),
"catppuccin-latte" | "latte" | "light" => Some(Self::catppuccin_latte()),
+ "terminal" => Some(Self::terminal()),
"tokyo-night" | "tokyonight" => Some(Self::tokyo_night()),
"tokyo-night-day" | "tokyo-day" | "tokyonight-day" => Some(Self::tokyo_night_day()),
"dracula" => Some(Self::dracula()),
@@ -615,6 +638,7 @@ impl SettingsSection {
pub const THEME_NAMES: &[&str] = &[
"catppuccin",
"catppuccin-latte",
+ "terminal",
"tokyo-night",
"tokyo-night-day",
"dracula",
diff --git a/src/config/theme.rs b/src/config/theme.rs
index 9d641862..87722b6e 100644
--- a/src/config/theme.rs
+++ b/src/config/theme.rs
@@ -5,7 +5,7 @@ use tracing::warn;
///
/// ```toml
/// [theme]
-/// name = "tokyo-night" # built-in: catppuccin, tokyo-night, dracula, nord, etc.
+/// name = "tokyo-night" # built-in: catppuccin, terminal, dracula, nord, etc.
///
/// [theme.custom] # override individual tokens on top of the base
/// accent = "#f5c2e7"
diff --git a/src/main.rs b/src/main.rs
index 79a5d544..c1b0acd3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -61,8 +61,9 @@ const DEFAULT_CONFIG: &str = r##"# herdr configuration
# onboarding = true
[theme]
-# Built-in themes: catppuccin, tokyo-night, dracula, nord, gruvbox,
-# one-dark, solarized, kanagawa, rose-pine, vesper
+# Built-in themes: catppuccin, terminal, tokyo-night, dracula, nord,
+# gruvbox, one-dark, solarized, kanagawa, rose-pine,
+# vesper
# name = "catppuccin"
# Override individual color tokens on top of the base theme.
diff --git a/src/ui/panes.rs b/src/ui/panes.rs
index 971901bd..d9108575 100644
--- a/src/ui/panes.rs
+++ b/src/ui/panes.rs
@@ -1,6 +1,6 @@
use ratatui::{
layout::Rect,
- style::{Color, Modifier, Style},
+ style::{Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, Paragraph},
Frame,
@@ -293,10 +293,7 @@ pub(super) fn render_panes(app: &AppState, frame: &mut Frame, area: Rect) {
for y in inner.y..inner.y + inner.height {
for x in inner.x..inner.x + inner.width {
let cell = &mut buf[(x, y)];
- let style = cell.style();
- let fg = style.fg.unwrap_or(Color::White);
- let dimmed_fg = dim_color(fg);
- cell.set_style(style.fg(dimmed_fg));
+ cell.set_style(cell.style().add_modifier(Modifier::DIM));
}
}
}
@@ -313,30 +310,6 @@ pub(super) fn render_panes(app: &AppState, frame: &mut Frame, area: Rect) {
}
}
-/// Render selection highlight for a pane by inverting fg/bg colors.
-/// Reduce a color's brightness by blending it toward black.
-fn dim_color(color: Color) -> Color {
- match color {
- Color::Rgb(r, g, b) => Color::Rgb(r / 3, g / 3, b / 3),
- Color::White => Color::DarkGray,
- Color::Gray => Color::DarkGray,
- Color::DarkGray => Color::Rgb(30, 30, 30),
- Color::Red => Color::Rgb(60, 0, 0),
- Color::Green => Color::Rgb(0, 60, 0),
- Color::Yellow => Color::Rgb(60, 60, 0),
- Color::Blue => Color::Rgb(0, 0, 60),
- Color::Magenta => Color::Rgb(60, 0, 60),
- Color::Cyan => Color::Rgb(0, 60, 60),
- Color::LightRed => Color::Rgb(80, 30, 30),
- Color::LightGreen => Color::Rgb(30, 80, 30),
- Color::LightYellow => Color::Rgb(80, 80, 30),
- Color::LightBlue => Color::Rgb(30, 30, 80),
- Color::LightMagenta => Color::Rgb(80, 30, 80),
- Color::LightCyan => Color::Rgb(30, 80, 80),
- _ => Color::DarkGray,
- }
-}
-
fn render_selection_highlight(
selection: &Option<crate::selection::Selection>,
frame: &mut Frame,