summaryrefslogtreecommitdiffhomepage
path: root/packages/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'packages/desktop')
-rw-r--r--packages/desktop/package.json4
-rw-r--r--packages/desktop/src/components/prompt-input.tsx2
-rw-r--r--packages/desktop/src/components/session-list.tsx38
-rw-r--r--packages/desktop/src/context/sync.tsx5
-rw-r--r--packages/desktop/src/index.css2
-rw-r--r--packages/desktop/src/pages/index.tsx48
6 files changed, 48 insertions, 51 deletions
diff --git a/packages/desktop/package.json b/packages/desktop/package.json
index b399d616f..523242f19 100644
--- a/packages/desktop/package.json
+++ b/packages/desktop/package.json
@@ -42,9 +42,9 @@
"remeda": "catalog:",
"solid-js": "catalog:",
"shiki": "3.9.2",
- "solid-list": "0.3.0",
+ "solid-list": "catalog:",
"tailwindcss": "catalog:",
- "virtua": "0.42.3"
+ "virtua": "catalog:"
},
"prettier": {
"semi": false,
diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx
index 48d238401..0f8fb5930 100644
--- a/packages/desktop/src/components/prompt-input.tsx
+++ b/packages/desktop/src/components/prompt-input.tsx
@@ -187,7 +187,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
return (
<div
classList={{
- "size-full max-w-xl bg-surface-base border border-border-base": true,
+ "size-full max-w-xl bg-surface-raised-stronger-non-alpha border border-border-strong-base": true,
"rounded-2xl overflow-clip focus-within:shadow-xs-border-selected": true,
[props.class ?? ""]: !!props.class,
}}
diff --git a/packages/desktop/src/components/session-list.tsx b/packages/desktop/src/components/session-list.tsx
deleted file mode 100644
index f26d39af8..000000000
--- a/packages/desktop/src/components/session-list.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { useSync, useLocal } from "@/context"
-import { Tooltip } from "@opencode-ai/ui"
-import { DateTime } from "luxon"
-import { VList } from "virtua/solid"
-
-export default function SessionList() {
- const sync = useSync()
- const local = useLocal()
- return (
- <VList data={sync.data.session} class="no-scrollbar p-3">
- {(session) => (
- <Tooltip placement="right" value={session.title} class="w-full min-w-0">
- <button
- data-active={local.session.active()?.id === session.id}
- class="group w-full min-w-0 text-left truncate justify-start text-xs my-0.5 cursor-pointer
- flex flex-col gap-1 rounded-md p-2 border-[0.5px] border-transparent
- hover:not-data-[active=true]:bg-background-panel
- data-[active=true]:bg-background-element data-[active=true]:border-border-subtle"
- onClick={() => local.session.setActive(session.id)}
- >
- <div class="flex gap-1 items-center">
- <div
- classList={{
- "text-text/80 min-w-0 grow truncate": true,
- "group-data-[active=true]:text-text!": true,
- }}
- >
- {session.title}
- </div>
- <div class="shrink-0 text-text-muted/60">{DateTime.fromMillis(session.time.updated).toRelative()}</div>
- </div>
- <span class="text-text-muted truncate">{session.share?.url}</span>
- </button>
- </Tooltip>
- )}
- </VList>
- )
-}
diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx
index 5d64f3ee7..5ba6b1af2 100644
--- a/packages/desktop/src/context/sync.tsx
+++ b/packages/desktop/src/context/sync.tsx
@@ -1,4 +1,4 @@
-import type { Message, Agent, Provider, Session, Part, Config, Path, File, FileNode } from "@opencode-ai/sdk"
+import type { Message, Agent, Provider, Session, Part, Config, Path, File, FileNode, Project } from "@opencode-ai/sdk"
import { createStore, produce, reconcile } from "solid-js/store"
import { createContext, createMemo, Show, useContext, type ParentProps } from "solid-js"
import { useSDK, useEvent } from "@/context"
@@ -9,6 +9,7 @@ function init() {
ready: boolean
provider: Provider[]
agent: Agent[]
+ project: Project
config: Config
path: Path
session: Session[]
@@ -21,6 +22,7 @@ function init() {
node: FileNode[]
changes: File[]
}>({
+ project: { id: "", worktree: "", time: { created: 0, initialized: 0 } },
config: {},
path: { state: "", config: "", worktree: "", directory: "" },
ready: false,
@@ -96,6 +98,7 @@ function init() {
const sdk = useSDK()
const load = {
+ project: () => sdk.project.current().then((x) => setStore("project", x.data!)),
provider: () => sdk.config.providers().then((x) => setStore("provider", x.data!.providers)),
path: () => sdk.path.get().then((x) => setStore("path", x.data!)),
agent: () => sdk.app.agents().then((x) => setStore("agent", x.data ?? [])),
diff --git a/packages/desktop/src/index.css b/packages/desktop/src/index.css
index b4717a4e8..4af87bca6 100644
--- a/packages/desktop/src/index.css
+++ b/packages/desktop/src/index.css
@@ -1 +1 @@
-@import "@opencode-ai/css/tailwind.css";
+@import "@opencode-ai/ui/styles/tailwind";
diff --git a/packages/desktop/src/pages/index.tsx b/packages/desktop/src/pages/index.tsx
index 1174f1e16..4133887c9 100644
--- a/packages/desktop/src/pages/index.tsx
+++ b/packages/desktop/src/pages/index.tsx
@@ -1,4 +1,4 @@
-import { Icon, Tooltip } from "@opencode-ai/ui"
+import { Button, Icon, List, Tooltip } from "@opencode-ai/ui"
import { FileIcon, IconButton } from "@/ui"
import FileTree from "@/components/file-tree"
import EditorPane from "@/components/editor-pane"
@@ -6,12 +6,12 @@ import { For, Match, onCleanup, onMount, Show, Switch } from "solid-js"
import { SelectDialog } from "@/components/select-dialog"
import { useSync, useSDK, useLocal } from "@/context"
import type { LocalFile, TextSelection } from "@/context/local"
-import SessionList from "@/components/session-list"
import SessionTimeline from "@/components/session-timeline"
-import PromptForm, { type PromptContentPart, type PromptSubmitValue } from "@/components/prompt-form"
+import { type PromptContentPart, type PromptSubmitValue } from "@/components/prompt-form"
import { createStore } from "solid-js/store"
import { getDirectory, getFilename } from "@/utils"
import { PromptInput } from "@/components/prompt-input"
+import { DateTime } from "luxon"
export default function Page() {
const local = useLocal()
@@ -225,13 +225,45 @@ export default function Page() {
)
return (
- <div class="relative h-screen flex flex-col bg-background-weak">
- <header class="hidden h-12 shrink-0 bg-background-base border-b border-border-weak-base"></header>
+ <div class="relative h-screen flex flex-col">
+ <header class="hidden h-12 shrink-0 bg-background-strong border-b border-border-weak-base"></header>
<main class="h-[calc(100vh-0rem)] flex">
- <div class="shrink-0 w-70">
- <SessionList />
+ <div class="shrink-0 w-70 p-1.5 bg-background-weak border-r border-border-weak-base flex flex-col items-start gap-1.5">
+ <div class="flex flex-col items-start self-stretch px-3 py-1">
+ <span class="text-12-medium overflow-hidden text-ellipsis">{sync.data.path.directory}</span>
+ </div>
+ <div class="flex flex-col items-start gap-4 self-stretch flex-1">
+ <div class="px-3 py-1.5 w-full">
+ <Button class="w-full" size="large">
+ New Session
+ </Button>
+ </div>
+ <List data={sync.data.session} key={(x) => x.id} onSelect={(s) => local.session.setActive(s?.id)}>
+ {(session) => (
+ <Tooltip placement="right" value={session.title}>
+ <div>
+ <div class="flex items-center self-stretch gap-6">
+ <span class="text-14-regular text-text-strong overflow-hidden text-ellipsis truncate">
+ {session.title}
+ </span>
+ <span class="text-12-regular text-text-weak text-right whitespace-nowrap">
+ {DateTime.fromMillis(session.time.updated).toRelative()}
+ </span>
+ </div>
+ <div class="flex justify-between items-center self-stretch">
+ <span class="text-12-regular text-text-weak">2 files changed</span>
+ <div class="flex gap-2 justify-end items-center">
+ <span class="text-12-mono text-right text-text-diff-add-base">+43</span>
+ <span class="text-12-mono text-right text-text-diff-delete-base">-2</span>
+ </div>
+ </div>
+ </div>
+ </Tooltip>
+ )}
+ </List>
+ </div>
</div>
- <div class="relative grid grid-cols-2">
+ <div class="relative grid grid-cols-2 bg-background-base">
<div class="min-w-0 overflow-y-auto no-scrollbar flex justify-center">
<Show when={local.session.active()}>
{(activeSession) => <SessionTimeline session={activeSession().id} class="w-full" />}