Unified residual theming (two-mode per-app) #3

Open
opened 2026-07-19 02:29:52 +00:00 by agent · 0 comments
Member

Plan: Unified residual theming + color-set unification

Goal (from user)

All residual UIs support theming via two modes, chosen per app:

  1. Residual unified theme — opt-in (unified_theme = false by default per app). When on, the app reads the shared ~/.config/residual/theme.toml palette.
  2. Inherited terminal color theme — the default (except res-console). App uses the terminal's own fg/bg; no OSC palette remap, no hardcoded amber.

All apps may use the amber unified theme, but by default they don't — except res-console, which keeps its current amber-by-default behavior.

res-theme is the editor for the unified theme config. The 4 non-palette overlay shade colors are unified into the 5 approved palette colors. res-demo and res-theme are added to the docs.

Decisions (confirmed with user)

  • Opt-in: per-app key in <app>.toml (unified_theme = false).
  • Off behavior: pure inherit (no OSC) — terminal's own colors show through.
  • Overlay colors: use only the 5 palette colors (drop the shade variants).
  • res-console is the exception: amber-by-default (keeps current behavior), opt-OUT via unified_theme = false → pure inherit.

Current state (verified)

  • theme.Config = 5 colors + TransparentBg; loaded from shared theme.toml via theme.LoadConfig().
  • res-console: theme.InitTheme(theme.LoadConfig()) + ApplyConsolePalette (OSC 10/11).
  • res-calc, res-sheets: theme.InitTheme(theme.DefaultConfig()) — amber, but ignores user theme.toml.
  • res-edit, res-code: intentionally neutral (ANSI indices only, no InitTheme) — already inherit-by-default.
  • res-theme: saves to ~/.config/residual/theme.toml (doc comment wrongly says /tmp/res-theme.toml).
  • Overlay shades appear only in core/lib/tui/theme/theme.go (#080600, #120f00, #aa8800, #3a2a00).

Implementation notes (as built)

  • Added theme.InitInherit() and theme.InitUnified() (replacing old InitTheme 2-arg call sites). InitUnified() reads shared theme.toml; InitInherit() sets neutral terminal-inherit styles.
  • Added theme.UnifiedEnabled(fileName string) bool helper (uses config.LoadOne) for apps without their own config struct. Used by res-calc/res-sheets.
  • res-edit/res-code got UnifiedTheme bool key in their config structs and call InitUnify/InitInherit. edit.LoadConfig/code.LoadConfig exported.
  • res-console flipped to amber-by-default: unified_theme = trueInitInherit(); default → InitTheme + palette.
  • Overlay shade hexes removed; only the 5 palette colors remain in theme.go.

Steps

  1. Theme package: add inherit mode + unify overlay colors (core/lib/tui/theme/theme.go + config.go).
  2. Per-app unified_theme key (default false) in each app config struct.
  3. App startup wiring (res-console exception amber-by-default; res-calc/res-sheets/res-edit/res-code conditional; res-demo demos unified).
  4. res-theme — fix stale doc comment (/tmp/res-theme.toml~/.config/residual/theme.toml).
  5. Docs — AGENTS.md §3 (add res-demo/res-theme as dev tools), docs/README.md, docs/design/aesthetic.md (two modes), per-app docs, extra/residual-overview.md.
  6. Verification — cd core && go build ./... && CGO_ENABLED=1 go test ./... PASS; cd extra && go build ./... && go test ./... PASS; grep no non-palette hex in core/lib/tui/theme.

Status: all code + doc steps complete; builds/tests green. Plan ready to close after commit/push.

Behavior changes to flag

  • res-calc/res-sheets become neutral-by-default (inherited terminal theme) instead of always-amber. Users who want amber set unified_theme = true.
  • res-console keeps amber-by-default (exception); set unified_theme = true to get pure inherit.

Risks

  • res-calc/res-sheets currently have no config file — adding one is new surface; keep minimal (just unified_theme).
  • InitInherit() must not break res-edit/res-code neutral rendering — mirror their ANSI-index approach.
# Plan: Unified residual theming + color-set unification ## Goal (from user) All residual UIs support theming via **two modes**, chosen per app: 1. **Residual unified theme** — opt-in (`unified_theme = false` by default per app). When on, the app reads the shared `~/.config/residual/theme.toml` palette. 2. **Inherited terminal color theme** — the default (except `res-console`). App uses the terminal's own fg/bg; no OSC palette remap, no hardcoded amber. All apps *may* use the amber unified theme, but by default they don't — **except `res-console`**, which keeps its current amber-by-default behavior. `res-theme` is the editor for the unified theme config. The 4 non-palette overlay shade colors are unified into the 5 approved palette colors. `res-demo` and `res-theme` are added to the docs. ## Decisions (confirmed with user) - Opt-in: **per-app key in `<app>.toml`** (`unified_theme = false`). - Off behavior: **pure inherit (no OSC)** — terminal's own colors show through. - Overlay colors: **use only the 5 palette colors** (drop the shade variants). - `res-console` is the exception: amber-by-default (keeps current behavior), opt-OUT via `unified_theme = false` → pure inherit. ## Current state (verified) - `theme.Config` = 5 colors + `TransparentBg`; loaded from shared `theme.toml` via `theme.LoadConfig()`. - `res-console`: `theme.InitTheme(theme.LoadConfig())` + `ApplyConsolePalette` (OSC 10/11). - `res-calc`, `res-sheets`: `theme.InitTheme(theme.DefaultConfig())` — amber, but **ignores** user `theme.toml`. - `res-edit`, `res-code`: intentionally neutral (ANSI indices only, no `InitTheme`) — already inherit-by-default. - `res-theme`: saves to `~/.config/residual/theme.toml` (doc comment wrongly says `/tmp/res-theme.toml`). - Overlay shades appear only in `core/lib/tui/theme/theme.go` (`#080600`, `#120f00`, `#aa8800`, `#3a2a00`). ## Implementation notes (as built) - Added `theme.InitInherit()` and `theme.InitUnified()` (replacing old `InitTheme` 2-arg call sites). `InitUnified()` reads shared `theme.toml`; `InitInherit()` sets neutral terminal-inherit styles. - Added `theme.UnifiedEnabled(fileName string) bool` helper (uses `config.LoadOne`) for apps without their own config struct. Used by `res-calc`/`res-sheets`. - `res-edit`/`res-code` got `UnifiedTheme bool` key in their config structs and call `InitUnify`/`InitInherit`. `edit.LoadConfig`/`code.LoadConfig` exported. - `res-console` flipped to amber-by-default: `unified_theme = true` → `InitInherit()`; default → `InitTheme` + palette. - Overlay shade hexes removed; only the 5 palette colors remain in theme.go. ## Steps 1. Theme package: add inherit mode + unify overlay colors (`core/lib/tui/theme/theme.go` + `config.go`). 2. Per-app `unified_theme` key (default `false`) in each app config struct. 3. App startup wiring (res-console exception amber-by-default; res-calc/res-sheets/res-edit/res-code conditional; res-demo demos unified). 4. `res-theme` — fix stale doc comment (`/tmp/res-theme.toml` → `~/.config/residual/theme.toml`). 5. Docs — AGENTS.md §3 (add res-demo/res-theme as dev tools), docs/README.md, docs/design/aesthetic.md (two modes), per-app docs, extra/residual-overview.md. 6. Verification — `cd core && go build ./... && CGO_ENABLED=1 go test ./...` PASS; `cd extra && go build ./... && go test ./...` PASS; grep no non-palette hex in `core/lib/tui/theme`. **Status: all code + doc steps complete; builds/tests green. Plan ready to close after commit/push.** ## Behavior changes to flag - **`res-calc`/`res-sheets` become neutral-by-default** (inherited terminal theme) instead of always-amber. Users who want amber set `unified_theme = true`. - **`res-console` keeps amber-by-default** (exception); set `unified_theme = true` to get pure inherit. ## Risks - `res-calc`/`res-sheets` currently have no config file — adding one is new surface; keep minimal (just `unified_theme`). - `InitInherit()` must not break `res-edit`/`res-code` neutral rendering — mirror their ANSI-index approach.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
residual/.agent#3
No description provided.