# Design SF's UI is a terminal application built on the Pi TUI framework (`@mariozechner/pi-tui`). These are the binding constraints any UI work must respect. ## The Cardinal Rule: Line Width **Every line returned from `render(width)` must not exceed `width` in visible characters.** Exceeding it causes terminal line-wrapping, cursor misposition, and visual corruption the framework cannot fix. Use the Pi TUI utilities — never raw `string.length`: ```typescript import { visibleWidth, truncateToWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui"; visibleWidth("\x1b[32mHello\x1b[0m"); // 5, not 14 truncateToWidth("Very long text here", 10); // "Very lo..." wrapTextWithAnsi("\x1b[32mlong green\x1b[0m", 15); // preserves ANSI per line ``` `visibleWidth` strips ANSI escape codes before measuring. `truncateToWidth` preserves ANSI codes in the truncated output. Use these everywhere a line's display length matters. ## Render Pattern ```typescript render(width: number): string[] { const lines: string[] = []; lines.push(truncateToWidth(` ${prefix}${content}`, width)); const labelWidth = visibleWidth(label); const available = width - labelWidth - 4; // padding lines.push(` ${label}: ${truncateToWidth(value, available)}`); return lines; } ``` ## Overlays and Modals Floating panels use the Pi TUI overlay pattern: they render at a fixed position within the terminal bounds and must still respect the outer `width` constraint. An overlay that overflows its bounds causes the same wrapping corruption as any other component. Use `ctx.ui.dialog()` for modal user input. Use `ctx.ui.notify()` for transient non-blocking notices. Persistent notification state goes through `notification-store.ts` → `notification-overlay.ts`. ## Theming Colors and styles come from the Pi TUI theme system, not from hardcoded ANSI codes. Access the active theme via the `ExtensionContext`. Respect theme changes: components must re-render when the theme changes (implement `onThemeChange` if caching rendered output). ## IME and Focus Interactive input components must implement the `Focusable` interface to receive keyboard events correctly, especially for IME (input method editor) support on non-ASCII keyboards. Components that handle key input but do not implement `Focusable` will silently swallow events. ## Performance Cache rendered output when the underlying data hasn't changed. Invalidate the cache on data change or theme change. Do not re-render on every tick. The TUI framework calls `render()` frequently; rendering must be cheap. ## Reference Full TUI documentation: [`docs/dev/pi-ui-tui/`](./dev/pi-ui-tui/README.md)