diff options
| author | Adam <[email protected]> | 2026-01-15 13:32:15 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-19 10:55:57 -0600 |
| commit | 1f11a8a6ea46867e2ad199c987bf14696a1b91d8 (patch) | |
| tree | 64a1a83c5d576a9592229d67815e76359b399a03 /packages/ui/src/components | |
| parent | d5ae8e0bef991f2b2ad9766b9ae2f1c903badab3 (diff) | |
| download | opencode-1f11a8a6ea46867e2ad199c987bf14696a1b91d8.tar.gz opencode-1f11a8a6ea46867e2ad199c987bf14696a1b91d8.zip | |
feat(app): improved session layout
Diffstat (limited to 'packages/ui/src/components')
| -rw-r--r-- | packages/ui/src/components/hover-card.css | 5 | ||||
| -rw-r--r-- | packages/ui/src/components/message-nav.css | 4 | ||||
| -rw-r--r-- | packages/ui/src/components/message-nav.tsx | 24 | ||||
| -rw-r--r-- | packages/ui/src/components/session-message-rail.css | 44 | ||||
| -rw-r--r-- | packages/ui/src/components/session-message-rail.tsx | 46 |
5 files changed, 27 insertions, 96 deletions
diff --git a/packages/ui/src/components/hover-card.css b/packages/ui/src/components/hover-card.css index 43a26c98f..f1172dfc7 100644 --- a/packages/ui/src/components/hover-card.css +++ b/packages/ui/src/components/hover-card.css @@ -1,5 +1,7 @@ [data-slot="hover-card-trigger"] { - display: inline-flex; + display: flex; + width: 100%; + min-width: 0; } [data-component="hover-card-content"] { @@ -8,6 +10,7 @@ max-width: 320px; border-radius: var(--radius-md); background-color: var(--surface-raised-stronger-non-alpha); + pointer-events: auto; border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); background-clip: padding-box; diff --git a/packages/ui/src/components/message-nav.css b/packages/ui/src/components/message-nav.css index 465bd66fe..9c2116b90 100644 --- a/packages/ui/src/components/message-nav.css +++ b/packages/ui/src/components/message-nav.css @@ -10,6 +10,10 @@ width: 240px; gap: 4px; } + + &[data-size="compact"] { + width: 24px; + } } [data-slot="message-nav-item"] { diff --git a/packages/ui/src/components/message-nav.tsx b/packages/ui/src/components/message-nav.tsx index 7416cfd93..0dd7c42b0 100644 --- a/packages/ui/src/components/message-nav.tsx +++ b/packages/ui/src/components/message-nav.tsx @@ -9,9 +9,10 @@ export function MessageNav( current?: UserMessage size: "normal" | "compact" onMessageSelect: (message: UserMessage) => void + getLabel?: (message: UserMessage) => string | undefined }, ) { - const [local, others] = splitProps(props, ["messages", "current", "size", "onMessageSelect"]) + const [local, others] = splitProps(props, ["messages", "current", "size", "onMessageSelect", "getLabel"]) const content = () => ( <ul role="list" data-component="message-nav" data-size={local.size} {...others}> @@ -19,23 +20,36 @@ export function MessageNav( {(message) => { const handleClick = () => local.onMessageSelect(message) + const handleKeyPress = (event: KeyboardEvent) => { + if (event.key !== "Enter" && event.key !== " ") return + event.preventDefault() + local.onMessageSelect(message) + } + return ( <li data-slot="message-nav-item"> <Switch> <Match when={local.size === "compact"}> - <div data-slot="message-nav-tick-button" data-active={message.id === local.current?.id || undefined}> + <div + data-slot="message-nav-tick-button" + data-active={message.id === local.current?.id || undefined} + role="button" + tabindex={0} + onClick={handleClick} + onKeyDown={handleKeyPress} + > <div data-slot="message-nav-tick-line" /> </div> </Match> <Match when={local.size === "normal"}> - <button data-slot="message-nav-message-button" onClick={handleClick}> + <button data-slot="message-nav-message-button" onClick={handleClick} onKeyDown={handleKeyPress}> <DiffChanges changes={message.summary?.diffs ?? []} variant="bars" /> <div data-slot="message-nav-title-preview" data-active={message.id === local.current?.id || undefined} > - <Show when={message.summary?.title} fallback="New message"> - {message.summary?.title} + <Show when={local.getLabel?.(message) ?? message.summary?.title} fallback="New message"> + {local.getLabel?.(message) ?? message.summary?.title} </Show> </div> </button> diff --git a/packages/ui/src/components/session-message-rail.css b/packages/ui/src/components/session-message-rail.css deleted file mode 100644 index 9f248bed2..000000000 --- a/packages/ui/src/components/session-message-rail.css +++ /dev/null @@ -1,44 +0,0 @@ -[data-component="session-message-rail"] { - display: contents; -} - -[data-slot="session-message-rail-compact"], -[data-slot="session-message-rail-full"] { - position: absolute; - left: 1.5rem; - margin-top: 0.625rem; - top: 0; - bottom: 8rem; - overflow-y: auto; -} - -[data-slot="session-message-rail-compact"] { - display: flex; -} - -[data-slot="session-message-rail-full"] { - display: none; -} - -@container (min-width: 88rem) { - [data-slot="session-message-rail-compact"] { - display: none; - } - [data-slot="session-message-rail-full"] { - display: flex; - } -} - -[data-component="session-message-rail"] [data-slot="session-message-rail-full"] { - transform: none; -} - -[data-component="session-message-rail"][data-wide] [data-slot="session-message-rail-full"] { - margin-top: 0.125rem; - left: calc(((100% - min(100%, 50rem)) / 2) - 1.5rem); - transform: translateX(-100%); -} - -[data-component="session-message-rail"]:not([data-wide]) [data-slot="session-message-rail-full"] { - margin-top: 0.625rem; -} diff --git a/packages/ui/src/components/session-message-rail.tsx b/packages/ui/src/components/session-message-rail.tsx deleted file mode 100644 index 1935a4f93..000000000 --- a/packages/ui/src/components/session-message-rail.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { UserMessage } from "@opencode-ai/sdk/v2" -import { ComponentProps, Show, splitProps } from "solid-js" -import { MessageNav } from "./message-nav" -import "./session-message-rail.css" - -export interface SessionMessageRailProps extends ComponentProps<"div"> { - messages: UserMessage[] - current?: UserMessage - wide?: boolean - onMessageSelect: (message: UserMessage) => void -} - -export function SessionMessageRail(props: SessionMessageRailProps) { - const [local, others] = splitProps(props, ["messages", "current", "wide", "onMessageSelect", "class", "classList"]) - - return ( - <Show when={(local.messages?.length ?? 0) > 1}> - <div - {...others} - data-component="session-message-rail" - data-wide={local.wide ? "" : undefined} - classList={{ - ...(local.classList ?? {}), - [local.class ?? ""]: !!local.class, - }} - > - <div data-slot="session-message-rail-compact"> - <MessageNav - messages={local.messages} - current={local.current} - onMessageSelect={local.onMessageSelect} - size="compact" - /> - </div> - <div data-slot="session-message-rail-full"> - <MessageNav - messages={local.messages} - current={local.current} - onMessageSelect={local.onMessageSelect} - size={local.wide ? "normal" : "compact"} - /> - </div> - </div> - </Show> - ) -} |
