|
1 | | -import { Show } from "solid-js" |
| 1 | +import { Show, createMemo } from "solid-js" |
2 | 2 | import { TextAttributes } from "@opentui/core" |
| 3 | +import { useTerminalDimensions } from "@opentui/solid" |
3 | 4 | import { useTheme } from "../context/theme" |
4 | 5 | import { Logo } from "./logo" |
5 | 6 | import { InstallationVersion } from "@opencode-ai/core/installation/version" |
6 | 7 | import { useReady } from "./altimate-onboarding" |
| 8 | +import { welcomePanelVariant } from "./welcome-panel-utils" |
7 | 9 |
|
8 | | -// altimate_change — Claude-Code-style full-width boot box: big block wordmark on |
9 | | -// the left and a single "What is Altimate Code" section on the right. Shared |
10 | | -// between the home route and the session view so the header stays consistent |
11 | | -// when a command (e.g. /discover) starts a session. zIndex keeps it above |
12 | | -// transient top toasts (update/MCP) that would otherwise blank its top rows. |
| 10 | +// altimate_change — Claude-Code-style boot box: "What is Altimate Code" plus the |
| 11 | +// readiness-aware CTA. Shared between the home route and the session view so the |
| 12 | +// header stays consistent when a command (e.g. /discover) starts a session. |
| 13 | +// zIndex keeps it above transient top toasts (update/MCP) that would otherwise |
| 14 | +// blank its top rows. |
| 15 | +// |
| 16 | +// Responsive (issue #1067): the full two-column boot box with the block wordmark |
| 17 | +// is ~65 cols wide and ~8 rows tall, which eats half a small terminal. So it |
| 18 | +// scales down by terminal size, following the repo's breakpoint idiom |
| 19 | +// (createMemo on useTerminalDimensions, e.g. routes/session/permission.tsx, |
| 20 | +// component/upgrade-indicator.tsx). Both axes matter — the wordmark is wide AND |
| 21 | +// tall: |
| 22 | +// full — wordmark + full description (large terminals) |
| 23 | +// medium — title + one condensed line, no wordmark |
| 24 | +// compact — a single line; the border title already shows the version |
13 | 25 | export function WelcomePanel() { |
14 | 26 | const { theme } = useTheme() |
15 | 27 | const ready = useReady() |
| 28 | + const dimensions = useTerminalDimensions() |
| 29 | + |
| 30 | + const variant = createMemo(() => welcomePanelVariant(dimensions().width, dimensions().height)) |
| 31 | + const compact = createMemo(() => variant() === "compact") |
| 32 | + const medium = createMemo(() => variant() === "medium") |
| 33 | + const full = createMemo(() => variant() === "full") |
| 34 | + |
| 35 | + const title = InstallationVersion === "local" ? " Altimate Code " : ` Altimate Code v${InstallationVersion} ` |
| 36 | + |
16 | 37 | return ( |
17 | 38 | <box |
18 | 39 | border |
19 | 40 | borderStyle="rounded" |
20 | 41 | borderColor={theme.border} |
21 | | - title={InstallationVersion === "local" ? " Altimate Code " : ` Altimate Code v${InstallationVersion} `} |
| 42 | + title={title} |
22 | 43 | titleAlignment="left" |
23 | 44 | flexShrink={0} |
24 | 45 | width="100%" |
25 | 46 | zIndex={2000} |
26 | 47 | backgroundColor={theme.background} |
27 | | - flexDirection="row" |
| 48 | + flexDirection="column" |
28 | 49 | > |
29 | | - {/* left column — the block-letter wordmark (59 cols wide) */} |
30 | | - <box |
31 | | - width={65} |
32 | | - flexShrink={0} |
33 | | - alignItems="center" |
34 | | - justifyContent="center" |
35 | | - gap={1} |
36 | | - paddingTop={1} |
37 | | - paddingBottom={1} |
38 | | - paddingLeft={1} |
39 | | - > |
40 | | - <text fg={theme.text} attributes={TextAttributes.BOLD}> |
41 | | - Welcome to Altimate Code |
42 | | - </text> |
43 | | - <Logo /> |
44 | | - </box> |
45 | | - {/* right column — tips + what-is sections */} |
46 | | - <box |
47 | | - flexGrow={1} |
48 | | - border={["left"]} |
49 | | - borderColor={theme.border} |
50 | | - paddingLeft={2} |
51 | | - paddingRight={2} |
52 | | - paddingTop={1} |
53 | | - paddingBottom={1} |
54 | | - gap={1} |
55 | | - > |
56 | | - <box gap={0}> |
57 | | - <text fg={theme.accent} attributes={TextAttributes.BOLD}> |
58 | | - What is Altimate Code |
| 50 | + {/* compact — one line; the border title already carries the version */} |
| 51 | + <Show when={compact()}> |
| 52 | + <box paddingLeft={2} paddingRight={2} width="100%"> |
| 53 | + <text fg={ready() ? theme.text : theme.primary} wrapMode="word" width="100%"> |
| 54 | + {ready() ? "Your data-aware AI harness." : "Connect your AI model to start."} |
59 | 55 | </text> |
60 | | - <text fg={theme.text} wrapMode="word" width="100%"> |
61 | | - Altimate Code is a specialized data engineering harness that sits between any LLM and your entire data |
62 | | - stack. |
| 56 | + </box> |
| 57 | + </Show> |
| 58 | + |
| 59 | + {/* medium — title + one condensed description + CTA, no block wordmark */} |
| 60 | + <Show when={medium()}> |
| 61 | + <box paddingLeft={2} paddingRight={2} paddingTop={1} paddingBottom={1} gap={0} width="100%"> |
| 62 | + <text fg={theme.text} attributes={TextAttributes.BOLD}> |
| 63 | + Welcome to Altimate Code |
63 | 64 | </text> |
64 | 65 | <text fg={theme.text} wrapMode="word" width="100%"> |
65 | | - It gives your AI real context — column-level lineage, SQL analysis, dbt, and live warehouse metadata — so it |
66 | | - reasons about your data instead of guessing. |
| 66 | + A data-engineering harness that gives your AI real context — column-level lineage, SQL analysis, dbt, and |
| 67 | + live warehouse metadata. |
67 | 68 | </text> |
68 | | - {/* CTA only until a model is connected — stale afterwards */} |
69 | 69 | <Show when={!ready()}> |
70 | 70 | <text fg={theme.primary} wrapMode="word" width="100%"> |
71 | 71 | Connect your AI model to start. |
72 | 72 | </text> |
73 | 73 | </Show> |
74 | 74 | </box> |
75 | | - </box> |
| 75 | + </Show> |
| 76 | + |
| 77 | + {/* full — the original two-column boot box */} |
| 78 | + <Show when={full()}> |
| 79 | + <box flexDirection="row" width="100%"> |
| 80 | + {/* left column — the block-letter wordmark */} |
| 81 | + <box |
| 82 | + width={65} |
| 83 | + flexShrink={0} |
| 84 | + alignItems="center" |
| 85 | + justifyContent="center" |
| 86 | + gap={1} |
| 87 | + paddingTop={1} |
| 88 | + paddingBottom={1} |
| 89 | + paddingLeft={1} |
| 90 | + > |
| 91 | + <text fg={theme.text} attributes={TextAttributes.BOLD}> |
| 92 | + Welcome to Altimate Code |
| 93 | + </text> |
| 94 | + <Logo /> |
| 95 | + </box> |
| 96 | + {/* right column — what-is section */} |
| 97 | + <box |
| 98 | + flexGrow={1} |
| 99 | + border={["left"]} |
| 100 | + borderColor={theme.border} |
| 101 | + paddingLeft={2} |
| 102 | + paddingRight={2} |
| 103 | + paddingTop={1} |
| 104 | + paddingBottom={1} |
| 105 | + gap={1} |
| 106 | + > |
| 107 | + <box gap={0}> |
| 108 | + <text fg={theme.accent} attributes={TextAttributes.BOLD}> |
| 109 | + What is Altimate Code |
| 110 | + </text> |
| 111 | + <text fg={theme.text} wrapMode="word" width="100%"> |
| 112 | + Altimate Code is a specialized data engineering harness that sits between any LLM and your entire data |
| 113 | + stack. |
| 114 | + </text> |
| 115 | + <text fg={theme.text} wrapMode="word" width="100%"> |
| 116 | + It gives your AI real context — column-level lineage, SQL analysis, dbt, and live warehouse metadata — |
| 117 | + so it reasons about your data instead of guessing. |
| 118 | + </text> |
| 119 | + {/* CTA only until a model is connected — stale afterwards */} |
| 120 | + <Show when={!ready()}> |
| 121 | + <text fg={theme.primary} wrapMode="word" width="100%"> |
| 122 | + Connect your AI model to start. |
| 123 | + </text> |
| 124 | + </Show> |
| 125 | + </box> |
| 126 | + </box> |
| 127 | + </box> |
| 128 | + </Show> |
76 | 129 | </box> |
77 | 130 | ) |
78 | 131 | } |
0 commit comments