diff options
| author | Dax Raad <[email protected]> | 2026-01-12 09:42:28 -0500 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2026-01-12 09:42:28 -0500 |
| commit | 547a975707c16253edf03c2d6ec30f8e499c83ad (patch) | |
| tree | 85f5d167ebdab6759ffd2c498b6ac8f2a10f3c33 | |
| parent | c009cab15b0590aeadb5030661af348bae75b1ea (diff) | |
| download | opencode-547a975707c16253edf03c2d6ec30f8e499c83ad.tar.gz opencode-547a975707c16253edf03c2d6ec30f8e499c83ad.zip | |
tui: redesign tips display on home screen
| -rw-r--r-- | packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx | 51 | ||||
| -rw-r--r-- | packages/opencode/src/cli/cmd/tui/component/tips.tsx (renamed from packages/opencode/src/cli/cmd/tui/component/tips.ts) | 51 | ||||
| -rw-r--r-- | packages/opencode/src/cli/cmd/tui/context/kv.tsx | 3 | ||||
| -rw-r--r-- | packages/opencode/src/cli/cmd/tui/routes/home.tsx | 21 |
4 files changed, 57 insertions, 69 deletions
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 ( - <box flexDirection="row" maxWidth="100%"> - <text flexShrink={0} style={{ fg: theme.warning }}> - ● Tip{" "} - </text> - <text flexShrink={1}> - <For each={tipParts()}> - {(part) => <span style={{ fg: part.highlight ? theme.text : theme.textMuted }}>{part.text}</span>} - </For> - </text> - </box> - ) -} diff --git a/packages/opencode/src/cli/cmd/tui/component/tips.ts b/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 ( + <box flexDirection="row" maxWidth="100%"> + <text flexShrink={0} style={{ fg: theme.warning }}> + ● Tip{" "} + </text> + <text flexShrink={1}> + <For each={parts}> + {(part) => <span style={{ fg: part.highlight ? theme.text : theme.textMuted }}>{part.text}</span>} + </For> + </text> + </box> + ) +} + +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<T>(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} /> </box> - <Show when={!isFirstTimeUser()}> - <Show when={showTips()}> - <box width="100%" maxWidth={75} paddingTop={3} alignItems="center"> - <DidYouKnow /> - </box> - </Show> + <Show when={showTips()}> + <box width="100%" maxWidth={75} paddingTop={2} alignItems="center"> + <Tips /> + </box> </Show> <Toast /> </box> - <Show when={showTips()}> - <box position="absolute" bottom={2} right={2}> - <text> - <span style={{ fg: theme.text }}>{keybind.print("tips_toggle")}</span> - <span style={{ fg: theme.textMuted }}> Hide tips</span> - </text> - </box> - </Show> <box paddingTop={1} paddingBottom={1} paddingLeft={2} paddingRight={2} flexDirection="row" flexShrink={0} gap={2}> <text fg={theme.textMuted}>{directory()}</text> <box gap={1} flexDirection="row" flexShrink={0}> |
