Skip to content

TUI design polish: bordered titles, status pills, dense controls, hatched empty states#10

Merged
21tmccauley merged 2 commits into
mainfrom
feat/tui-design-tier1
Jul 10, 2026
Merged

TUI design polish: bordered titles, status pills, dense controls, hatched empty states#10
21tmccauley merged 2 commits into
mainfrom
feat/tui-design-tier1

Conversation

@21tmccauley

Copy link
Copy Markdown
Collaborator

What

A visual-design pass on the TUI, porting the design language of Posting (also a Textual app, so its patterns port as CSS + small widget tweaks). No behavior changes — layout, keybindings, and the api facade surface are untouched.

Panels — titles moved into the border frame (border_title, right-aligned). Panels rest at a 40%-alpha border and brighten to full $primary + bold title on :focus-within, so the active pane is always obvious, and every panel gained a content row. The Evidence files panel carries the selected run's scoreboard in its border title (run-id ✓ 4 ✗ 2).

Status pills — new palette.pill() / status_pill() helpers render statuses as readable text on a same-hue muted swatch (the exact text-*/*-muted pairs Textual derives for tokyo-night). Run statuses, manifest ✓/⚠ cells, upload preflight, and nonzero exit codes all route through them — replacing the hand-picked "green"/"red" literals that were duplicated across six screens.

Dense controls — inputs and buttons flatten to one row (Button's tall borders zeroed in every state). A focused input shows a wide $primary left edge with padding swapped so text never shifts. Top bars realigned for the new heights; modals got denser for free.

Chrome — thin 1-cell scrollbars tinted $primary (brighten on hover/focus), muted-bold DataTable headers, and render.py detail panes moved onto the Tokyo Night palette hexes so contract/entry views match the rest of the app.

Hatched empty states — a .panel tagged .empty swaps its table/log for a hatched, centered placeholder with the relevant keybind accented: Run before a run, Evidence with no runs / no files, Upload before an upload, Manifest when empty or unloaded. Cleared automatically when content arrives (the run console also clears on the run_start event so the synthetic-event test path behaves identically).

Verification

  • Headless Pilot tour: every tab, both modal types, and a synthetic-event run (ok / partial / skipped / error / running variety) screenshotted at each state.
  • Full test suite: 209 passed.

Notes for review

  • The riskiest change is the global Input/Button restyle — only the states this app uses (base/hover/active, -primary, -error) are flattened; a future variant="success" button would regain tall borders.
  • STATUS_TONE covers all eight runner statuses; unknown words fall back to muted text rather than crashing.
  • docs/demo/tui.gif still shows the old design and needs regenerating (left out to keep this reviewable).

🤖 Generated with Claude Code

Tate McCauley and others added 2 commits July 10, 2026 09:13
…ls, dense controls

Tier 1 of the Posting design port (both apps are Textual, so the patterns
port as CSS):

- Panel titles move into the border (border_title, right-aligned); panels
  rest at 40%-alpha borders and brighten to full $primary + bold title on
  focus-within. Evidence's files panel carries the run scoreboard in its
  border title.
- New palette.pill()/status_pill() render status cells as text on a
  same-hue muted swatch (the tokyo-night text-*/*-muted pairs), replacing
  hand-picked green/red literals across run/manifest/evidence/upload.
- Inputs and buttons flatten to one row; focused inputs show a wide
  $primary left edge with padding swapped so text never shifts.
- Thin 1-cell scrollbars tinted $primary, muted-bold DataTable headers,
  and render.py detail panes moved onto the palette hexes.

Verified with a headless Pilot tour (screenshots of every tab, modals, and
a synthetic-event run); 209 tests pass.

Co-Authored-By: Claude Fable 5 <[email protected]>
…st panels

A .panel tagged .empty hides its DataTable/RichLog and shows a hatched,
centered .empty-hint placeholder instead (Posting's empty-state idiom),
with the relevant keybind accented in the hint:

- Run: both panels hatch until a run starts ("ctrl+r executes the
  manifest"); cleared by _start_run and by the run_start event so the
  synthetic-event test path behaves the same; reset_state restores them.
- Evidence: runs panel hatches when no runs exist, files panel when the
  selected run produced no files.
- Upload: the log panel hatches until an upload starts.
- Manifest: the entries panel hatches with a message that adapts to
  "no manifest loaded" vs "manifest is empty".

Verified with the headless Pilot screenshot tour; 209 tests pass.

Co-Authored-By: Claude Fable 5 <[email protected]>
@21tmccauley
21tmccauley merged commit ac8e1f7 into main Jul 10, 2026
12 checks passed
@21tmccauley
21tmccauley deleted the feat/tui-design-tier1 branch July 10, 2026 19:17
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