From 0fee65cf6ba437f3899bba879fbde805c93f9a04 Mon Sep 17 00:00:00 2001 From: Loki Date: Wed, 14 Oct 2026 15:59:27 +0800 Subject: [PATCH] fix(terminal): search box as full-width strings; indent no longer adds 8px - The /plugins search box sits under 'Install Plugins (n/m)', as in Claude Code. Each row is one string sized to the window's cells, so the corners meet the lines and the box copies whole. - The cell indent utility was named indent-*, the same as Tailwind's text-indent. Every indented row got 8px more on its first line. It is now pl-cells-*, like w-cells-* and gap-cells-*. Co-Authored-By: Claude Opus 5.5 --- app/globals.css | 2 +- registry.json | 2 +- .../winlab/blocks/claude-code/claude-code.tsx | 75 ++++++++++++------- registry/winlab/ui/terminal.tsx | 12 +-- 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/app/globals.css b/app/globals.css index 240a826..20a9e6c 100644 --- a/app/globals.css +++ b/app/globals.css @@ -366,7 +366,7 @@ } } /* terminal: widths and indents in character cells */ -@utility indent-* { +@utility pl-cells-* { padding-inline-start: calc(--value(integer) * 1ch); } @utility cell-wide { diff --git a/registry.json b/registry.json index 62e550a..6c46353 100644 --- a/registry.json +++ b/registry.json @@ -680,7 +680,7 @@ } }, "css": { - "@utility indent-*": { + "@utility pl-cells-*": { "padding-inline-start": "calc(--value(integer) * 1ch)" }, "@utility cell-wide": { diff --git a/registry/winlab/blocks/claude-code/claude-code.tsx b/registry/winlab/blocks/claude-code/claude-code.tsx index 1622b4e..c6a249b 100644 --- a/registry/winlab/blocks/claude-code/claude-code.tsx +++ b/registry/winlab/blocks/claude-code/claude-code.tsx @@ -735,30 +735,52 @@ function Marketplace({ ) } -// A search field in a menu, such as the one above /plugins > Discover: a -// round box drawn with box characters, as wide as the screen. +// How many monospace cells fit across `ref`: a terminal box is drawn to the +// window's width, one character per cell. The probe holds 10 cells. +function useColumns(ref: React.RefObject) { + const [columns, setColumns] = React.useState(0) + React.useEffect(() => { + const row = ref.current + const probe = row?.querySelector("[data-probe]") + if (!row || !probe) return + const measure = () => + setColumns( + Math.floor(row.clientWidth / (probe.getBoundingClientRect().width / 10)) + ) + // The observer reports the first size as soon as it starts; the web font + // can arrive later and change the cell width. + const observer = new ResizeObserver(measure) + observer.observe(row) + document.fonts.ready.then(measure) + return () => observer.disconnect() + }, [ref]) + return columns +} + +// A search field in a menu, such as the one in /plugins > Discover: a round +// box as wide as the screen. Each row is one string, the way the terminal +// prints it, so the box copies whole. function SearchBox({ placeholder = "Search…" }: { placeholder?: string }) { - const edge = (left: string, right: string) => ( - - {left} - - {"─".repeat(240)} - - {right} - - ) + const row = React.useRef(null) + const columns = useColumns(row) + const inner = Math.max(0, columns - 2) + const text = ` ⌕ ${placeholder}`.slice(0, inner).padEnd(inner) return ( -
- {edge("╭", "╮")} - - │ - - {" ⌕ "} - {placeholder} - - │ - - {edge("╰", "╯")} +
+
+ + 0000000000 + + + {columns > 1 && `╭${"─".repeat(inner)}╮`} + + + {columns > 1 && `│${text}│`} + + + {columns > 1 && `╰${"─".repeat(inner)}╯`} + +
) } @@ -776,9 +798,9 @@ function cut(text: string, width: number) { return text.length > width ? `${text.slice(0, width - 1)}…` : text } -// The plugin list of /plugins > Discover: a count, then one row per plugin -// with its description cut to `width` cells and its version. `shown` rows -// are drawn; the rest sit under "more below". +// The plugin list of /plugins > Discover: a count, the search box, then one +// row per plugin with its description cut to `width` cells and its version. +// `shown` rows are drawn; the rest sit under "more below". function PluginList({ items, choice, @@ -792,12 +814,13 @@ function PluginList({ }) { return ( <> - + Install Plugins{" "} ({choice + 1}/{items.length}) + {items.slice(0, shown).map((item, index) => { const on = index === choice return ( diff --git a/registry/winlab/ui/terminal.tsx b/registry/winlab/ui/terminal.tsx index 809efc4..2a4930e 100644 --- a/registry/winlab/ui/terminal.tsx +++ b/registry/winlab/ui/terminal.tsx @@ -195,12 +195,12 @@ function TerminalLine({ }) { const pad = [ "", - "indent-1", - "indent-2", - "indent-3", - "indent-4", - "indent-5", - "indent-6", + "pl-cells-1", + "pl-cells-2", + "pl-cells-3", + "pl-cells-4", + "pl-cells-5", + "pl-cells-6", ] return (