summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/desktop/src/context/layout.tsx52
-rw-r--r--packages/desktop/src/context/local.tsx47
-rw-r--r--packages/desktop/src/context/sdk.tsx15
-rw-r--r--packages/desktop/src/context/session.tsx6
-rw-r--r--packages/desktop/src/context/sync.tsx2
-rw-r--r--packages/desktop/src/index.tsx6
-rw-r--r--packages/desktop/src/pages/layout.tsx82
-rw-r--r--packages/desktop/src/pages/session-layout.tsx16
-rw-r--r--packages/desktop/src/pages/session.tsx49
-rw-r--r--packages/desktop/src/ui/file-icon.tsx3
-rw-r--r--packages/sdk/js/src/client.ts12
-rw-r--r--packages/ui/src/components/button.css42
-rw-r--r--packages/ui/src/components/icon-button.css41
-rw-r--r--packages/ui/src/components/icon.tsx4
-rw-r--r--packages/ui/src/components/index.ts1
-rw-r--r--packages/ui/src/components/logo.css4
-rw-r--r--packages/ui/src/components/logo.tsx14
-rw-r--r--packages/ui/src/styles/index.css1
18 files changed, 257 insertions, 140 deletions
diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx
new file mode 100644
index 000000000..9e4af90aa
--- /dev/null
+++ b/packages/desktop/src/context/layout.tsx
@@ -0,0 +1,52 @@
+import { createStore } from "solid-js/store"
+import { createMemo } from "solid-js"
+import { createSimpleContext } from "./helper"
+import { makePersisted } from "@solid-primitives/storage"
+
+export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({
+ name: "Layout",
+ init: () => {
+ const [store, setStore] = makePersisted(
+ createStore({
+ sidebar: {
+ opened: true,
+ width: 280,
+ },
+ review: {
+ state: "pane" as "pane" | "tab",
+ },
+ }),
+ {
+ name: "__default-layout",
+ },
+ )
+
+ return {
+ sidebar: {
+ opened: createMemo(() => store.sidebar.opened),
+ open() {
+ setStore("sidebar", "opened", true)
+ },
+ close() {
+ setStore("sidebar", "opened", false)
+ },
+ toggle() {
+ setStore("sidebar", "opened", (x) => !x)
+ },
+ width: createMemo(() => store.sidebar.width),
+ resize(width: number) {
+ setStore("sidebar", "width", width)
+ },
+ },
+ review: {
+ state: createMemo(() => store.review?.state ?? "closed"),
+ pane() {
+ setStore("review", "state", "pane")
+ },
+ tab() {
+ setStore("review", "state", "tab")
+ },
+ },
+ }
+ },
+})
diff --git a/packages/desktop/src/context/local.tsx b/packages/desktop/src/context/local.tsx
index 1cef1c9f1..cef6c5555 100644
--- a/packages/desktop/src/context/local.tsx
+++ b/packages/desktop/src/context/local.tsx
@@ -5,7 +5,6 @@ import type { FileContent, FileNode, Model, Provider, File as FileStatus } from
import { createSimpleContext } from "./helper"
import { useSDK } from "./sdk"
import { useSync } from "./sync"
-import { makePersisted } from "@solid-primitives/storage"
export type LocalFile = FileNode &
Partial<{
@@ -457,57 +456,11 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
}
})()
- const layout = (() => {
- const [store, setStore] = makePersisted(
- createStore({
- sidebar: {
- opened: true,
- width: 240,
- },
- review: {
- state: "pane" as "pane" | "tab",
- },
- }),
- {
- name: "_default-layout",
- },
- )
-
- return {
- sidebar: {
- opened: createMemo(() => store.sidebar.opened),
- open() {
- setStore("sidebar", "opened", true)
- },
- close() {
- setStore("sidebar", "opened", false)
- },
- toggle() {
- setStore("sidebar", "opened", (x) => !x)
- },
- width: createMemo(() => store.sidebar.width),
- resize(width: number) {
- setStore("sidebar", "width", width)
- },
- },
- review: {
- state: createMemo(() => store.review?.state ?? "closed"),
- pane() {
- setStore("review", "state", "pane")
- },
- tab() {
- setStore("review", "state", "tab")
- },
- },
- }
- })()
-
const result = {
model,
agent,
file,
context,
- layout,
}
return result
},
diff --git a/packages/desktop/src/context/sdk.tsx b/packages/desktop/src/context/sdk.tsx
index 8d0cace65..b7b753dbc 100644
--- a/packages/desktop/src/context/sdk.tsx
+++ b/packages/desktop/src/context/sdk.tsx
@@ -5,12 +5,15 @@ import { onCleanup } from "solid-js"
export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
name: "SDK",
- init: (props: { url: string }) => {
+ init: (props: { url: string; directory?: string }) => {
const abort = new AbortController()
- const sdk = createOpencodeClient({
- baseUrl: props.url,
- signal: abort.signal,
- })
+ const sdk = createOpencodeClient(
+ {
+ baseUrl: props.url,
+ signal: abort.signal,
+ },
+ { directory: props.directory },
+ )
const emitter = createGlobalEmitter<{
[key in Event["type"]]: Extract<Event, { type: key }>
@@ -27,6 +30,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
abort.abort()
})
- return { client: sdk, event: emitter }
+ return { url: props.url, directory: props.directory, client: sdk, event: emitter }
},
})
diff --git a/packages/desktop/src/context/session.tsx b/packages/desktop/src/context/session.tsx
index b2e15a42c..a468f4673 100644
--- a/packages/desktop/src/context/session.tsx
+++ b/packages/desktop/src/context/session.tsx
@@ -3,7 +3,7 @@ import { createSimpleContext } from "./helper"
import { batch, createEffect, createMemo } from "solid-js"
import { useSync } from "./sync"
import { makePersisted } from "@solid-primitives/storage"
-import { TextSelection, useLocal } from "./local"
+import { TextSelection } from "./local"
import { pipe, sumBy } from "remeda"
import { AssistantMessage } from "@opencode-ai/sdk"
@@ -11,7 +11,6 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex
name: "Session",
init: (props: { sessionId?: string }) => {
const sync = useSync()
- const local = useLocal()
const [store, setStore] = makePersisted(
createStore<{
@@ -140,9 +139,6 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex
setStore("tabs", "active", undefined)
return
}
- if (tab.startsWith("file://")) {
- await local.file.open(tab.replace("file://", ""))
- }
if (tab !== "review") {
if (!store.tabs.opened.includes(tab)) {
setStore("tabs", "opened", [...store.tabs.opened, tab])
diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx
index 3626cf54f..11b2c36b8 100644
--- a/packages/desktop/src/context/sync.tsx
+++ b/packages/desktop/src/context/sync.tsx
@@ -63,6 +63,8 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
const sdk = useSDK()
sdk.event.listen((e) => {
+ // fetch the child store
+ // make a set store function that always rights to the child store
const event = e.details
switch (event.type) {
case "session.updated": {
diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx
index 63d96ae84..2499e5e85 100644
--- a/packages/desktop/src/index.tsx
+++ b/packages/desktop/src/index.tsx
@@ -6,10 +6,10 @@ import { MetaProvider } from "@solidjs/meta"
import { Fonts, MarkedProvider } from "@opencode-ai/ui"
import { SDKProvider } from "./context/sdk"
import { SyncProvider } from "./context/sync"
-import { LocalProvider } from "./context/local"
import Layout from "@/pages/layout"
import SessionLayout from "@/pages/session-layout"
import Session from "@/pages/session"
+import { LayoutProvider } from "./context/layout"
const host = import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "127.0.0.1"
const port = import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"
@@ -32,7 +32,7 @@ render(
<MarkedProvider>
<SDKProvider url={url}>
<SyncProvider>
- <LocalProvider>
+ <LayoutProvider>
<MetaProvider>
<Fonts />
<Router root={Layout}>
@@ -41,7 +41,7 @@ render(
</Route>
</Router>
</MetaProvider>
- </LocalProvider>
+ </LayoutProvider>
</SyncProvider>
</SDKProvider>
</MarkedProvider>
diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx
index d88564007..6e0078a16 100644
--- a/packages/desktop/src/pages/layout.tsx
+++ b/packages/desktop/src/pages/layout.tsx
@@ -1,33 +1,85 @@
-import { Button, Tooltip, DiffChanges, IconButton } from "@opencode-ai/ui"
-import { createMemo, For, ParentProps, Show } from "solid-js"
+import { Button, Tooltip, DiffChanges, IconButton, Mark, Icon } from "@opencode-ai/ui"
+import { createMemo, For, Match, ParentProps, Show, Switch } from "solid-js"
import { DateTime } from "luxon"
import { useSync } from "@/context/sync"
import { A, useParams } from "@solidjs/router"
-import { useLocal } from "@/context/local"
+import { useLayout } from "@/context/layout"
export default function Layout(props: ParentProps) {
const params = useParams()
const sync = useSync()
- const local = useLocal()
+ const layout = useLayout()
return (
<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>
- <div class="h-[calc(100vh-0rem)] flex">
+ <header class="h-12 shrink-0 bg-background-base border-b border-border-weak-base">
<div
classList={{
- "@container w-14 pb-4 shrink-0 bg-background-weak": true,
- "flex flex-col items-start self-stretch justify-between": true,
+ "w-12 shrink-0 px-4 py-3.5": true,
+ "flex items-center justify-start self-stretch": true,
"border-r border-border-weak-base": true,
- "w-70": local.layout.sidebar.opened(),
}}
+ style={{ width: layout.sidebar.opened() ? `${layout.sidebar.width()}px` : undefined }}
>
- <div class="flex flex-col justify-center items-start gap-4 self-stretch py-2 overflow-hidden mx-auto @[4rem]:mx-0">
- <div class="h-8 shrink-0 flex items-center self-stretch px-3">
- <Tooltip placement="right" value="Collapse sidebar">
- <IconButton icon="layout-left" variant="ghost" size="large" onClick={local.layout.sidebar.toggle} />
- </Tooltip>
- </div>
+ <Mark class="shrink-0" />
+ </div>
+ </header>
+ <div class="h-[calc(100vh-3rem)] flex">
+ <div
+ classList={{
+ "@container w-12 pb-5 shrink-0 bg-background-base": true,
+ "flex flex-col gap-5.5 items-start self-stretch justify-between": true,
+ "border-r border-border-weak-base": true,
+ }}
+ style={{ width: layout.sidebar.opened() ? `${layout.sidebar.width()}px` : undefined }}
+ >
+ <div class="flex flex-col justify-center items-start gap-4 self-stretch p-2 overflow-hidden mx-auto @[4rem]:mx-0">
+ <Switch>
+ <Match when={layout.sidebar.opened()}>
+ <Button
+ variant="ghost"
+ size="large"
+ class="group/sidebar-toggle w-full text-left justify-start"
+ onClick={layout.sidebar.toggle}
+ >
+ <div class="relative -ml-px flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
+ <Icon name="layout-left" size="small" class="group-hover/sidebar-toggle:hidden" />
+ <Icon
+ name="layout-left-partial"
+ size="small"
+ class="hidden group-hover/sidebar-toggle:inline-block"
+ />
+ <Icon
+ name="layout-left-full"
+ size="small"
+ class="hidden group-active/sidebar-toggle:inline-block"
+ />
+ </div>
+ <div class="hidden group-hover/sidebar-toggle:block group-active/sidebar-toggle:block text-text-base">
+ Toggle sidebar
+ </div>
+ </Button>
+ </Match>
+ <Match when={!layout.sidebar.opened()}>
+ <Tooltip placement="right" value="Toggle sidebar">
+ <Button variant="ghost" size="large" class="group/sidebar-toggle" onClick={layout.sidebar.toggle}>
+ <div class="relative -ml-px flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
+ <Icon name="layout-right" size="small" class="group-hover/sidebar-toggle:hidden" />
+ <Icon
+ name="layout-right-partial"
+ size="small"
+ class="hidden group-hover/sidebar-toggle:inline-block"
+ />
+ <Icon
+ name="layout-right-full"
+ size="small"
+ class="hidden group-active/sidebar-toggle:inline-block"
+ />
+ </div>
+ </Button>
+ </Tooltip>
+ </Match>
+ </Switch>
<div class="w-full px-3">
<Button as={A} href="/session" class="hidden @[4rem]:flex w-full" size="large" icon="edit-small-2">
New Session
diff --git a/packages/desktop/src/pages/session-layout.tsx b/packages/desktop/src/pages/session-layout.tsx
index 9a24608f0..7f355c9bc 100644
--- a/packages/desktop/src/pages/session-layout.tsx
+++ b/packages/desktop/src/pages/session-layout.tsx
@@ -1,12 +1,24 @@
import { Show, type ParentProps } from "solid-js"
-import { SessionProvider } from "@/context/session"
+import { SessionProvider, useSession } from "@/context/session"
import { useParams } from "@solidjs/router"
+import { SDKProvider, useSDK } from "@/context/sdk"
+import { LocalProvider } from "@/context/local"
export default function Layout(props: ParentProps) {
const params = useParams()
+ const root = useSDK()
return (
<Show when={params.id || true} keyed>
- <SessionProvider sessionId={params.id}>{props.children}</SessionProvider>
+ <SessionProvider sessionId={params.id}>
+ {(() => {
+ const session = useSession()
+ return (
+ <SDKProvider url={root.url} directory={session.info()?.directory}>
+ <LocalProvider>{props.children}</LocalProvider>
+ </SDKProvider>
+ )
+ })()}
+ </SessionProvider>
</Show>
)
}
diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx
index 0e5eb1f3d..884d789b1 100644
--- a/packages/desktop/src/pages/session.tsx
+++ b/packages/desktop/src/pages/session.tsx
@@ -13,7 +13,6 @@ import {
Code,
Tooltip,
ProgressCircle,
- Button,
} from "@opencode-ai/ui"
import { FileIcon } from "@/ui"
import { MessageProgress } from "@/components/message-progress"
@@ -52,8 +51,10 @@ import { Spinner } from "@/components/spinner"
import { useSession } from "@/context/session"
import { StickyAccordionHeader } from "@/components/sticky-accordion-header"
import { SessionReview } from "@/components/session-review"
+import { useLayout } from "@/context/layout"
export default function Page() {
+ const layout = useLayout()
const local = useLocal()
const sync = useSync()
const session = useSession()
@@ -176,10 +177,16 @@ export default function Page() {
setStore("activeDraggable", undefined)
}
- const FileVisual = (props: { file: LocalFile }): JSX.Element => {
+ const FileVisual = (props: { file: LocalFile; active?: boolean }): JSX.Element => {
return (
<div class="flex items-center gap-x-1.5">
- <FileIcon node={props.file} class="grayscale-100 group-data-[selected]/tab:grayscale-0" />
+ <FileIcon
+ node={props.file}
+ classList={{
+ "grayscale-100 group-data-[selected]/tab:grayscale-0": !props.active,
+ "grayscale-0": props.active,
+ }}
+ />
<span
classList={{
"text-14-medium": true,
@@ -300,11 +307,11 @@ export default function Page() {
</Tooltip>
</div>
</Tabs.Trigger>
- <Show when={local.layout.review.state() === "tab" && session.diffs().length}>
+ <Show when={layout.review.state() === "tab" && session.diffs().length}>
<Tabs.Trigger
value="review"
closeButton={
- <IconButton icon="collapse" size="normal" variant="ghost" onClick={local.layout.review.pane} />
+ <IconButton icon="collapse" size="normal" variant="ghost" onClick={layout.review.pane} />
}
>
<div class="flex items-center gap-3">
@@ -343,8 +350,8 @@ export default function Page() {
<div
classList={{
"w-full flex-1 min-h-0": true,
- grid: local.layout.review.state() === "tab",
- flex: local.layout.review.state() === "pane",
+ grid: layout.review.state() === "tab",
+ flex: layout.review.state() === "pane",
}}
>
<div class="relative shrink-0 px-6 py-3 flex flex-col gap-6 flex-1 min-h-0 w-full max-w-xl mx-auto">
@@ -353,7 +360,7 @@ export default function Page() {
<div
classList={{
"flex-1 min-h-0 pb-20": true,
- "flex items-start justify-start": local.layout.review.state() === "pane",
+ "flex items-start justify-start": layout.review.state() === "pane",
}}
>
<Show when={session.messages.user().length > 1}>
@@ -361,8 +368,8 @@ export default function Page() {
role="list"
classList={{
"mr-8 shrink-0 flex flex-col items-start": true,
- "absolute right-full w-60 mt-3 @7xl:gap-2 @7xl:mt-1": local.layout.review.state() === "tab",
- "mt-3": local.layout.review.state() === "pane",
+ "absolute right-full w-60 mt-3 @7xl:gap-2 @7xl:mt-1": layout.review.state() === "tab",
+ "mt-3": layout.review.state() === "pane",
}}
>
<For each={session.messages.user()}>
@@ -382,7 +389,7 @@ export default function Page() {
<li
classList={{
"group/li flex items-center self-stretch justify-end": true,
- "@7xl:justify-start": local.layout.review.state() === "tab",
+ "@7xl:justify-start": layout.review.state() === "tab",
}}
>
<Tooltip
@@ -401,7 +408,7 @@ export default function Page() {
classList={{
"group/tick flex items-center justify-start h-2 w-8 -mr-3": true,
"data-[active=true]:[&>div]:bg-icon-strong-base data-[active=true]:[&>div]:w-full": true,
- "@7xl:hidden": local.layout.review.state() === "tab",
+ "@7xl:hidden": layout.review.state() === "tab",
}}
>
<div class="h-px w-5 bg-icon-base group-hover/tick:w-full group-hover/tick:bg-icon-strong-base" />
@@ -410,7 +417,7 @@ export default function Page() {
<button
classList={{
"hidden items-center self-stretch w-full gap-x-2 cursor-default": true,
- "@7xl:flex": local.layout.review.state() === "tab",
+ "@7xl:flex": layout.review.state() === "tab",
}}
onClick={handleClick}
>
@@ -654,7 +661,7 @@ export default function Page() {
/>
</div>
</div>
- <Show when={local.layout.review.state() === "pane" && session.diffs().length}>
+ <Show when={layout.review.state() === "pane" && session.diffs().length}>
<div
classList={{
"relative grow px-6 py-3 flex-1 min-h-0 border-l border-border-weak-base": true,
@@ -665,7 +672,7 @@ export default function Page() {
</Show>
</div>
</Tabs.Content>
- <Show when={local.layout.review.state() === "tab" && session.diffs().length}>
+ <Show when={layout.review.state() === "tab" && session.diffs().length}>
<Tabs.Content value="review" class="select-text flex flex-col h-full overflow-hidden">
<div
classList={{
@@ -718,8 +725,8 @@ export default function Page() {
},
)
return (
- <div class="relative px-3 h-10 flex items-center bg-background-base border-x border-border-weak-base border-b border-b-transparent">
- <Show when={file()}>{(f) => <FileVisual file={f()} />}</Show>
+ <div class="relative px-6 h-12 flex items-center bg-background-stronger border-x border-border-weak-base border-b border-b-transparent">
+ <Show when={file()}>{(f) => <FileVisual active file={f()} />}</Show>
</div>
)
}}
@@ -769,7 +776,13 @@ export default function Page() {
items={local.file.searchFiles}
key={(x) => x}
onOpenChange={(open) => setStore("fileSelectOpen", open)}
- onSelect={(x) => (x ? session.layout.openTab("file://" + x) : undefined)}
+ onSelect={(x) => {
+ if (x) {
+ local.file.open(x)
+ return session.layout.openTab("file://" + x)
+ }
+ return undefined
+ }}
>
{(i) => (
<div
diff --git a/packages/desktop/src/ui/file-icon.tsx b/packages/desktop/src/ui/file-icon.tsx
index d31a741e0..53b3c1e69 100644
--- a/packages/desktop/src/ui/file-icon.tsx
+++ b/packages/desktop/src/ui/file-icon.tsx
@@ -9,12 +9,13 @@ export type FileIconProps = JSX.GSVGAttributes<SVGSVGElement> & {
}
export const FileIcon: Component<FileIconProps> = (props) => {
- const [local, rest] = splitProps(props, ["node", "class", "expanded"])
+ const [local, rest] = splitProps(props, ["node", "class", "classList", "expanded"])
const name = createMemo(() => chooseIconName(local.node.path, local.node.type, local.expanded || false))
return (
<svg
{...rest}
classList={{
+ ...(local.classList ?? {}),
"shrink-0 size-4": true,
[local.class ?? ""]: !!local.class,
}}
diff --git a/packages/sdk/js/src/client.ts b/packages/sdk/js/src/client.ts
index ac9aa1519..ebe0b8ed4 100644
--- a/packages/sdk/js/src/client.ts
+++ b/packages/sdk/js/src/client.ts
@@ -5,7 +5,7 @@ import { createClient } from "./gen/client/client.gen.js"
import { type Config } from "./gen/client/types.gen.js"
import { OpencodeClient } from "./gen/sdk.gen.js"
-export function createOpencodeClient(config?: Config) {
+export function createOpencodeClient(config?: Config, options?: { directory?: string }) {
if (!config?.fetch) {
config = {
...config,
@@ -18,5 +18,15 @@ export function createOpencodeClient(config?: Config) {
}
const client = createClient(config)
+
+ if (options?.directory) {
+ async function middleware(request: Request) {
+ const url = new URL(request.url)
+ url.searchParams.set("directory", options!.directory!)
+ return new Request(url.toString(), request)
+ }
+ client.interceptors.request.use(middleware)
+ }
+
return new OpencodeClient({ client })
}
diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css
index 0fdb49cdc..7015ea88d 100644
--- a/packages/ui/src/components/button.css
+++ b/packages/ui/src/components/button.css
@@ -19,13 +19,29 @@
border-color: var(--border-hover);
background-color: var(--surface-brand-hover);
}
+ &:focus:not(:disabled) {
+ border-color: var(--border-focus);
+ background-color: var(--surface-brand-focus);
+ }
&:active:not(:disabled) {
border-color: var(--border-active);
background-color: var(--surface-brand-active);
}
+ }
+
+ &[data-variant="ghost"] {
+ border-color: transparent;
+ background-color: transparent;
+ color: var(--text-strong);
+
+ &:hover:not(:disabled) {
+ background-color: var(--surface-raised-base-hover);
+ }
&:focus:not(:disabled) {
- border-color: var(--border-focus);
- background-color: var(--surface-brand-focus);
+ background-color: var(--surface-raised-base-hover);
+ }
+ &:active:not(:disabled) {
+ background-color: var(--surface-raised-base-active);
}
}
@@ -38,9 +54,6 @@
&:hover:not(:disabled) {
background-color: var(--button-secondary-hover);
}
- &:active:not(:disabled) {
- background-color: var(--button-secondary-base);
- }
&:focus:not(:disabled) {
background-color: var(--button-secondary-base);
}
@@ -51,7 +64,8 @@
&:focus-visible:active {
box-shadow: none;
}
- &:active {
+ &:active:not(:disabled) {
+ background-color: var(--button-secondary-base);
scale: 0.99;
transition: all 150ms ease-out;
}
@@ -61,22 +75,6 @@
}
}
- &[data-variant="ghost"] {
- border-color: transparent;
- background-color: transparent;
- color: var(--text-strong);
-
- &:hover:not(:disabled) {
- background-color: var(--button-ghost-hover);
- }
- &:active:not(:disabled) {
- background-color: var(--button-ghost-hover-2);
- }
- &:focus:not(:disabled) {
- background-color: var(--button-ghost-hover);
- }
- }
-
&[data-size="normal"] {
height: 24px;
padding: 0 6px;
diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css
index 9e1c51cb2..3449adaeb 100644
--- a/packages/ui/src/components/icon-button.css
+++ b/packages/ui/src/components/icon-button.css
@@ -26,12 +26,12 @@
&:hover:not(:disabled) {
background-color: var(--icon-strong-hover);
}
- &:active:not(:disabled) {
- background-color: var(--icon-string-active);
- }
&:focus:not(:disabled) {
background-color: var(--icon-strong-focus);
}
+ &:active:not(:disabled) {
+ background-color: var(--icon-string-active);
+ }
&:disabled {
background-color: var(--icon-strong-disabled);
@@ -50,9 +50,6 @@
&:hover:not(:disabled) {
background-color: var(--button-secondary-hover);
}
- &:active:not(:disabled) {
- background-color: var(--button-secondary-base);
- }
&:focus:not(:disabled) {
background-color: var(--button-secondary-base);
}
@@ -63,6 +60,9 @@
&:focus-visible:active {
box-shadow: none;
}
+ &:active:not(:disabled) {
+ background-color: var(--button-secondary-base);
+ }
[data-slot="icon"] {
color: var(--icon-strong-base);
@@ -78,25 +78,26 @@
}
&:hover:not(:disabled) {
- background-color: var(--surface-base-hover);
+ background-color: var(--surface-raised-base-hover);
- [data-slot="icon"] {
- color: var(--icon-hover);
- }
+ /* [data-slot="icon"] { */
+ /* color: var(--icon-hover); */
+ /* } */
+ }
+ &:focus:not(:disabled) {
+ background-color: var(--surface-focus);
}
&:active:not(:disabled) {
- [data-slot="icon"] {
- color: var(--icon-active);
- }
+ background-color: var(--surface-raised-base-active);
+ /* [data-slot="icon"] { */
+ /* color: var(--icon-active); */
+ /* } */
}
&:selected:not(:disabled) {
- background-color: var(--surface-base-active);
- [data-slot="icon"] {
- color: var(--icon-selected);
- }
- }
- &:focus:not(:disabled) {
- background-color: var(--surface-focus);
+ background-color: var(--surface-raised-base-active);
+ /* [data-slot="icon"] { */
+ /* color: var(--icon-selected); */
+ /* } */
}
}
diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx
index c69d04f7a..da893564e 100644
--- a/packages/ui/src/components/icon.tsx
+++ b/packages/ui/src/components/icon.tsx
@@ -153,7 +153,11 @@ const newIcons = {
stop: `<rect x="5" y="5" width="10" height="10" fill="currentColor"/>`,
enter: `<path d="M5.83333 15.8334L2.5 12.5L5.83333 9.16671M3.33333 12.5H17.9167V4.58337H10" stroke="currentColor" stroke-linecap="square"/>`,
"layout-left": `<path d="M2.91675 2.91699L2.91675 2.41699L2.41675 2.41699L2.41675 2.91699L2.91675 2.91699ZM17.0834 2.91699L17.5834 2.91699L17.5834 2.41699L17.0834 2.41699L17.0834 2.91699ZM17.0834 17.0837L17.0834 17.5837L17.5834 17.5837L17.5834 17.0837L17.0834 17.0837ZM2.91675 17.0837L2.41675 17.0837L2.41675 17.5837L2.91675 17.5837L2.91675 17.0837ZM7.41674 17.0837L7.41674 17.5837L8.41674 17.5837L8.41674 17.0837L7.91674 17.0837L7.41674 17.0837ZM8.41674 2.91699L8.41674 2.41699L7.41674 2.41699L7.41674 2.91699L7.91674 2.91699L8.41674 2.91699ZM2.91675 2.91699L2.91675 3.41699L17.0834 3.41699L17.0834 2.91699L17.0834 2.41699L2.91675 2.41699L2.91675 2.91699ZM17.0834 2.91699L16.5834 2.91699L16.5834 17.0837L17.0834 17.0837L17.5834 17.0837L17.5834 2.91699L17.0834 2.91699ZM17.0834 17.0837L17.0834 16.5837L2.91675 16.5837L2.91675 17.0837L2.91675 17.5837L17.0834 17.5837L17.0834 17.0837ZM2.91675 17.0837L3.41675 17.0837L3.41675 2.91699L2.91675 2.91699L2.41675 2.91699L2.41675 17.0837L2.91675 17.0837ZM7.91674 17.0837L8.41674 17.0837L8.41674 2.91699L7.91674 2.91699L7.41674 2.91699L7.41674 17.0837L7.91674 17.0837Z" fill="currentColor"/>`,
+ "layout-left-partial": `<path d="M2.91732 2.91602L7.91732 2.91602L7.91732 17.0827H2.91732L2.91732 2.91602Z" fill="currentColor" fill-opacity="20%" /><path d="M2.91732 2.91602L17.084 2.91602M2.91732 2.91602L2.91732 17.0827M2.91732 2.91602L7.91732 2.91602M17.084 2.91602L17.084 17.0827M17.084 2.91602L7.91732 2.91602M17.084 17.0827L2.91732 17.0827M17.084 17.0827L7.91732 17.0827M2.91732 17.0827H7.91732M7.91732 17.0827L7.91732 2.91602" stroke="currentColor" stroke-linecap="square"/>`,
+ "layout-left-full": `<path d="M2.91732 2.91602L7.91732 2.91602L7.91732 17.0827H2.91732L2.91732 2.91602Z" fill="currentColor"/><path d="M2.91732 2.91602L17.084 2.91602M2.91732 2.91602L2.91732 17.0827M2.91732 2.91602L7.91732 2.91602M17.084 2.91602L17.084 17.0827M17.084 2.91602L7.91732 2.91602M17.084 17.0827L2.91732 17.0827M17.084 17.0827L7.91732 17.0827M2.91732 17.0827H7.91732M7.91732 17.0827L7.91732 2.91602" stroke="currentColor" stroke-linecap="square"/>`,
"layout-right": `<path d="M17.0832 2.91699L17.5832 2.91699L17.5832 2.41699L17.0832 2.41699L17.0832 2.91699ZM2.91651 2.91699L2.91651 2.41699L2.41651 2.41699L2.41651 2.91699L2.91651 2.91699ZM2.9165 17.0837L2.4165 17.0837L2.4165 17.5837L2.9165 17.5837L2.9165 17.0837ZM17.0832 17.0837L17.0832 17.5837L17.5832 17.5837L17.5832 17.0837L17.0832 17.0837ZM11.5832 17.0837L11.5832 17.5837L12.5832 17.5837L12.5832 17.0837L12.0832 17.0837L11.5832 17.0837ZM12.5832 2.91699L12.5832 2.41699L11.5832 2.41699L11.5832 2.91699L12.0832 2.91699L12.5832 2.91699ZM17.0832 2.91699L17.0832 2.41699L2.91651 2.41699L2.91651 2.91699L2.91651 3.41699L17.0832 3.41699L17.0832 2.91699ZM2.91651 2.91699L2.41651 2.91699L2.4165 17.0837L2.9165 17.0837L3.4165 17.0837L3.41651 2.91699L2.91651 2.91699ZM2.9165 17.0837L2.9165 17.5837L17.0832 17.5837L17.0832 17.0837L17.0832 16.5837L2.9165 16.5837L2.9165 17.0837ZM17.0832 17.0837L17.5832 17.0837L17.5832 2.91699L17.0832 2.91699L16.5832 2.91699L16.5832 17.0837L17.0832 17.0837ZM12.0832 17.0837L12.5832 17.0837L12.5832 2.91699L12.0832 2.91699L11.5832 2.91699L11.5832 17.0837L12.0832 17.0837Z" fill="currentColor"/>`,
+ "layout-right-partial": `<path d="M12.0827 2.91602L2.91602 2.91602L2.91602 17.0827L12.0827 17.0827L12.0827 2.91602Z" fill="currentColor" fill-opacity="20%" /><path d="M2.91602 2.91602L17.0827 2.91602L17.0827 17.0827L2.91602 17.0827M2.91602 2.91602L2.91602 17.0827M2.91602 2.91602L12.0827 2.91602L12.0827 17.0827L2.91602 17.0827" stroke="currentColor" stroke-linecap="square"/>`,
+ "layout-right-full": `<path d="M12.0827 2.91602L2.91602 2.91602L2.91602 17.0827L12.0827 17.0827L12.0827 2.91602Z" fill="currentColor"/><path d="M2.91602 2.91602L17.0827 2.91602L17.0827 17.0827L2.91602 17.0827M2.91602 2.91602L2.91602 17.0827M2.91602 2.91602L12.0827 2.91602L12.0827 17.0827L2.91602 17.0827" stroke="currentColor" stroke-linecap="square"/>`,
"speech-bubble": `<path d="M18.3334 10.0003C18.3334 5.57324 15.0927 2.91699 10.0001 2.91699C4.90749 2.91699 1.66675 5.57324 1.66675 10.0003C1.66675 11.1497 2.45578 13.1016 2.5771 13.3949C2.5878 13.4207 2.59839 13.4444 2.60802 13.4706C2.69194 13.6996 3.04282 14.9364 1.66675 16.7684C3.5186 17.6538 5.48526 16.1982 5.48526 16.1982C6.84592 16.9202 8.46491 17.0837 10.0001 17.0837C15.0927 17.0837 18.3334 14.4274 18.3334 10.0003Z" stroke="currentColor" stroke-linecap="square"/>`,
"align-right": `<path d="M12.292 6.04167L16.2503 9.99998L12.292 13.9583M2.91699 9.99998H15.6253M17.0837 3.75V16.25" stroke="currentColor" stroke-linecap="square"/>`,
expand: `<path d="M4.58301 10.4163V15.4163H9.58301M10.4163 4.58301H15.4163V9.58301" stroke="currentColor" stroke-linecap="square"/>`,
diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts
index ebc897a1f..7dc7ee0f1 100644
--- a/packages/ui/src/components/index.ts
+++ b/packages/ui/src/components/index.ts
@@ -13,6 +13,7 @@ export * from "./input"
export * from "./favicon"
export * from "./fonts"
export * from "./list"
+export * from "./logo"
export * from "./markdown"
export * from "./message-part"
export * from "./progress-circle"
diff --git a/packages/ui/src/components/logo.css b/packages/ui/src/components/logo.css
new file mode 100644
index 000000000..36e871859
--- /dev/null
+++ b/packages/ui/src/components/logo.css
@@ -0,0 +1,4 @@
+[data-component="logo-mark"] {
+ width: 16px;
+ height: 20px;
+}
diff --git a/packages/ui/src/components/logo.tsx b/packages/ui/src/components/logo.tsx
new file mode 100644
index 000000000..d3588f301
--- /dev/null
+++ b/packages/ui/src/components/logo.tsx
@@ -0,0 +1,14 @@
+export const Mark = (props: { class?: string }) => {
+ return (
+ <svg
+ data-component="logo-mark"
+ classList={{ [props.class ?? ""]: !!props.class }}
+ viewBox="0 0 16 20"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path data-slot="logo-mark-shadow" d="M12 16H4V8H12V16Z" fill="var(--icon-weak-base)" />
+ <path data-slot="logo-mark-o" d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="var(--icon-strong-base)" />
+ </svg>
+ )
+}
diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css
index 60ce76ffe..b009b6daa 100644
--- a/packages/ui/src/styles/index.css
+++ b/packages/ui/src/styles/index.css
@@ -19,6 +19,7 @@
@import "../components/icon-button.css" layer(components);
@import "../components/input.css" layer(components);
@import "../components/list.css" layer(components);
+@import "../components/logo.css" layer(components);
@import "../components/markdown.css" layer(components);
@import "../components/message-part.css" layer(components);
@import "../components/progress-circle.css" layer(components);