From 6226f7457cc7d3b043f3255ed0daf047002e3a51 Mon Sep 17 00:00:00 2001 From: can1357 Date: Thu, 20 Aug 2026 06:36:43 +0200 Subject: [PATCH] feat(tui): implemented top border truncation and exported rule module - Add top border truncation in renderTopRule to handle narrow terminals gracefully. - Export rule module consistently in index. --- packages/tui/src/components/composer/claude.ts | 3 ++- packages/tui/src/components/composer/index.ts | 2 +- packages/tui/src/components/composer/rule.ts | 16 ++++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/tui/src/components/composer/claude.ts b/packages/tui/src/components/composer/claude.ts index 32d5ff770..4a9485363 100644 --- a/packages/tui/src/components/composer/claude.ts +++ b/packages/tui/src/components/composer/claude.ts @@ -4,8 +4,9 @@ * bg chip near the right edge (`─────── hi ─`); the left group renders as a * plain standalone bottom bar that yields its row to the autocomplete menu. */ -import type { ComposerChromeContext, ComposerRowContext, ComposerStyle } from "./types"; + import { renderTopRule } from "./rule"; +import type { ComposerChromeContext, ComposerRowContext, ComposerStyle } from "./types"; export const claudeComposerStyle: ComposerStyle = { id: "claude", diff --git a/packages/tui/src/components/composer/index.ts b/packages/tui/src/components/composer/index.ts index 9c0708001..28cd0b1e4 100644 --- a/packages/tui/src/components/composer/index.ts +++ b/packages/tui/src/components/composer/index.ts @@ -4,6 +4,6 @@ export * from "./claude"; export * from "./field"; export * from "./pi"; export * from "./rail"; -export * from "./rule"; export * from "./registry"; +export * from "./rule"; export * from "./types"; diff --git a/packages/tui/src/components/composer/rule.ts b/packages/tui/src/components/composer/rule.ts index d2dbabe3e..96fc32246 100644 --- a/packages/tui/src/components/composer/rule.ts +++ b/packages/tui/src/components/composer/rule.ts @@ -3,14 +3,22 @@ * right status group rides the rule while the left group remains below the * editor, preserving the compact status split without a closing rule. */ +import { truncateToWidth, visibleWidth } from "../../utils"; import type { ComposerChromeContext, ComposerRowContext, ComposerStyle } from "./types"; -/** Draw a full-width rule with optional status content docked at its right edge. */ +/** Draw a full-width rule with status content docked at its right edge. + * Over-wide content is truncated (keeping one rule cell on each side) rather + * than dropped, so the chip survives narrow terminals and previews. */ export function renderTopRule(ctx: ComposerChromeContext): string { const { box, width, borderColor, topBorder } = ctx; - if (topBorder && topBorder.width > 0 && topBorder.width <= width - 2) { - const leftFill = Math.max(0, width - topBorder.width - 1); - return borderColor(box.horizontal.repeat(leftFill)) + topBorder.content + borderColor(box.horizontal); + if (topBorder && topBorder.width > 0 && width > 2) { + let { content, width: chipWidth } = topBorder; + if (chipWidth > width - 2) { + content = truncateToWidth(content, width - 2); + chipWidth = visibleWidth(content); + } + const leftFill = Math.max(0, width - chipWidth - 1); + return borderColor(box.horizontal.repeat(leftFill)) + content + borderColor(box.horizontal); } return borderColor(box.horizontal.repeat(width)); }