summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-11-24 14:52:32 -0600
committerAdam <[email protected]>2025-11-24 15:10:40 -0600
commitc60cb6c329dd52a6b8a3f80eda9000d528398228 (patch)
tree2410ab91405a7273692ca2f0ecd507f098ebcccb
parentacf1dd85006a0bb4009ef601ae7f7a60eb36af4d (diff)
downloadopencode-c60cb6c329dd52a6b8a3f80eda9000d528398228.tar.gz
opencode-c60cb6c329dd52a6b8a3f80eda9000d528398228.zip
wip(share): more styling
-rw-r--r--packages/enterprise/src/routes/share/[sessionID].tsx58
-rw-r--r--packages/ui/src/components/message-nav.tsx7
-rw-r--r--packages/ui/src/components/tabs.tsx18
3 files changed, 73 insertions, 10 deletions
diff --git a/packages/enterprise/src/routes/share/[sessionID].tsx b/packages/enterprise/src/routes/share/[sessionID].tsx
index 96a651391..e34cbcc7e 100644
--- a/packages/enterprise/src/routes/share/[sessionID].tsx
+++ b/packages/enterprise/src/routes/share/[sessionID].tsx
@@ -3,7 +3,7 @@ import { SessionTurn } from "@opencode-ai/ui/session-turn"
import { SessionReview } from "@opencode-ai/ui/session-review"
import { DataProvider } from "@opencode-ai/ui/context"
import { createAsync, query, RouteDefinition, useParams } from "@solidjs/router"
-import { createMemo, ErrorBoundary, Show } from "solid-js"
+import { createMemo, ErrorBoundary, For, Match, Show, Switch } from "solid-js"
import { Share } from "~/core/share"
import { Logo, Mark } from "@opencode-ai/ui/logo"
import { IconButton } from "@opencode-ai/ui/icon-button"
@@ -15,6 +15,7 @@ import { MessageNav } from "@opencode-ai/ui/message-nav"
import { createStore } from "solid-js/store"
import z from "zod"
import NotFound from "../[...404]"
+import { Tabs } from "@opencode-ai/ui/tabs"
const SessionDataMissingError = NamedError.create(
"SessionDataMissingError",
@@ -140,7 +141,7 @@ export default function () {
const model = createMemo(() => data().model[params.sessionID!]?.find((m) => m.id === modelID()))
const diffs = createMemo(() => data().session_diff[params.sessionID!] ?? [])
- const title = (
+ const title = () => (
<div class="flex flex-col gap-4 shrink-0">
<div class="h-8 flex gap-4 items-center justify-start self-stretch">
<div class="pl-[2.5px] pr-2 flex items-center gap-1.75 bg-surface-strong shadow-xs-border-base">
@@ -159,6 +160,30 @@ export default function () {
</div>
)
+ const turns = () => (
+ <div class="relative mt-2 pt-6 pb-8 px-4 min-w-0 w-full h-full overflow-y-auto no-scrollbar">
+ {title()}
+ <div class="flex flex-col gap-15 items-start justify-start mt-4">
+ <For each={messages()}>
+ {(message) => (
+ <SessionTurn
+ sessionID={params.sessionID!}
+ messageID={message.id}
+ classes={{
+ root: "min-w-0 w-full relative",
+ content:
+ "flex flex-col justify-between !overflow-visible [&_[data-slot=session-turn-message-header]]:top-[-32px]",
+ }}
+ />
+ )}
+ </For>
+ </div>
+ <div class="flex items-center justify-center pt-20 pb-8 shrink-0">
+ <Logo class="w-58.5 opacity-12" />
+ </div>
+ </div>
+ )
+
return (
<div class="relative bg-background-stronger w-screen h-screen overflow-hidden flex flex-col">
<header class="h-12 px-6 py-2 flex items-center justify-between self-stretch bg-background-base border-b border-border-weak-base">
@@ -185,7 +210,7 @@ export default function () {
</div>
</header>
<div class="select-text flex flex-col flex-1 min-h-0">
- <div class="w-full flex-1 min-h-0 flex">
+ <div class="hidden md:flex w-full flex-1 min-h-0">
<div
classList={{
"@container relative shrink-0 pt-14 flex flex-col gap-10 min-h-0 w-full mx-auto": true,
@@ -193,7 +218,7 @@ export default function () {
"px-6 max-w-2xl": diffs().length === 0,
}}
>
- {title}
+ {title()}
<div class="flex items-start justify-start h-full min-h-0">
<Show when={messages().length > 1}>
<>
@@ -252,6 +277,31 @@ export default function () {
</div>
</Show>
</div>
+ <Switch>
+ <Match when={diffs().length}>
+ <Tabs class="md:hidden">
+ <Tabs.List>
+ <Tabs.Trigger value="session" class="w-1/2" classes={{ button: "w-full" }}>
+ Session
+ </Tabs.Trigger>
+ <Tabs.Trigger value="review" class="w-1/2" classes={{ button: "w-full" }}>
+ 5 Files Changed
+ </Tabs.Trigger>
+ </Tabs.List>
+ <Tabs.Content value="session" class="!overflow-hidden">
+ {turns()}
+ </Tabs.Content>
+ <Tabs.Content value="review" class="!overflow-hidden">
+ <div class="relative px-4 pt-8 h-full overflow-y-auto no-scrollbar">
+ <SessionReview diffs={diffs()} class="pb-20" />
+ </div>
+ </Tabs.Content>
+ </Tabs>
+ </Match>
+ <Match when={true}>
+ <div class="md:hidden !overflow-hidden">{turns()}</div>
+ </Match>
+ </Switch>
</div>
</div>
)
diff --git a/packages/ui/src/components/message-nav.tsx b/packages/ui/src/components/message-nav.tsx
index 333ad3743..9d56ce1a6 100644
--- a/packages/ui/src/components/message-nav.tsx
+++ b/packages/ui/src/components/message-nav.tsx
@@ -2,7 +2,6 @@ import { UserMessage } from "@opencode-ai/sdk"
import { ComponentProps, createMemo, For, Match, Show, splitProps, Switch } from "solid-js"
import { DiffChanges } from "./diff-changes"
import { Spinner } from "./spinner"
-import { HoverCard } from "@kobalte/core/hover-card"
import { Tooltip } from "@kobalte/core/tooltip"
export function MessageNav(
@@ -19,7 +18,7 @@ export function MessageNav(
return local.messages?.at(0)
})
- const content = (
+ const content = () => (
<ul role="list" data-component="message-nav" data-size={local.size} {...others}>
<For each={local.messages}>
{(message) => {
@@ -66,7 +65,7 @@ export function MessageNav(
<Switch>
<Match when={local.size === "compact"}>
<Tooltip openDelay={0} closeDelay={0} placement="top-start" gutter={-65} shift={-16} overlap>
- <Tooltip.Trigger as="div">{content}</Tooltip.Trigger>
+ <Tooltip.Trigger as="div">{content()}</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content data-slot="message-nav-tooltip">
<div data-slot="message-nav-tooltip-content">
@@ -76,7 +75,7 @@ export function MessageNav(
</Tooltip.Portal>
</Tooltip>
</Match>
- <Match when={local.size === "normal"}>{content}</Match>
+ <Match when={local.size === "normal"}>{content()}</Match>
</Switch>
)
}
diff --git a/packages/ui/src/components/tabs.tsx b/packages/ui/src/components/tabs.tsx
index e3363bdd5..68acd88d4 100644
--- a/packages/ui/src/components/tabs.tsx
+++ b/packages/ui/src/components/tabs.tsx
@@ -5,6 +5,9 @@ import type { ComponentProps, ParentProps } from "solid-js"
export interface TabsProps extends ComponentProps<typeof Kobalte> {}
export interface TabsListProps extends ComponentProps<typeof Kobalte.List> {}
export interface TabsTriggerProps extends ComponentProps<typeof Kobalte.Trigger> {
+ classes?: {
+ button?: string
+ }
hideCloseButton?: boolean
closeButton?: JSX.Element
}
@@ -39,7 +42,14 @@ function TabsList(props: TabsListProps) {
}
function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
- const [split, rest] = splitProps(props, ["class", "classList", "children", "closeButton", "hideCloseButton"])
+ const [split, rest] = splitProps(props, [
+ "class",
+ "classList",
+ "classes",
+ "children",
+ "closeButton",
+ "hideCloseButton",
+ ])
return (
<div
data-slot="tabs-tabs-trigger-wrapper"
@@ -48,7 +58,11 @@ function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
[split.class ?? ""]: !!split.class,
}}
>
- <Kobalte.Trigger {...rest} data-slot="tabs-tabs-trigger" class="group/tab">
+ <Kobalte.Trigger
+ {...rest}
+ data-slot="tabs-tabs-trigger"
+ classList={{ "group/tab": true, [split.classes?.button ?? ""]: split.classes?.button }}
+ >
{split.children}
</Kobalte.Trigger>
<Show when={split.closeButton}>