# TUI Overhaul — Design **Status:** Approved, pending implementation plan **Date:** 2026-07-14 **Scope:** `src/view/`, `src/controller/` (render/interaction layer only) ## Context The TUI went through a "modern design" pass the day before this spec (commit `3f5f27c`: dark palette, neon accents, message cards, segmented status bar). The request for this overhaul covers all three axes at once: aesthetics, UX/navigation, and layout paradigm — not a re-skin of the existing structure. ## Goals - Replace the current 3-zone layout (chat / input / status, everything else as a full-block centered modal) with a **Multi-Pane Dashboard**: chat stays central, a persistent right sidebar surfaces live status that today requires opening a modal. - Replace the current "neon dusk" palette with a **Tokyo Night** palette. - Replace the current per-message card rendering (badge pill, left accent bar, blank-line gaps) with a **tight inline log** format. - Drop decorative emoji from overlay titles in favor of plain colored text — the accent border/text color already carries identity. - Restyle (not restructure) the overlays that stay modal. ## Non-goals - No `AppStateRest` shape changes, no new `Action` variants, no controller/state-mutation changes. This is a view-layer repaint; `theme.rs` constants are the only "API" the rest of the app depends on, and their names don't change, only their values. - No new keybindings and no mouse support. Sidebar widgets are read-only/glanceable — none of the three (Workflow, Todo, Usage) are interactive today, so they don't need focus or selection state in their new form either. - No overlay is removed. Workflow/Todo/Usage keep their existing overlay trigger as an "expand" view (see below); the other 13 overlays are untouched functionally. - No automated visual/snapshot tests are being introduced (none exist today for `view/`/`controller/`; see Testing below). ## Layout architecture ``` ┌───────────────────────────────────────────┬──────────────┐ │ │ WORKFLOW │ │ Chat transcript (tight inline log) │ ▶ Node-0-1 │ │ │ ✓ Node-0-2 │ │ ├──────────────┤ │ │ TASKS │ │ │ ☐ Fix bug │ │ │ ☑ Repro │ │ ├──────────────┤ │ │ USAGE │ │ │ 12.3k tok │ ├─────────────────────────────────────────────┴──────────────┤ │ ❯ input bar │ ├───────────────────────────────────────────────────────────┤ │ status bar │ └───────────────────────────────────────────────────────────┘ ``` - The sidebar is a fixed-width column (generalizing the existing `show_todo` two-column split in `view/mod.rs::draw`) holding three stacked widgets, in this order: **Workflow**, **Tasks**, **Usage**. - **Responsive collapse**: below a width threshold (~90 cols — extending the existing `show_todo && area.width > 60` precedent, widened because the new sidebar holds three stacked widgets instead of one), the sidebar doesn't render and chat takes full width. No manual toggle key — purely width-driven, matching current behavior. - Each sidebar widget truncates its content to what fits and shows a `+N more, press to expand` hint (same pattern `Rewind` already uses for `"... and N more messages"`) when there's more than fits — that's what the kept overlay is for. ### Workflow / Todo / Usage: sidebar glance + overlay expand These three overlays are **not removed**. Their existing trigger (same keys/commands as today) still opens the full-screen version — now serving as the "expand" view for when the sidebar column is too narrow to show everything (many hive-mind nodes, a long task list). The sidebar widget and the overlay both read the same state (`workflow_engine`, `misc.todo_content`, `session_runtime.usage` + `session_runtime.session_start`); the sidebar version is a new compact rendering, factored out so both call sites share it where the content is identical (e.g. per-agent card formatting in `workflow.rs`). ### Remaining 13 overlays: restyled modals, unchanged behavior `Help, Settings, Bash, QuitConfirm, KeyInput, Editor, Effort, Mcp, Rewind, Learning, Loading, ModelSelector, ClearConfirm` keep their current centered-modal mechanic and content logic exactly as-is. Only their chrome changes: new palette values (same semantic-color-per-overlay mapping as today — e.g. `QuitConfirm` stays `ERROR`, `Settings` stays `PRIMARY`), and emoji dropped from their title strings. ## Visual language ### Palette — Tokyo Night Values only; `Theme` constant names in `view/theme.rs` are unchanged, so every call site across `view/*` keeps working without edits beyond the const definitions themselves. | Constant | Value | Constant | Value | |---|---|---|---| | `BG` | `#1a1b26` | `ROLE_USER` | `#9ece6a` | | `SURFACE` | `#1f2335` | `ROLE_ASSISTANT` | `#7aa2f7` | | `SURFACE_ELEVATED` | `#292e42` | `ROLE_SYSTEM` | `#7dcfff` | | `TEXT` | `#c0caf5` | `ROLE_TOOL` | `#e0af68` | | `TEXT_MUTED` | `#a9b1d6` | `PRIMARY` | `#7aa2f7` | | `TEXT_DIM` | `#565f89` | `SUCCESS` | `#9ece6a` | | `BORDER` | `#3b4261` | `WARNING` | `#e0af68` | | `BORDER_FOCUS` | `#7aa2f7` | `ERROR` | `#f7768e` | | `HIGHLIGHT` | `#3d59a1` | `INFO` | `#7dcfff` | | `HIGHLIGHT_DIM` | `#292e42` | `ACCENT_PURPLE` | `#bb9af7` | | `STATUS_BAR_BG` | `#16161e` | `ACCENT_PINK` | `#ff007c` | | `MODE_AUTO` | `#9ece6a` | `ACCENT_ORANGE` | `#ff9e64` | | `MODE_YOLO` | `#f7768e` | `ACCENT_TEAL` | `#73daca` | | `CODE_BG` | `#16161e` | `CODE_BAR` | `#292e42` | | `BLOCKQUOTE_BAR` | `#7dcfff` | `SCROLLBAR_BG` / `SCROLLBAR_FG` | `#1f2335` / `#3b4261` | ### Message density — tight inline log Replaces the per-message card (role badge pill + left accent bar + blank-line gap) in `chat.rs`: ``` you 09:14 fix the login bug ai 09:14 Looking at src/auth.rs now. ↳ Reading src/auth.rs you 09:15 ok try again ``` - Role rendered as a short lowercase colored label (`ROLE_*` colors), timestamp dim, inline with the first content line. - Wrapped/multi-line content aligns under the content column (not under the role label). - Tool-call sub-lines get a dim `↳` prefix. - No blank line within a turn; a single blank line only between different speakers (not after every message). - The chat panel's outer bordered `Block` is unchanged — only the messages inside it lose per-message decoration. - The streaming indicator becomes `ai 09:14 ⠋ generating...` inline, matching the new format, instead of the current padded badge line. ### Icons Overlay titles drop decorative emoji (❓⚙💻🚪✏️🎯🔌📋⏪📚📊⏳🧠🗑️⚡) and render as plain bold colored text (e.g. `Settings` in `PRIMARY`, no ⚙). The border/text accent color is the identity signal, consistent with the muted Tokyo Night + tight-density direction. ## File impact | File | Change | |---|---| | `view/theme.rs` | Palette values swap (table above). Const names/count unchanged. | | `view/chat.rs` | Rewrite message rendering to the tight inline format. | | `view/markdown.rs` | Re-themed code/quote colors; tightened padding. No structural rewrite. | | `view/mod.rs` | `draw()` grows the persistent sidebar column (generalizes `show_todo` split). `render_overlay()` match arms restyled in place (palette + title text), content logic untouched. Todo/Usage compact-widget rendering factored out of the current inline overlay code so it's callable from both the sidebar and the kept overlay. | | `view/status.rs` | Restyle to new palette; structurally unchanged. | | `view/workflow.rs` | Add a compact-card render function for the sidebar widget, reusing the existing per-agent formatting logic. | | `controller/*` | No changes. Interaction model is unchanged; sidebar is non-interactive. | ## Edge cases - Empty states per sidebar widget (no workflow running, no tasks, zero usage) — compact one-line placeholders, consistent with the tight density (not the current multi-line placeholder paragraphs). - Sidebar auto-collapses below ~90 cols; chat reclaims full width. - Sidebar widget overflow (e.g. a hive-mind run with many nodes, a long task list) truncates with a `+N more` hint pointing at the existing expand-overlay trigger. - Long chat content wraps with continuation lines aligned under the content column. ## Testing / verification No automated visual or snapshot tests exist for `view/`/`controller/` today (confirmed: zero `#[cfg(test)] mod tests` in either directory), and none are introduced by this change — ratatui rendering isn't meaningfully unit-testable without a snapshot harness this repo doesn't have. Verification is manual: run the TUI (`cargo run`) and exercise the golden paths (send a chat message, trigger a workflow/hive-mind run, open each of the 13 remaining overlays, resize the terminal across the sidebar-collapse threshold). `cargo clippy` must stay clean (warnings-as-errors per repo config), and every touched `pub fn`/`struct` keeps the doc-comment convention from CLAUDE.md (What/Flow/Why/Return). ## Suggested implementation order Not binding — the implementation plan owns sequencing — but a sensible build order given the dependency shape (palette first, since everything else reads `Theme` consts): 1. `theme.rs` palette swap 2. `chat.rs` tight-inline rewrite 3. `mod.rs` sidebar scaffolding + Workflow/Tasks/Usage compact widgets (+ `workflow.rs` compact-card fn) 4. `status.rs` restyle + remaining 13 overlay restyle (mechanical: palette + title text) 5. Manual TUI verification pass across golden paths above