Skip to content

fix(tui): drop the input box side borders so drag-select copies text alone - #2882

Open
puncsky wants to merge 1 commit into
MoonshotAI:mainfrom
puncsky:fix/borderless-composer
Open

fix(tui): drop the input box side borders so drag-select copies text alone#2882
puncsky wants to merge 1 commit into
MoonshotAI:mainfrom
puncsky:fix/borderless-composer

Conversation

@puncsky

@puncsky puncsky commented Aug 13, 2026

Copy link
Copy Markdown

Related Issue

No existing issue covers this — see the Problem section below. The closest one is #2095, which is about the caret being included in a mouse selection; that is a different glyph and is not fixed here.

Problem

The input box was drawn as a full box: rounded corners plus a in the outer column of every content row. Dragging to select the text with the mouse pulls those bars into the clipboard, so pasting the copy elsewhere gives something like

│ > deploy the staging worker              │

instead of the typed line. Content rows were also padded out to the full width, so the copy carried trailing spaces past the text.

What changed

The composer is now delimited by two edge-to-edge horizontal rules instead of a box, and nothing but text lives on the content rows.

  • paintHorizontalRules (was wrapWithSideBorders) repaints the top/bottom border rows across every column — including the two that used to carry ╭╮╰╯ — and returns content rows untouched, so no vertical bars are drawn at all. Scroll indicators (── ↑ N more ──) keep working as rules.
  • The > / ! prompt token moves to column 0 (paddingX 4 → 2, now the single EDITOR_PADDING_X constant that injectArgumentHint shares) and the mirrored right-hand padding is trimmed at render time. A copied row is then exactly the typed text: no leading gap, no trailing spaces. Rules and pi-tui's inverse-video caret both end in an SGR reset, so the trim can only ever eat unstyled padding.
  • The /btw panel gets the same treatment since it docks onto the composer: full-width rule on top, body indented to the editor's text column, no padding on the right, height-holding rows collapse to empty strings.
  • connectedAbove / borderHighlighted are gone — they existed only to choose the ├ ┤ connector corners, which are no longer drawn.

The bash-mode label keeps one leading dash (─ ! shell mode ───…) so the top row still reads as a rule rather than an indented caption, and the shell-mode / plan-mode / slash-context border colours are unchanged.

Before / after ( marks the end of each rendered row):

╭──────────────────────────────────────────────╮¶       ────────────────────────────────────────────────¶
│ > a very long line that should wrap near the │¶       > a very long line that should wrap near the¶
│   right edge to show the wrap column         │¶  →      right edge to show the wrap column¶
╰──────────────────────────────────────────────╯¶       ────────────────────────────────────────────────¶

Known trade-off: pi-tui's paddingX is symmetric, so the right-hand 2 columns are still reserved for padding and text wraps 2 columns earlier than the rule ends. It is invisible (the spaces are trimmed), but on a very narrow terminal it costs 2 columns of usable width. Making it truly asymmetric means changing the padding contract in packages/pi-tui, which felt out of scope for this fix — happy to follow up if you would rather have that.

Tests: paintHorizontalRules gets its own suite (rule width, no corner/bar glyphs, content passthrough, SGR repaint, label overlay and its overflow fallback, scroll-indicator rows), CustomEditor gains full-render assertions (no anywhere, top/bottom rows are exactly '─'.repeat(width), prompt flush at column 0 in both prompt and bash mode, no trailing padding on any row), and prompt-symbol is rewritten for the new geometry. test/tui passes at 139 files / 1962 tests, plus tsc --noEmit and oxlint --type-aware on the touched files.

The normative TUI design spec (.agents/skills/write-tui/DESIGN.md) is updated so the composer style is recorded next to the existing list/selector rule; dialog input boxes keep their rounded boxes.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update. (The docs describe the input box in prose only — no rendered box art — and the shell-mode wording "the border turns violet" still holds.)

…alone

The composer drew a full box: rounded corners plus a vertical bar on the
outer column of every content row. Dragging to select the text pulled
those bars into the clipboard, and the padded row width added trailing
spaces on top.

- Repaint the top/bottom border rows as edge-to-edge horizontal rules
  (the two columns that carried the corners are rule now) and leave
  content rows untouched, so no vertical bars are drawn at all.
- Move the `>` / `!` prompt token to column 0 (paddingX 4 -> 2) and trim
  the mirrored right-hand padding at render time; a copied row is then
  exactly the typed text. Rules and the inverse-video caret end in an SGR
  reset, so the trim never eats into them.
- Give the /btw panel the same treatment, since it docks onto the
  composer: full-width rule on top, body indented to the editor's text
  column, no padding to the right.
- Remove `connectedAbove` / `borderHighlighted`, which only existed to
  pick the connector corners that no longer get drawn.

The bash-mode label keeps one leading dash so the top rule still reads as
a rule, and the shell-mode / plan-mode border colours are unchanged.
@changeset-bot

changeset-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c6489a8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@puncsky
puncsky marked this pull request as ready for review August 13, 2026 06:55
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