Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions packages/opencode/src/cli/cmd/tui/component/logo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TextAttributes, RGBA } from "@opentui/core"
import { For, type JSX } from "solid-js"
import { For, Show, createMemo, type JSX } from "solid-js"
import { useTerminalDimensions } from "@opentui/solid"
import { useTheme, tint } from "@tui/context/theme"

// Shadow markers (rendered chars in parens):
Expand All @@ -12,8 +13,14 @@ const LOGO_LEFT = [` `, `█▀▀█ █▀▀█ █▀▀

const LOGO_RIGHT = [` ▄ `, `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`, `█___ █__█ █__█ █^^^`, `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`]

// 19 (LOGO_LEFT) + 1 (gap) + 19 (LOGO_RIGHT) + 3 (padding) = 42
const LOGO_MIN_WIDTH = 42

export function Logo() {
const { theme } = useTheme()
const dimensions = useTerminalDimensions()

const showLogo = createMemo(() => dimensions().width >= LOGO_MIN_WIDTH)

const renderLine = (line: string, fg: RGBA, bold: boolean): JSX.Element[] => {
const shadow = tint(theme.background, fg, 0.25)
Expand Down Expand Up @@ -74,15 +81,17 @@ export function Logo() {
}

return (
<box>
<For each={LOGO_LEFT}>
{(line, index) => (
<box flexDirection="row" gap={1}>
<box flexDirection="row">{renderLine(line, theme.textMuted, false)}</box>
<box flexDirection="row">{renderLine(LOGO_RIGHT[index()], theme.text, true)}</box>
</box>
)}
</For>
</box>
<Show when={showLogo()}>
<box>
<For each={LOGO_LEFT}>
{(line, index) => (
<box flexDirection="row" gap={1}>
<box flexDirection="row">{renderLine(line, theme.textMuted, false)}</box>
<box flexDirection="row">{renderLine(LOGO_RIGHT[index()], theme.text, true)}</box>
</box>
)}
</For>
</box>
</Show>
)
}
26 changes: 18 additions & 8 deletions packages/opencode/src/cli/cmd/tui/routes/home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Prompt, type PromptRef } from "@tui/component/prompt"
import { createMemo, Match, onMount, Show, Switch } from "solid-js"
import { useTerminalDimensions } from "@opentui/solid"
import { useTheme } from "@tui/context/theme"
import { useKeybind } from "@tui/context/keybind"
import { Logo } from "../component/logo"
Expand All @@ -18,13 +19,18 @@ import { useCommandDialog } from "../component/dialog-command"
// TODO: what is the best way to do this?
let once = false

const MIN_HEIGHT_FOR_LOGO = 20
const MIN_HEIGHT_FOR_TIPS = 16

export function Home() {
const sync = useSync()
const kv = useKV()
const { theme } = useTheme()
const route = useRouteData("home")
const promptRef = usePromptRef()
const command = useCommandDialog()
const dimensions = useTerminalDimensions()
const isCompact = createMemo(() => dimensions().height < MIN_HEIGHT_FOR_LOGO)
const mcp = createMemo(() => Object.keys(sync.data.mcp).length > 0)
const mcpError = createMemo(() => {
return Object.values(sync.data.mcp).some((x) => x.status === "failed")
Expand All @@ -37,8 +43,8 @@ export function Home() {
const isFirstTimeUser = createMemo(() => sync.data.session.length === 0)
const tipsHidden = createMemo(() => kv.get("tips_hidden", false))
const showTips = createMemo(() => {
// Don't show tips for first-time users
if (isFirstTimeUser()) return false
if (dimensions().height < MIN_HEIGHT_FOR_TIPS) return false
return !tipsHidden()
})

Expand Down Expand Up @@ -94,9 +100,13 @@ export function Home() {
return (
<>
<box flexGrow={1} justifyContent="center" alignItems="center" paddingLeft={2} paddingRight={2} gap={1}>
<box height={3} />
<Logo />
<box width="100%" maxWidth={75} zIndex={1000} paddingTop={1}>
<Show when={!isCompact()}>
<box height={3} />
</Show>
<Show when={!isCompact()}>
<Logo />
</Show>
<box width="100%" maxWidth={75} zIndex={1000} paddingTop={isCompact() ? 0 : 1}>
<Prompt
ref={(r) => {
prompt = r
Expand All @@ -105,11 +115,11 @@ export function Home() {
hint={Hint}
/>
</box>
<box height={3} width="100%" maxWidth={75} alignItems="center" paddingTop={2}>
<Show when={showTips()}>
<Show when={showTips()}>
<box height={3} width="100%" maxWidth={75} alignItems="center" paddingTop={2}>
<Tips />
</Show>
</box>
</box>
</Show>
<Toast />
</box>
<box paddingTop={1} paddingBottom={1} paddingLeft={2} paddingRight={2} flexDirection="row" flexShrink={0} gap={2}>
Expand Down