Skip to content

feat(scene): restructure the trace frame as a three-pane Sidebar/Main/ContextPanel layout#1003

Merged
esengine merged 1 commit into
mainfrom
rust-scene-three-pane
May 16, 2026
Merged

feat(scene): restructure the trace frame as a three-pane Sidebar/Main/ContextPanel layout#1003
esengine merged 1 commit into
mainfrom
rust-scene-three-pane

Conversation

@esengine
Copy link
Copy Markdown
Owner

Stage 1 toward the user's design mock. Restructures the trace frame
from a flat column of rows into the classic IDE three-pane shape.

```
┌───────────── title (full width) ─────────────┐
│ SIDEBAR (24) │ MAIN (fill) │ CTX (32) │
└───────────── status (full width) ────────────┘
```

What

The middle band is a `direction: "row"` box with `height: "fill"`,
made possible by the flex-sizing infra from #1000. Sidebar and
context pane have fixed cell widths; main pane fills the remainder.
Both side panes auto-hide on narrow terminals — sidebar below
60 cols, context pane below 100 cols — so an 80-col terminal still
works the way it did before, just with a sessions rail on the left.

Main pane (unchanged behavior). Cards stack, composer / approval /
sessions-picker takeover, slash overlay — exactly the same nodes as
before, now living inside the main pane's column instead of inline
in the root.

Sidebar (stage-1 placeholder). Just `─ SESSIONS ─` header +
`use /sessions to browse` hint. The real session list goes here in
stage 2 once App.tsx surfaces a permanently-loaded list (today it's
loaded only when the picker is open). Doing this PR without real data
is deliberate — the structural change is large enough on its own,
and the placeholder honestly says "this is where it goes."

