From 547a975707c16253edf03c2d6ec30f8e499c83ad Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 12 Jan 2026 09:42:28 -0500 Subject: [PATCH] tui: redesign tips display on home screen --- .../cli/cmd/tui/component/did-you-know.tsx | 51 ------------------- .../cmd/tui/component/{tips.ts => tips.tsx} | 51 ++++++++++++++++++- .../opencode/src/cli/cmd/tui/context/kv.tsx | 3 ++ .../opencode/src/cli/cmd/tui/routes/home.tsx | 21 ++------ 4 files changed, 57 insertions(+), 69 deletions(-) delete mode 100644 packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx rename packages/opencode/src/cli/cmd/tui/component/{tips.ts => tips.tsx} (86%) diff --git a/packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx b/packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx deleted file mode 100644 index 10042d938..000000000 --- a/packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { createMemo, createSignal, For } from "solid-js" -import { useTheme } from "@tui/context/theme" -import { TIPS } from "./tips" - -type TipPart = { text: string; highlight: boolean } - -function parseTip(tip: string): TipPart[] { - const parts: TipPart[] = [] - const regex = /\{highlight\}(.*?)\{\/highlight\}/g - let lastIndex = 0 - let match - - while ((match = regex.exec(tip)) !== null) { - if (match.index > lastIndex) { - parts.push({ text: tip.slice(lastIndex, match.index), highlight: false }) - } - parts.push({ text: match[1], highlight: true }) - lastIndex = regex.lastIndex - } - - if (lastIndex < tip.length) { - parts.push({ text: tip.slice(lastIndex), highlight: false }) - } - - return parts -} - -const [tipIndex, setTipIndex] = createSignal(Math.floor(Math.random() * TIPS.length)) - -export function randomizeTip() { - setTipIndex(Math.floor(Math.random() * TIPS.length)) -} - -export function DidYouKnow() { - const { theme } = useTheme() - - const tipParts = createMemo(() => parseTip(TIPS[tipIndex()])) - - return ( - - - ● Tip{" "} - - - - {(part) => {part.text}} - - - - ) -} diff --git a/packages/opencode/src/cli/cmd/tui/component/tips.ts b/packages/opencode/src/cli/cmd/tui/component/tips.tsx similarity index 86% rename from packages/opencode/src/cli/cmd/tui/component/tips.ts rename to packages/opencode/src/cli/cmd/tui/component/tips.tsx index 24e0913e9..18d3c2df1 100644 --- a/packages/opencode/src/cli/cmd/tui/component/tips.ts +++ b/packages/opencode/src/cli/cmd/tui/component/tips.tsx @@ -1,4 +1,51 @@ -export const TIPS = [ +import { createMemo, createSignal, For } from "solid-js" +import { useTheme } from "@tui/context/theme" + +type TipPart = { text: string; highlight: boolean } + +function parse(tip: string): TipPart[] { + const parts: TipPart[] = [] + const regex = /\{highlight\}(.*?)\{\/highlight\}/g + const found = Array.from(tip.matchAll(regex)) + const state = found.reduce( + (acc, match) => { + const start = match.index ?? 0 + if (start > acc.index) { + acc.parts.push({ text: tip.slice(acc.index, start), highlight: false }) + } + acc.parts.push({ text: match[1], highlight: true }) + acc.index = start + match[0].length + return acc + }, + { parts, index: 0 }, + ) + + if (state.index < tip.length) { + parts.push({ text: tip.slice(state.index), highlight: false }) + } + + return parts +} + +export function Tips() { + const theme = useTheme().theme + const parts = parse(TIPS[Math.floor(Math.random() * TIPS.length)]) + + return ( + + + ● Tip{" "} + + + + {(part) => {part.text}} + + + + ) +} + +const TIPS = [ "Type {highlight}@{/highlight} followed by a filename to fuzzy search and attach files", "Start a message with {highlight}!{/highlight} to run shell commands directly (e.g., {highlight}!ls -la{/highlight})", "Press {highlight}Tab{/highlight} to cycle between Build and Plan agents", @@ -78,7 +125,7 @@ export const TIPS = [ "Set agent {highlight}temperature{/highlight} from 0.0 (focused) to 1.0 (creative)", "Configure {highlight}maxSteps{/highlight} to limit agentic iterations per request", 'Set {highlight}"tools": {"bash": false}{/highlight} to disable specific tools', - 'Use {highlight}"mcp_*": false{/highlight} to disable all tools from an MCP server', + 'Set {highlight}"mcp_*": false{/highlight} to disable all tools from an MCP server', "Override global tool settings per agent configuration", 'Set {highlight}"share": "auto"{/highlight} to automatically share all sessions', 'Set {highlight}"share": "disabled"{/highlight} to prevent any session sharing', diff --git a/packages/opencode/src/cli/cmd/tui/context/kv.tsx b/packages/opencode/src/cli/cmd/tui/context/kv.tsx index e0844ba5a..93f469afa 100644 --- a/packages/opencode/src/cli/cmd/tui/context/kv.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/kv.tsx @@ -25,6 +25,9 @@ export const { use: useKV, provider: KVProvider } = createSimpleContext({ get ready() { return ready() }, + get store() { + return kvStore + }, signal(name: string, defaultValue: T) { if (kvStore[name] === undefined) setKvStore(name, defaultValue) return [ diff --git a/packages/opencode/src/cli/cmd/tui/routes/home.tsx b/packages/opencode/src/cli/cmd/tui/routes/home.tsx index e5ce80efc..6b4ab3354 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/home.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/home.tsx @@ -3,7 +3,7 @@ import { createMemo, Match, onMount, Show, Switch } from "solid-js" import { useTheme } from "@tui/context/theme" import { useKeybind } from "@tui/context/keybind" import { Logo } from "../component/logo" -import { DidYouKnow, randomizeTip } from "../component/did-you-know" +import { Tips } from "../component/tips" import { Locale } from "@/util/locale" import { useSync } from "../context/sync" import { Toast } from "../ui/toast" @@ -77,7 +77,6 @@ export function Home() { let prompt: PromptRef const args = useArgs() onMount(() => { - randomizeTip() if (once) return if (route.initialPrompt) { prompt.set(route.initialPrompt) @@ -105,23 +104,13 @@ export function Home() { hint={Hint} /> - - - - - - + + + + - - - - {keybind.print("tips_toggle")} - Hide tips - - - {directory()}