Skip to content

fix(rendering): adapt terminal output to narrow widths (swamp-club#377)#1401

Merged
stack72 merged 2 commits into
mainfrom
fix/terminal-rendering-narrow-widths
May 19, 2026
Merged

fix(rendering): adapt terminal output to narrow widths (swamp-club#377)#1401
stack72 merged 2 commits into
mainfrom
fix/terminal-rendering-narrow-widths

Conversation

@stack72
Copy link
Copy Markdown
Contributor

@stack72 stack72 commented May 19, 2026

Summary

  • Flatten all 14 SearchPicker preview callbacks from nested <Box> structures to flat <Text> arrays — nested Boxes cause Ink/Yoga layout garbling at narrow terminal widths
  • Add overflow="hidden" to ResultsList and SearchPicker's inline/minimal tier containers
  • Create getTerminalColumns() utility wrapping Deno.consoleSize() with 80-col fallback for log-mode renderers
  • Update 6 log-mode renderers (audit timeline, extension list, data list, summarise, method-run reports, report get) to use terminal-width-aware separators, truncation, and markdown maxWidth
  • Document terminal width conventions in design/rendering.md

Test Plan

  • Verified TUI rendering at 76, 80, and 254 columns — model type search, model search, data search, extension search, workflow search, data query
  • Confirmed bordered-split layout at wide widths shows no regression
  • Confirmed stacked/inline layouts at narrow widths render cleanly with truncation
  • 5987 tests pass, 0 failures

🤖 Generated with Claude Code

TUI SearchPicker preview panes used nested <Box> structures that Ink/Yoga
laid out at natural content width then clipped, causing garbled text at
narrow terminals. Flatten all 14 preview callbacks to use only <Text>
elements in a single <Box flexDirection="column">, and add
overflow="hidden" to ResultsList and the inline/minimal tier containers.

Log-mode renderers (extension list, audit timeline, data list, summarise,
method-run reports, report get) had zero terminal width awareness —
hardcoded separators and unclamped column widths. Add getTerminalColumns()
utility wrapping Deno.consoleSize() with 80-col fallback, and use it for
terminal-width-aware separators, truncation, and markdown maxWidth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

- Restore dropped raw type name in type_search.tsx detail preview
- Fix report header separator overflow in model_method_run.ts by computing
  separator length as cols minus header prefix length
- Remove unreachable getTerminalColumns() fallback in report_get.ts
- Remove whole-line truncation before logger.info in extension_list.ts
  to follow the convention that only writeOutput() calls get width constraints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI UX Review

Blocking

None.

Suggestions

  1. audit_timeline.ts — truncation sentinel inconsistency (pre-existing, not introduced here): The audit timeline still uses "..." (3-char ASCII) with a -3 offset, while the new truncations in data_list.ts and extension_list.ts use "…" (single Unicode ellipsis) with a -1 offset. This pre-dated the PR, but since several renderers were touched it would be a natural place to align them. Non-blocking.

  2. report_search.tsxrenderMarkdownToTerminal in detail preview has no maxWidth: The full-detail path calls renderMarkdownToTerminal(detail.markdown) without maxWidth before wrapping the result in <Text wrap="truncate-end">. Log-mode renderers (report_get.ts, model_method_run.ts) do pass maxWidth. In TUI mode Ink's wrap="truncate-end" will clip each line, so this is functional — but markdown tables and code blocks may render wider than the pane before being clipped rather than reflowed. Passing innerWidth here would make it consistent with the log-mode approach.

Verdict

PASS — rendering-only change that improves narrow-terminal experience across all interactive search pickers and six log-mode renderers. No UX regressions, no missing JSON fields, no broken help text. Both truncation strategies (log-mode getTerminalColumns() + Ink overflow="hidden" / wrap="truncate-end") are applied consistently across the renderer surface area.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Blocking Issues

None.

Suggestions

  1. Missing truncation in summarise.ts before padEnd() — In extension_list.ts, names are properly truncated before padding when they exceed the clamped max:

    const name = ext.name.length > maxName
      ? ext.name.substring(0, maxName - 1) + "…"
      : ext.name;
    const paddedName = name.padEnd(maxName);

    But in summarise.ts, both method.method (line 82) and group.workflowName (line 153) are passed directly to .padEnd() without truncation. When a name exceeds Math.floor(cols * 0.4), padEnd is a no-op and the full name is printed, defeating the column clamping. Consider adding the same truncation pattern used in extension_list.ts.

  2. report_get.ts captures terminal width at construction timeLogReportGetRenderer calls getTerminalColumns() in its constructor rather than in the completed handler. If a resize happens between construction and rendering, the old width is used. The other log-mode renderers all call it at render time. This is unlikely to matter in practice (these are short-lived command invocations), but it's a minor inconsistency.

Overall

Well-scoped fix. All changes are confined to the presentation layer — no domain logic touched. The getTerminalColumns() utility is placed correctly in presentation/output/, has a unit test, and the Ink changes (adding overflow="hidden", width constraints, wrap="truncate-end") consistently follow the same pattern. The flattening from nested <Box> to flat <Text> arrays is the right approach to avoid Ink/Yoga layout issues. Design doc update is a nice addition.

@stack72 stack72 merged commit b868506 into main May 19, 2026
11 checks passed
@stack72 stack72 deleted the fix/terminal-rendering-narrow-widths branch May 19, 2026 15:18
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