Context pane (uses what's wired). `─ CONTEXT ─` + `model · cards
· wallet`. Wallet moves from the status row into the ctx pane when
both are visible — avoids duplicating it. At cols < 100 the ctx pane
is hidden and wallet stays on the right of the status row (as in
#1001).

Test rewrite

The flat-children shape was load-bearing in 15 tests. Added three
helpers (`mainOf(f)` / `statusOf(f)` / `titleOf(f)`) and rewrote
each test to drill through the new structure. Coverage is identical
in spirit (cards / composer / approval modal / sessions picker /
slash overlay / status segments all still verified) but expressed
against the new hierarchy.

3 new shape tests:

  • root is now `[title, middle, status]` (3 children, not 4-7)
  • sidebar hidden below 60 cols
  • context pane hidden below 100 cols
  • wallet moves from status row into context pane when both visible

`npm run verify` green via prepush gate (61 scene-trace tests).

Coming up (separate sub-PRs)

  • Stage 2 — real sessions list in the sidebar (wires App.tsx to
    keep `sessionsPickerList` populated whether or not the picker is
    open).
  • Stage 3 — fill the context pane with cache-hit % and context token
    meter (telemetry/stats data).
  • Stage 4 — card head/body split + collapse (long tool outputs).

Refs #868

…/ContextPanel layout

Stage 1 toward the user's design mock — restructure from a flat
column of rows to the classic IDE three-pane shape:

  ┌───────────── title (full width) ─────────────┐
  │ SIDEBAR (24) │   MAIN (fill)   │  CTX (32)   │
  └───────────── status (full width) ────────────┘

The middle band is a `direction: "row"` box with `height: "fill"`,
made possible by the flex-sizing infra from #1000. Sidebar and ctx
pane have fixed cell widths; main pane fills the remainder. Both
side panes auto-hide on narrow terminals — sidebar below 60 cols,
ctx pane below 100 cols — so an 80-col terminal still works the way
it did before, just with a sessions-rail on the left.

## Main pane content (unchanged)

The cards stack, composer / approval / sessions-picker takeover,
slash overlay — exactly the same nodes as before, now living inside
the main pane's column instead of inline in the root.

## Sidebar (stage-1 placeholder)

Just a `─ SESSIONS ─` header + `use /sessions to browse` hint. The
real session list goes here in stage 2 once App.tsx surfaces a
permanently-loaded list (today it's loaded only when the picker is
open).

## Context pane (uses what's wired)

`─ CONTEXT ─` + `model · cards · wallet`. Wallet moves from the
status row into the ctx pane when both are visible — avoids
duplicating it. At cols < 100 the ctx pane is hidden and wallet
stays on the right of the status row (as in #1001).

## Test rewrite

The flat-children shape was load-bearing in 15 tests. Added two
helpers — `mainOf(f)` / `statusOf(f)` / `titleOf(f)` — and rewrote
each test to drill through the new structure. Coverage is identical
in spirit (still asserts behavior of card rows, composer, approval
modal, sessions picker, slash overlay, status segments) but
expressed in terms of the new hierarchy.

3 new shape tests:
- root is now `[title, middle, status]` (3 children, not 4-7)
- sidebar hidden below 60 cols
- ctx pane hidden below 100 cols

Refs #868
@esengine esengine merged commit 82eff74 into main May 16, 2026
5 checks passed
@esengine esengine deleted the rust-scene-three-pane branch May 16, 2026 03:10
esengine added a commit that referenced this pull request May 16, 2026
… palette (#1005)

Closes the visual gap between the structural three-pane layout from
#1003 and the user's design mock. Previously every cell defaulted to
the terminal's stock bg/fg; now the trace frame honors a small
palette derived from the mock's oklch tokens, panes carry rounded
borders, and title / status rows sit on a panel-tinted bar.

## Schema + Rust render

- `BoxLayout.background?: Color` — new field, same shape as
  `borderColor`. Schema added in both TS (types.ts) and Rust
  (scene.rs).
- `render_box` now runs `apply_decoration(layout, buf, area)` before
  laying out children:
  - if `background` is set, fills every cell of the box area with
    that bg (via ratatui Block's style).
  - if `borderStyle` is set, draws ratatui's box-drawing perimeter
    (Plain/Double/Rounded/Thick) in `borderColor`, shrinking inner
    area by 1 cell on each side for children.
  - both are independent — bg without border (title/status bars)
    works, border without bg (debug outlines) works too.

ratatui's `Block` widget already does the right thing for the
combined case (fill then draw border on top), so we lean on that
rather than rolling perimeter-drawing by hand.

## Design palette (`src/cli/ui/scene/theme.ts`)

oklch tokens from the mock converted to hex once, frozen as
`PALETTE.{bg, bg2, panel, card, border, borderStrong, fg, fg2,
muted, accent, accentStrong, success, warning, danger, violet}`.
Single source of truth — components don't pick raw colors anymore.

## Producer side

- Outer frame: `background: PALETTE.bg` (dark blue-grey base, sits
  behind every pane).
- Title row: `background: PALETTE.panel`, brand prefix glyph in
  `accent`, model name in `violet` (matches the gradient brand mark
  in the mock).
- Sidebar + ctx pane: `borderStyle: round` + `borderColor: border`
  + `background: bg2`. Reads as two soft cards flanking the main
  pane, same shape as the mock's panel/card style (modulo CSS
  gradients which ratatui can't do).
- Status bar: `background: PALETTE.panel`, busy/idle in
  warning/success hexes from the palette, wallet segment in
  success when present.
- Section headers (`SESSIONS`, `CONTEXT`) drop the dash decoration
  and use bold accent — cleaner now that bordered panes provide the
  framing.

## Tests

- Rust (6 new): box-drawing chars at perimeter for Single / Round /
  Double border styles, border color applied to perimeter cells,
  background fills every cell, border shrinks inner area by 1
  on each side.
- JS: existing 61 tests adjusted to the new shapes (status row is
  now always a box for its bg tint, busy/idle assert hex colors via
  PALETTE rather than named "green"/"yellow"). 2 new shape
  assertions: title/status carry a background; side/ctx panes
  carry borderStyle=round + background.

`cargo test -p reasonix-render --test render` → 23/23.
`npm run verify` → green via prepush gate.

## What's still aspirational

Real CSS gradients, drop shadows, border-radius smoothness, custom
fonts, hover states — ratatui can't do any of these and won't.
That's the floor for "TUI-native faithful to the mock"; everything
above is what we ship.

Refs #868

Co-authored-by: reasonix <reasonix@deepseek.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant