import { RGBA, StyledText, TextAttributes, type TextChunk } from "@opentui/core" export interface FooterHint { key: string label: string tone?: "normal" | "danger" } export interface FooterHintTheme { accent: string danger: string muted: string separator: string } export type FooterMode = | "mention" | "active" | "branch" | "command" | "session" | "context" | "history" | "ready" export function contextualFooterHints( mode: FooterMode, width: number, theme: FooterHintTheme, ): StyledText { return footerHints(hintsFor(mode, width), theme) } /** Give shortcuts visual hierarchy without turning the footer into a toolbar. */ export function footerHints(hints: readonly FooterHint[], theme: FooterHintTheme): StyledText { const chunks: TextChunk[] = [] hints.forEach((hint, index) => { if (index) chunks.push(chunk(" · ", theme.separator)) const color = hint.tone === "danger" ? theme.danger : theme.accent chunks.push(chunk(hint.key, color, true)) chunks.push(chunk(` ${hint.label}`, theme.muted)) }) return new StyledText(chunks) } function hintsFor(mode: FooterMode, width: number): FooterHint[] { if (mode === "mention") return width >= 64 ? [hint("↑↓", "choose"), hint("tab/enter", "insert"), hint("esc", "close")] : [hint("enter", "insert"), hint("esc", "close")] if (mode === "active") return width >= 96 ? [hint("enter", "steer"), hint("tab", "queue"), hint("alt+↑", "edit"), stopHint()] : width >= 64 ? [hint("enter", "steer"), hint("tab", "queue"), stopHint()] : [] if (mode === "branch") return width >= 64 ? [hint("type", "filter"), hint("↑↓", "choose"), hint("enter", "branch"), hint("esc", "close")] : [hint("enter", "branch"), hint("esc", "close")] if (mode === "command") return width >= 72 ? [hint("↑↓", "choose"), hint("tab", "complete"), hint("esc", "close")] : [hint("tab", "complete"), hint("esc", "close")] if (mode === "session") return width >= 64 ? [hint("type", "filter"), hint("↑↓", "choose"), hint("enter", "open"), hint("esc", "close")] : [hint("enter", "open"), hint("esc", "close")] if (mode === "context") return [hint("esc", "close"), hint("pgup/pgdn", "scroll")] if (mode === "history") return width >= 72 ? [hint("ctrl+end", "latest"), hint("pgup/pgdn", "scroll")] : width >= 48 ? [hint("ctrl+end", "latest")] : [] if (width >= 112) return [ hint("enter", "send"), hint("ctrl+j", "newline"), hint("pgup/pgdn", "scroll"), hint("ctrl+o", "tools"), stopHint(), ] if (width >= 72) return [hint("enter", "send"), hint("ctrl+j", "newline"), stopHint()] return width >= 48 ? [hint("enter", "send"), hint("ctrl+j", "newline")] : [] } function hint(key: string, label: string): FooterHint { return { key, label } } function stopHint(): FooterHint { return { key: "ctrl+c", label: "stop", tone: "danger" } } function chunk(text: string, color: string, bold = false): TextChunk { return { __isChunk: true, text, fg: RGBA.fromHex(color), attributes: bold ? TextAttributes.BOLD : 0, } }