diff --git a/.gitignore b/.gitignore index 3dbbf5a..479cbc7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ target/ .claude/settings.local.json node_modules/ package.json -package-lock.json \ No newline at end of file +package-lock.json +.superpowers/ \ No newline at end of file diff --git a/docs/superpowers/specs/2026-07-14-tui-overhaul-design.md b/docs/superpowers/specs/2026-07-14-tui-overhaul-design.md new file mode 100644 index 0000000..77ea27f --- /dev/null +++ b/docs/superpowers/specs/2026-07-14-tui-overhaul-design.md @@ -0,0 +1,187 @@ +# 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