Skip to content

feat(tui): lean detail + artifact into OpenTUI rich components (#192)#462

Merged
windoliver merged 27 commits into
mainfrom
feat/tui-192-detail-artifact-opentui
May 29, 2026
Merged

feat(tui): lean detail + artifact into OpenTUI rich components (#192)#462
windoliver merged 27 commits into
mainfrom
feat/tui-192-detail-artifact-opentui

Conversation

@windoliver
Copy link
Copy Markdown
Owner

Closes #192.

Leans detail.tsx and artifact-preview.tsx into OpenTUI's richer components, per the issue's "audit and upgrade high-value surfaces" scope. Focused first cycle — these two surfaces only; other surfaces (terminal, dag, dashboard, lists) are out of scope and tracked as follow-ups.

What changed

  • Detail view is now a <scrollbox> with focus-aware sections: j/k move a highlighted section (accent border + > marker), the scrollbox scrolls it into view, and all silent .slice() truncations were removed (full description / summaries / context are now reachable by scroll instead of being cut). Focus resets to the first section when you open a different contribution.
  • Artifact diff now renders through the real OpenTUI <diff> intrinsic (syntax-aware) instead of an uncolored hand-rolled <text> blob. [d] toggles diff on/off, [s] toggles split ↔ inline (view: "split" | "unified"). Diff input is capped at 2000 lines (OOM guard, visible truncation marker).
  • Minimal orientation transition: a ~150ms accent pulse on the focused section (detail) and the artifact header on change, via a shared useAccentPulse hook. Degrades gracefully to a static accent where the timeline engine is unavailable.

Acceptance criteria (#192)

  • Detail/artifact easier to inspect → scrollbox + no truncation + syntax-aware diff ✅
  • Focus/selection consistently obvious → accent border + > marker + pulse ✅
  • High-value transitions, not noise → single focus-change pulse ✅
  • Feels native to OpenTUI → <scrollbox> / <diff> / useTimeline

OpenTUI API note

A probe (and adversarial verification) established the real <diff> API is diff (a unified-diff string) + view: "unified" | "split" + filetype — there is no mode/oldContent/newContent. computeUnifiedDiff is kept (its output is the diff string) and now emits a valid @@ -1,m +1,n @@ hunk header so the intrinsic's parsePatch accepts it. The design spec was updated to the as-shipped behavior.

Verification

  • tsc --noEmit: 0 errors (run directly — note the repo typecheck script &&-chains the ask-user sub-build, which can mask the main tsc in a fresh worktree before bun install).
  • biome check: 0 errors. bun test: 8332 pass / 0 fail across 541 files.
  • This branch was produced via multi-agent orchestration with an adversarial multi-lens review that caught and fixed 4 real issues the basic gate missed:
    • detail j/k was dead in production — the resolved keymap dispatched cursor_down/up before the detail handler; now gated inside executeKeymapAction and confirmed under the real default keymap.
    • the new diff rendered a parse-error viewparsePatch requires an @@ header; verified fixed against three parsers including OpenTUI's own bundled parsePatch (all hunks=1, incl. adversarial content shapes).
    • a tsc failure (dead artifact_diff_mode case) and an incomplete test stub, both fixed.
    • section-focus test gaps closed and mutation-validated.

Remaining before merge

  • Live interactive TUI visual smoke (the one step automation can't fully judge — colors/animation/feel): open a contribution detail, j/k through sections; open an artifact with a parent, d then s. Recommended as a human visual pass.

Follow-ups (pre-existing, out of scope)

  • src/tui/components/split-diff.tsx passes nonexistent oldContent/newContent/mode props to <diff>compare-view.tsx diffs render empty/error. (Filing separately.)
  • intervalMs is a dead prop on both views (documented "kept for caller-stability").

windoliver added 19 commits May 28, 2026 12:09
Add onDetailSectionNext/onDetailSectionPrev to KeyboardActions and insert
a detail-view guard before the generic within-panel j/k navigation block so
that pressing j/k while the detail overlay is open moves the focused section
instead of calling cursorDown/cursorUp.
Use React.createElement (member access) for <diff>/<scrollbox>/<markdown>/<code>
intrinsics so a process-wide leaked mock.module(@opentui/react) that exports
createElement:()=>null can no longer collapse the subtree to null under the
full bun test run. Resolve useTimeline once at module load with a no-op
chainable fallback for mocks that omit it. Flush the artifact diff test until
the <diff> node settles. Remove the #192 probe.
@windoliver windoliver merged commit 55a7a83 into main May 29, 2026
1 check passed
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.

TUI: lean further into OpenTUI rich components and transitions

1 participant