From 7cb84f13d3b73c6bd6e6f7949bb952da1af3f2be Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 30 Jan 2026 12:19:36 -0500 Subject: [PATCH 01/58] wip: zen (#11343) --- infra/console.ts | 2 ++ packages/console/core/script/promote-models.ts | 11 ++++++----- packages/console/core/script/pull-models.ts | 11 ++++++----- packages/console/core/script/update-models.ts | 16 +++++++++------- packages/console/core/src/model.ts | 4 +++- packages/console/core/sst-env.d.ts | 8 ++++++++ packages/console/function/sst-env.d.ts | 8 ++++++++ packages/console/resource/sst-env.d.ts | 8 ++++++++ packages/enterprise/sst-env.d.ts | 8 ++++++++ packages/function/sst-env.d.ts | 8 ++++++++ sst-env.d.ts | 8 ++++++++ 11 files changed, 74 insertions(+), 18 deletions(-) diff --git a/infra/console.ts b/infra/console.ts index 5b08e9ceaa..ba1ff15bf2 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -133,6 +133,8 @@ const ZEN_MODELS = [ new sst.Secret("ZEN_MODELS6"), new sst.Secret("ZEN_MODELS7"), new sst.Secret("ZEN_MODELS8"), + new sst.Secret("ZEN_MODELS9"), + new sst.Secret("ZEN_MODELS10"), ] const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY") const STRIPE_PUBLISHABLE_KEY = new sst.Secret("STRIPE_PUBLISHABLE_KEY") diff --git a/packages/console/core/script/promote-models.ts b/packages/console/core/script/promote-models.ts index bc57fc5bb3..9a9b2dcade 100755 --- a/packages/console/core/script/promote-models.ts +++ b/packages/console/core/script/promote-models.ts @@ -2,20 +2,21 @@ import { $ } from "bun" import path from "path" +import os from "os" import { ZenData } from "../src/model" const stage = process.argv[2] if (!stage) throw new Error("Stage is required") const root = path.resolve(process.cwd(), "..", "..", "..") -const PARTS = 8 +const PARTS = 10 // read the secret const ret = await $`bun sst secret list`.cwd(root).text() const lines = ret.split("\n") const values = Array.from({ length: PARTS }, (_, i) => { const value = lines - .find((line) => line.startsWith(`ZEN_MODELS${i + 1}`)) + .find((line) => line.startsWith(`ZEN_MODELS${i + 1}=`)) ?.split("=") .slice(1) .join("=") @@ -27,6 +28,6 @@ const values = Array.from({ length: PARTS }, (_, i) => { ZenData.validate(JSON.parse(values.join(""))) // update the secret -for (let i = 0; i < PARTS; i++) { - await $`bun sst secret set ZEN_MODELS${i + 1} --stage ${stage} -- ${values[i]}` -} +const envFile = Bun.file(path.join(os.tmpdir(), `models-${Date.now()}.env`)) +await envFile.write(values.map((v, i) => `ZEN_MODELS${i + 1}=${v}`).join("\n")) +await $`bun sst secret load ${envFile.name} --stage ${stage}`.cwd(root) diff --git a/packages/console/core/script/pull-models.ts b/packages/console/core/script/pull-models.ts index f360b81864..6e89f602b7 100755 --- a/packages/console/core/script/pull-models.ts +++ b/packages/console/core/script/pull-models.ts @@ -2,20 +2,21 @@ import { $ } from "bun" import path from "path" +import os from "os" import { ZenData } from "../src/model" const stage = process.argv[2] if (!stage) throw new Error("Stage is required") const root = path.resolve(process.cwd(), "..", "..", "..") -const PARTS = 8 +const PARTS = 10 // read the secret const ret = await $`bun sst secret list --stage ${stage}`.cwd(root).text() const lines = ret.split("\n") const values = Array.from({ length: PARTS }, (_, i) => { const value = lines - .find((line) => line.startsWith(`ZEN_MODELS${i + 1}`)) + .find((line) => line.startsWith(`ZEN_MODELS${i + 1}=`)) ?.split("=") .slice(1) .join("=") @@ -27,6 +28,6 @@ const values = Array.from({ length: PARTS }, (_, i) => { ZenData.validate(JSON.parse(values.join(""))) // update the secret -for (let i = 0; i < PARTS; i++) { - await $`bun sst secret set ZEN_MODELS${i + 1} -- ${values[i]}` -} +const envFile = Bun.file(path.join(os.tmpdir(), `models-${Date.now()}.env`)) +await envFile.write(values.map((v, i) => `ZEN_MODELS${i + 1}=${v}`).join("\n")) +await $`bun sst secret load ${envFile.name}`.cwd(root) diff --git a/packages/console/core/script/update-models.ts b/packages/console/core/script/update-models.ts index 56940af257..3085353a75 100755 --- a/packages/console/core/script/update-models.ts +++ b/packages/console/core/script/update-models.ts @@ -7,18 +7,20 @@ import { ZenData } from "../src/model" const root = path.resolve(process.cwd(), "..", "..", "..") const models = await $`bun sst secret list`.cwd(root).text() -const PARTS = 8 +const PARTS = 10 // read the line starting with "ZEN_MODELS" const lines = models.split("\n") const oldValues = Array.from({ length: PARTS }, (_, i) => { const value = lines - .find((line) => line.startsWith(`ZEN_MODELS${i + 1}`)) + .find((line) => line.startsWith(`ZEN_MODELS${i + 1}=`)) ?.split("=") .slice(1) .join("=") - if (!value) throw new Error(`ZEN_MODELS${i + 1} not found`) - return value + // TODO + //if (!value) throw new Error(`ZEN_MODELS${i + 1} not found`) + //return value + return value ?? "" }) // store the prettified json to a temp file @@ -38,6 +40,6 @@ const newValues = Array.from({ length: PARTS }, (_, i) => newValue.slice(chunk * i, i === PARTS - 1 ? undefined : chunk * (i + 1)), ) -for (let i = 0; i < PARTS; i++) { - await $`bun sst secret set ZEN_MODELS${i + 1} -- ${newValues[i]}` -} +const envFile = Bun.file(path.join(os.tmpdir(), `models-${Date.now()}.env`)) +await envFile.write(newValues.map((v, i) => `ZEN_MODELS${i + 1}=${v}`).join("\n")) +await $`bun sst secret load ${envFile.name}`.cwd(root) diff --git a/packages/console/core/src/model.ts b/packages/console/core/src/model.ts index 0fd8bdecfb..880c63a190 100644 --- a/packages/console/core/src/model.ts +++ b/packages/console/core/src/model.ts @@ -75,7 +75,9 @@ export namespace ZenData { Resource.ZEN_MODELS5.value + Resource.ZEN_MODELS6.value + Resource.ZEN_MODELS7.value + - Resource.ZEN_MODELS8.value, + Resource.ZEN_MODELS8.value + + Resource.ZEN_MODELS9.value + + Resource.ZEN_MODELS10.value, ) return ModelsSchema.parse(json) }) diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index cb49028130..0769c76335 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -133,6 +133,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS10": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_MODELS2": { "type": "sst.sst.Secret" "value": string @@ -161,6 +165,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS9": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_SESSION_SECRET": { "type": "sst.sst.Secret" "value": string diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index cb49028130..0769c76335 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -133,6 +133,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS10": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_MODELS2": { "type": "sst.sst.Secret" "value": string @@ -161,6 +165,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS9": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_SESSION_SECRET": { "type": "sst.sst.Secret" "value": string diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index cb49028130..0769c76335 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -133,6 +133,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS10": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_MODELS2": { "type": "sst.sst.Secret" "value": string @@ -161,6 +165,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS9": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_SESSION_SECRET": { "type": "sst.sst.Secret" "value": string diff --git a/packages/enterprise/sst-env.d.ts b/packages/enterprise/sst-env.d.ts index cb49028130..0769c76335 100644 --- a/packages/enterprise/sst-env.d.ts +++ b/packages/enterprise/sst-env.d.ts @@ -133,6 +133,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS10": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_MODELS2": { "type": "sst.sst.Secret" "value": string @@ -161,6 +165,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS9": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_SESSION_SECRET": { "type": "sst.sst.Secret" "value": string diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts index cb49028130..0769c76335 100644 --- a/packages/function/sst-env.d.ts +++ b/packages/function/sst-env.d.ts @@ -133,6 +133,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS10": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_MODELS2": { "type": "sst.sst.Secret" "value": string @@ -161,6 +165,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS9": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_SESSION_SECRET": { "type": "sst.sst.Secret" "value": string diff --git a/sst-env.d.ts b/sst-env.d.ts index 0b4cbffe2e..2d60c83ecd 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -159,6 +159,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS10": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_MODELS2": { "type": "sst.sst.Secret" "value": string @@ -187,6 +191,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS9": { + "type": "sst.sst.Secret" + "value": string + } "ZEN_SESSION_SECRET": { "type": "sst.sst.Secret" "value": string From 0b91e9087df38a2dcf63e5ac8408f86e557e25f3 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Fri, 30 Jan 2026 17:20:20 +0000 Subject: [PATCH 02/58] chore: generate --- packages/console/core/script/update-models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/console/core/script/update-models.ts b/packages/console/core/script/update-models.ts index 3085353a75..d37c6a9aab 100755 --- a/packages/console/core/script/update-models.ts +++ b/packages/console/core/script/update-models.ts @@ -17,7 +17,7 @@ const oldValues = Array.from({ length: PARTS }, (_, i) => { ?.split("=") .slice(1) .join("=") - // TODO + // TODO //if (!value) throw new Error(`ZEN_MODELS${i + 1} not found`) //return value return value ?? "" From 21edc00f110a05c8bf4c657066091565f0a3f916 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:45:42 -0600 Subject: [PATCH 03/58] ci: update pr template (#11341) --- .github/pull_request_template.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b4369fa1a4..d8a5c8a902 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,3 +1,7 @@ ### What does this PR do? +Please provide a description of the issue (if there is one), the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the pr. + +**If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** + ### How did you verify your code works? From 1bbe84ed8d0eceb96af06b971690ebd0b0213580 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 12:55:58 -0500 Subject: [PATCH 04/58] ci --- .github/workflows/generate.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml index 3bb8f364d6..706ab2989e 100644 --- a/.github/workflows/generate.yml +++ b/.github/workflows/generate.yml @@ -4,8 +4,6 @@ on: push: branches: - dev - pull_request: - workflow_dispatch: jobs: generate: From 20619a6a26ec0cfc2707b7ed13387715e9f9cdaa Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Fri, 30 Jan 2026 18:57:49 +0100 Subject: [PATCH 05/58] feat: Transitions, spacing, scroll fade, prompt area update (#11168) Co-authored-by: Github Action Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: aaroniker <4730431+aaroniker@users.noreply.github.com> --- .../src/components/dialog-select-model.tsx | 7 +- packages/app/src/components/prompt-input.tsx | 148 +- .../src/components/session-context-usage.tsx | 6 +- .../app/src/components/settings-general.tsx | 42 +- .../app/src/components/settings-keybinds.tsx | 10 +- packages/desktop/src-tauri/src/lib.rs | 1 + packages/ui/src/components/accordion.css | 183 +-- packages/ui/src/components/accordion.tsx | 43 +- packages/ui/src/components/avatar.css | 64 +- packages/ui/src/components/basic-tool.css | 168 +-- packages/ui/src/components/button.css | 292 ++-- packages/ui/src/components/button.tsx | 2 +- packages/ui/src/components/card.css | 50 +- packages/ui/src/components/checkbox.css | 219 +-- packages/ui/src/components/code.css | 4 +- packages/ui/src/components/collapsible.css | 178 ++- packages/ui/src/components/collapsible.tsx | 42 +- packages/ui/src/components/cycle-label.css | 52 + packages/ui/src/components/cycle-label.tsx | 132 ++ packages/ui/src/components/dialog.css | 305 ++-- packages/ui/src/components/diff-changes.css | 66 +- packages/ui/src/components/diff.css | 60 +- packages/ui/src/components/dropdown-menu.css | 213 +-- packages/ui/src/components/file-icon.css | 6 +- packages/ui/src/components/hover-card.css | 90 +- packages/ui/src/components/icon-button.css | 243 ++-- packages/ui/src/components/icon.css | 54 +- packages/ui/src/components/icon.tsx | 4 +- packages/ui/src/components/image-preview.css | 110 +- packages/ui/src/components/inline-input.css | 28 +- packages/ui/src/components/keybind.css | 30 +- packages/ui/src/components/line-comment.css | 140 +- packages/ui/src/components/list.css | 570 ++++---- packages/ui/src/components/list.tsx | 11 +- packages/ui/src/components/logo.css | 4 +- packages/ui/src/components/markdown.css | 354 ++--- packages/ui/src/components/message-nav.css | 165 +-- packages/ui/src/components/message-part.css | 1292 ++++++++--------- packages/ui/src/components/message-part.tsx | 3 +- packages/ui/src/components/morph-chevron.css | 10 + packages/ui/src/components/morph-chevron.tsx | 73 + packages/ui/src/components/popover.css | 190 ++- .../ui/src/components/progress-circle.css | 16 +- .../ui/src/components/progress-circle.tsx | 46 +- packages/ui/src/components/provider-icon.css | 6 +- packages/ui/src/components/radio-group.css | 280 ++-- packages/ui/src/components/reasoning-icon.css | 10 + packages/ui/src/components/reasoning-icon.tsx | 32 + packages/ui/src/components/resize-handle.css | 98 +- packages/ui/src/components/scroll-fade.css | 122 ++ packages/ui/src/components/scroll-fade.tsx | 207 +++ packages/ui/src/components/scroll-reveal.tsx | 141 ++ packages/ui/src/components/select.css | 329 ++--- packages/ui/src/components/select.tsx | 18 +- packages/ui/src/components/session-review.css | 367 +++-- packages/ui/src/components/session-review.tsx | 5 +- packages/ui/src/components/session-turn.css | 1148 +++++++-------- packages/ui/src/components/session-turn.tsx | 2 +- packages/ui/src/components/spinner.css | 8 +- .../components/sticky-accordion-header.css | 24 +- packages/ui/src/components/switch.css | 223 +-- packages/ui/src/components/tabs.css | 901 ++++++------ packages/ui/src/components/tag.css | 63 +- packages/ui/src/components/text-field.css | 218 +-- packages/ui/src/components/toast.css | 330 ++--- packages/ui/src/components/tooltip.css | 116 +- packages/ui/src/components/typewriter.css | 18 +- packages/ui/src/context/dialog.tsx | 24 + packages/ui/src/styles/index.css | 2 + packages/ui/src/styles/utilities.css | 225 +-- 70 files changed, 5836 insertions(+), 4807 deletions(-) create mode 100644 packages/ui/src/components/cycle-label.css create mode 100644 packages/ui/src/components/cycle-label.tsx create mode 100644 packages/ui/src/components/morph-chevron.css create mode 100644 packages/ui/src/components/morph-chevron.tsx create mode 100644 packages/ui/src/components/reasoning-icon.css create mode 100644 packages/ui/src/components/reasoning-icon.tsx create mode 100644 packages/ui/src/components/scroll-fade.css create mode 100644 packages/ui/src/components/scroll-fade.tsx create mode 100644 packages/ui/src/components/scroll-reveal.tsx diff --git a/packages/app/src/components/dialog-select-model.tsx b/packages/app/src/components/dialog-select-model.tsx index 4f0dcc3ee6..4d96c6c5f6 100644 --- a/packages/app/src/components/dialog-select-model.tsx +++ b/packages/app/src/components/dialog-select-model.tsx @@ -90,7 +90,7 @@ const ModelList: Component<{ export function ModelSelectorPopover(props: { provider?: string - children?: JSX.Element + children?: JSX.Element | ((open: boolean) => JSX.Element) triggerAs?: T triggerProps?: ComponentProps }) { @@ -182,12 +182,13 @@ export function ModelSelectorPopover(props: { as={props.triggerAs ?? "div"} {...(props.triggerProps as any)} > - {props.children} + {typeof props.children === "function" ? props.children(store.open) : props.children} setStore("content", el)} - class="w-72 h-80 flex flex-col p-2 rounded-md border border-border-base bg-surface-raised-stronger-non-alpha shadow-md z-50 outline-none overflow-hidden" onEscapeKeyDown={(event) => { setStore("dismiss", "escape") setStore("open", false) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 5c1d417eb0..313f0402d0 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -32,7 +32,9 @@ import { useNavigate, useParams } from "@solidjs/router" import { useSync } from "@/context/sync" import { useComments } from "@/context/comments" import { FileIcon } from "@opencode-ai/ui/file-icon" +import { MorphChevron } from "@opencode-ai/ui/morph-chevron" import { Button } from "@opencode-ai/ui/button" +import { CycleLabel } from "@opencode-ai/ui/cycle-label" import { Icon } from "@opencode-ai/ui/icon" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import type { IconName } from "@opencode-ai/ui/icons/provider" @@ -42,6 +44,7 @@ import { Select } from "@opencode-ai/ui/select" import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/util/path" import { useDialog } from "@opencode-ai/ui/context/dialog" import { ImagePreview } from "@opencode-ai/ui/image-preview" +import { ReasoningIcon } from "@opencode-ai/ui/reasoning-icon" import { ModelSelectorPopover } from "@/components/dialog-select-model" import { DialogSelectModelUnpaid } from "@/components/dialog-select-model-unpaid" import { useProviders } from "@/hooks/use-providers" @@ -922,7 +925,7 @@ export const PromptInput: Component = (props) => { .abort({ sessionID, }) - .catch(() => {}) + .catch(() => { }) } const addToHistory = (prompt: Prompt, mode: "normal" | "shell") => { @@ -1252,7 +1255,7 @@ export const PromptInput: Component = (props) => { clearInput() client.session .shell({ - sessionID: session.id, + sessionID: session?.id || "", agent, model, command: text, @@ -1275,7 +1278,7 @@ export const PromptInput: Component = (props) => { clearInput() client.session .command({ - sessionID: session.id, + sessionID: session?.id || "", command: commandName, arguments: args.join(" "), agent, @@ -1348,18 +1351,18 @@ export const PromptInput: Component = (props) => { const contextParts: Array< | { - id: string - type: "text" - text: string - synthetic?: boolean - } + id: string + type: "text" + text: string + synthetic?: boolean + } | { - id: string - type: "file" - mime: string - url: string - filename?: string - } + id: string + type: "file" + mime: string + url: string + filename?: string + } > = [] const commentNote = (path: string, selection: FileSelection | undefined, comment: string) => { @@ -1431,13 +1434,13 @@ export const PromptInput: Component = (props) => { const optimisticParts = requestParts.map((part) => ({ ...part, - sessionID: session.id, + sessionID: session?.id || "", messageID, })) as unknown as Part[] const optimisticMessage: Message = { id: messageID, - sessionID: session.id, + sessionID: session?.id || "", role: "user", time: { created: Date.now() }, agent, @@ -1448,9 +1451,9 @@ export const PromptInput: Component = (props) => { if (sessionDirectory === projectDirectory) { sync.set( produce((draft) => { - const messages = draft.message[session.id] + const messages = draft.message[session?.id || ""] if (!messages) { - draft.message[session.id] = [optimisticMessage] + draft.message[session?.id || ""] = [optimisticMessage] } else { const result = Binary.search(messages, messageID, (m) => m.id) messages.splice(result.index, 0, optimisticMessage) @@ -1466,9 +1469,9 @@ export const PromptInput: Component = (props) => { globalSync.child(sessionDirectory)[1]( produce((draft) => { - const messages = draft.message[session.id] + const messages = draft.message[session?.id || ""] if (!messages) { - draft.message[session.id] = [optimisticMessage] + draft.message[session?.id || ""] = [optimisticMessage] } else { const result = Binary.search(messages, messageID, (m) => m.id) messages.splice(result.index, 0, optimisticMessage) @@ -1485,7 +1488,7 @@ export const PromptInput: Component = (props) => { if (sessionDirectory === projectDirectory) { sync.set( produce((draft) => { - const messages = draft.message[session.id] + const messages = draft.message[session?.id || ""] if (messages) { const result = Binary.search(messages, messageID, (m) => m.id) if (result.found) messages.splice(result.index, 1) @@ -1498,7 +1501,7 @@ export const PromptInput: Component = (props) => { globalSync.child(sessionDirectory)[1]( produce((draft) => { - const messages = draft.message[session.id] + const messages = draft.message[session?.id || ""] if (messages) { const result = Binary.search(messages, messageID, (m) => m.id) if (result.found) messages.splice(result.index, 1) @@ -1519,15 +1522,15 @@ export const PromptInput: Component = (props) => { const worktree = WorktreeState.get(sessionDirectory) if (!worktree || worktree.status !== "pending") return true - if (sessionDirectory === projectDirectory) { - sync.set("session_status", session.id, { type: "busy" }) + if (sessionDirectory === projectDirectory && session?.id) { + sync.set("session_status", session?.id, { type: "busy" }) } const controller = new AbortController() const cleanup = () => { - if (sessionDirectory === projectDirectory) { - sync.set("session_status", session.id, { type: "idle" }) + if (sessionDirectory === projectDirectory && session?.id) { + sync.set("session_status", session?.id, { type: "idle" }) } removeOptimisticMessage() for (const item of commentItems) { @@ -1544,7 +1547,7 @@ export const PromptInput: Component = (props) => { restoreInput() } - pending.set(session.id, { abort: controller, cleanup }) + pending.set(session?.id || "", { abort: controller, cleanup }) const abort = new Promise>>((resolve) => { if (controller.signal.aborted) { @@ -1572,7 +1575,7 @@ export const PromptInput: Component = (props) => { if (timer.id === undefined) return clearTimeout(timer.id) }) - pending.delete(session.id) + pending.delete(session?.id || "") if (controller.signal.aborted) return false if (result.status === "failed") throw new Error(result.message) return true @@ -1582,7 +1585,7 @@ export const PromptInput: Component = (props) => { const ok = await waitForWorktree() if (!ok) return await client.session.prompt({ - sessionID: session.id, + sessionID: session?.id || "", agent, model, messageID, @@ -1592,9 +1595,9 @@ export const PromptInput: Component = (props) => { } void send().catch((err) => { - pending.delete(session.id) - if (sessionDirectory === projectDirectory) { - sync.set("session_status", session.id, { type: "idle" }) + pending.delete(session?.id || "") + if (sessionDirectory === projectDirectory && session?.id) { + sync.set("session_status", session?.id, { type: "idle" }) } showToast({ title: language.t("prompt.toast.promptSendFailed.title"), @@ -1616,6 +1619,28 @@ export const PromptInput: Component = (props) => { }) } + const currrentModelVariant = createMemo(() => { + const modelVariant = local.model.variant.current() ?? "" + return modelVariant === "xhigh" + ? "xHigh" + : modelVariant.length > 0 + ? modelVariant[0].toUpperCase() + modelVariant.slice(1) + : "Default" + }) + + const reasoningPercentage = createMemo(() => { + const variants = local.model.variant.list() + const current = local.model.variant.current() + const totalEntries = variants.length + 1 + + if (totalEntries <= 2 || current === "Default") { + return 0 + } + + const currentIndex = current ? variants.indexOf(current) + 1 : 0 + return ((currentIndex + 1) / totalEntries) * 100 + }, [local.model.variant]) + return (
@@ -1668,7 +1693,7 @@ export const PromptInput: Component = (props) => { } > - + @{(item as { type: "agent"; name: string }).name} @@ -1729,9 +1754,9 @@ export const PromptInput: Component = (props) => { }} > -
+
- + {language.t("prompt.dropzone.label")}
@@ -1770,7 +1795,7 @@ export const PromptInput: Component = (props) => { }} >
- +
{getFilenameTruncated(item.path, 14)} @@ -1787,7 +1812,7 @@ export const PromptInput: Component = (props) => { type="button" icon="close-small" variant="ghost" - class="ml-auto h-5 w-5 opacity-0 group-hover:opacity-100 transition-all" + class="ml-auto size-7 opacity-0 group-hover:opacity-100 transition-all" onClick={(e) => { e.stopPropagation() if (item.commentID) comments.remove(item.path, item.commentID) @@ -1817,7 +1842,7 @@ export const PromptInput: Component = (props) => { when={attachment.mime.startsWith("image/")} fallback={
- +
} > @@ -1891,7 +1916,7 @@ export const PromptInput: Component = (props) => {
-
+
@@ -1922,12 +1947,17 @@ export const PromptInput: Component = (props) => { title={language.t("command.model.choose")} keybind={command.keybind("model.choose")} > - } @@ -1938,11 +1968,15 @@ export const PromptInput: Component = (props) => { keybind={command.keybind("model.choose")} > - - - - {local.model.current()?.name ?? language.t("dialog.model.select.title")} - + {(open) => ( + <> + + + + {local.model.current()?.name ?? language.t("dialog.model.select.title")} + + + )} @@ -1955,10 +1989,13 @@ export const PromptInput: Component = (props) => { @@ -1972,7 +2009,7 @@ export const PromptInput: Component = (props) => { variant="ghost" onClick={() => permission.toggleAutoAccept(params.id!, sdk.directory)} classList={{ - "_hidden group-hover/prompt-input:flex size-6 items-center justify-center": true, + "_hidden group-hover/prompt-input:flex items-center justify-center": true, "text-text-base": !permission.isAutoAccepting(params.id!, sdk.directory), "hover:bg-surface-success-base": permission.isAutoAccepting(params.id!, sdk.directory), }} @@ -1994,7 +2031,7 @@ export const PromptInput: Component = (props) => {
-
+
= (props) => { e.currentTarget.value = "" }} /> -
+
@@ -2036,7 +2074,7 @@ export const PromptInput: Component = (props) => {
{language.t("prompt.action.send")} - +
@@ -2047,7 +2085,7 @@ export const PromptInput: Component = (props) => { disabled={!prompt.dirty() && !working()} icon={working() ? "stop" : "arrow-up"} variant="primary" - class="h-6 w-4.5" + class="h-6 w-5.5" aria-label={working() ? language.t("prompt.action.stop") : language.t("prompt.action.send")} /> diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index 1e37d8f6a2..92b060212d 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -64,8 +64,8 @@ export function SessionContextUsage(props: SessionContextUsageProps) { } const circle = () => ( -
- +
+
) @@ -101,7 +101,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
+ ) } diff --git a/packages/app/src/components/settings-keybinds.tsx b/packages/app/src/components/settings-keybinds.tsx index 393da0c2ab..efd18c8bd6 100644 --- a/packages/app/src/components/settings-keybinds.tsx +++ b/packages/app/src/components/settings-keybinds.tsx @@ -9,6 +9,7 @@ import fuzzysort from "fuzzysort" import { formatKeybind, parseKeybind, useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { useSettings } from "@/context/settings" +import { ScrollFade } from "@opencode-ai/ui/scroll-fade" const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) const PALETTE_ID = "command.palette" @@ -352,7 +353,12 @@ export const SettingsKeybinds: Component = () => { }) return ( -
+
@@ -429,6 +435,6 @@ export const SettingsKeybinds: Component = () => {
-
+
) } diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs index 29ac86f29a..d16416c9f2 100644 --- a/packages/desktop/src-tauri/src/lib.rs +++ b/packages/desktop/src-tauri/src/lib.rs @@ -345,6 +345,7 @@ pub fn run() { .decorations(false); let window = window_builder.build().expect("Failed to create window"); + let _ = window.show(); #[cfg(windows)] let _ = window.create_overlay_titlebar(); diff --git a/packages/ui/src/components/accordion.css b/packages/ui/src/components/accordion.css index 7bf287fe54..441bd0542f 100644 --- a/packages/ui/src/components/accordion.css +++ b/packages/ui/src/components/accordion.css @@ -1,98 +1,107 @@ [data-component="accordion"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - align-self: stretch; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + align-self: stretch; - [data-slot="accordion-item"] { - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - overflow: clip; + [data-slot="accordion-item"] { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + overflow: clip; - [data-slot="accordion-header"] { - width: 100%; - display: flex; - align-items: center; - margin: 0; - padding: 0; + [data-slot="accordion-header"] { + width: 100%; + display: flex; + align-items: center; + margin: 0; + padding: 0; - [data-slot="accordion-trigger"] { - width: 100%; - display: flex; - height: 32px; - padding: 8px 12px; - justify-content: space-between; - align-items: center; - align-self: stretch; - cursor: default; - user-select: none; + [data-slot="accordion-trigger"] { + width: 100%; + display: flex; + height: 32px; + padding: 8px 12px; + justify-content: space-between; + align-items: center; + align-self: stretch; + cursor: default; + user-select: none; - background-color: var(--surface-base); - border: 1px solid var(--border-weak-base); - border-radius: var(--radius-md); - overflow: clip; - color: var(--text-strong); - transition: background-color 0.15s ease; + background-color: var(--surface-base); + border: 1px solid var(--border-weak-base); + border-radius: var(--radius-md); + overflow: clip; + color: var(--text-strong); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &:hover { - background-color: var(--surface-base); - } - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } - } - } + &:hover { + background-color: var(--surface-base); + } + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } + } + } - &[data-expanded] { - [data-slot="accordion-trigger"] { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } + [data-slot="accordion-arrow"] { + flex-shrink: 0; + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } - [data-slot="accordion-content"] { - border: 1px solid var(--border-weak-base); - border-top: none; - border-bottom-left-radius: var(--radius-md); - border-bottom-right-radius: var(--radius-md); - } - } + [data-slot="accordion-content"] { + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + width: 100%; - [data-slot="accordion-content"] { - overflow: hidden; - width: 100%; - } - } -} - -@keyframes slideDown { - from { - height: 0; - } - to { - height: var(--kb-accordion-content-height); - } -} - -@keyframes slideUp { - from { - height: var(--kb-accordion-content-height); - } - to { - height: 0; - } + > * { + overflow: hidden; + } + } + + [data-slot="accordion-content"][data-expanded] { + grid-template-rows: 1fr; + } + + [data-slot="accordion-content"][data-closed] { + grid-template-rows: 0fr; + } + + &[data-expanded] [data-slot="accordion-trigger"] { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + &[data-expanded] [data-slot="accordion-content"] { + border: 1px solid var(--border-weak-base); + border-top: none; + border-bottom-left-radius: var(--radius-md); + border-bottom-right-radius: var(--radius-md); + height: auto; + } + } } diff --git a/packages/ui/src/components/accordion.tsx b/packages/ui/src/components/accordion.tsx index 535d38e3d0..e30be95e05 100644 --- a/packages/ui/src/components/accordion.tsx +++ b/packages/ui/src/components/accordion.tsx @@ -1,6 +1,7 @@ import { Accordion as Kobalte } from "@kobalte/core/accordion" -import { splitProps } from "solid-js" +import { Accessor, createContext, splitProps, useContext } from "solid-js" import type { ComponentProps, ParentProps } from "solid-js" +import { MorphChevron } from "./morph-chevron" export interface AccordionProps extends ComponentProps {} export interface AccordionItemProps extends ComponentProps {} @@ -8,6 +9,8 @@ export interface AccordionHeaderProps extends ComponentProps {} export interface AccordionContentProps extends ComponentProps {} +const AccordionItemContext = createContext>() + function AccordionRoot(props: AccordionProps) { const [split, rest] = splitProps(props, ["class", "classList"]) return ( @@ -22,17 +25,19 @@ function AccordionRoot(props: AccordionProps) { ) } -function AccordionItem(props: AccordionItemProps) { - const [split, rest] = splitProps(props, ["class", "classList"]) +function AccordionItem(props: AccordionItemProps & { expanded?: boolean }) { + const [split, rest] = splitProps(props, ["class", "classList", "expanded"]) return ( - + split.expanded ?? false}> + + ) } @@ -84,9 +89,25 @@ function AccordionContent(props: ParentProps) { ) } +export interface AccordionArrowProps extends ComponentProps<"div"> { + expanded?: boolean +} + +function AccordionArrow(props: AccordionArrowProps = {}) { + const [local, rest] = splitProps(props, ["expanded"]) + const contextExpanded = useContext(AccordionItemContext) + const isExpanded = () => local.expanded ?? contextExpanded?.() ?? false + return ( +
+ +
+ ) +} + export const Accordion = Object.assign(AccordionRoot, { Item: AccordionItem, Header: AccordionHeader, Trigger: AccordionTrigger, Content: AccordionContent, + Arrow: AccordionArrow, }) diff --git a/packages/ui/src/components/avatar.css b/packages/ui/src/components/avatar.css index 5872160771..dff6bb7b89 100644 --- a/packages/ui/src/components/avatar.css +++ b/packages/ui/src/components/avatar.css @@ -1,49 +1,49 @@ [data-component="avatar"] { - --avatar-bg: var(--color-surface-info-base); - --avatar-fg: var(--color-text-base); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - border-radius: var(--radius-sm); - border: 1px solid var(--color-border-weak-base); - font-family: var(--font-mono); - font-weight: 500; - text-transform: uppercase; - background-color: var(--avatar-bg); - color: var(--avatar-fg); + --avatar-bg: var(--color-surface-info-base); + --avatar-fg: var(--color-text-base); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + border-radius: var(--radius-sm); + border: 1px solid var(--color-border-weak-base); + font-family: var(--font-mono); + font-weight: 500; + text-transform: uppercase; + background-color: var(--avatar-bg); + color: var(--avatar-fg); } [data-component="avatar"][data-has-image] { - background-color: transparent; - border: none; + background-color: transparent; + border: none; } [data-component="avatar"][data-size="small"] { - width: 1.25rem; - height: 1.25rem; - font-size: 0.75rem; - line-height: 1; + width: 1.25rem; + height: 1.25rem; + font-size: 0.75rem; + line-height: 1; } [data-component="avatar"][data-size="normal"] { - width: 1.5rem; - height: 1.5rem; - font-size: 1.125rem; - line-height: 1.5rem; + width: 1.5rem; + height: 1.5rem; + font-size: 1.125rem; + line-height: 1.5rem; } [data-component="avatar"][data-size="large"] { - width: 2rem; - height: 2rem; - font-size: 1.25rem; - line-height: 2rem; + width: 2rem; + height: 2rem; + font-size: 1.25rem; + line-height: 2rem; } [data-component="avatar"] [data-slot="avatar-image"] { - width: 100%; - height: 100%; - display: block; - object-fit: cover; - border-radius: inherit; + width: 100%; + height: 100%; + display: block; + object-fit: cover; + border-radius: inherit; } diff --git a/packages/ui/src/components/basic-tool.css b/packages/ui/src/components/basic-tool.css index 2c6bfeb672..cc58cfa730 100644 --- a/packages/ui/src/components/basic-tool.css +++ b/packages/ui/src/components/basic-tool.css @@ -1,97 +1,97 @@ [data-component="tool-trigger"] { - content-visibility: auto; - width: 100%; - display: flex; - align-items: center; - align-self: stretch; - gap: 20px; - justify-content: space-between; + content-visibility: auto; + width: 100%; + display: flex; + align-items: center; + align-self: stretch; + gap: 20px; + justify-content: space-between; - [data-slot="basic-tool-tool-trigger-content"] { - width: 100%; - display: flex; - align-items: center; - align-self: stretch; - gap: 20px; - } + [data-slot="basic-tool-tool-trigger-content"] { + width: 100%; + display: flex; + align-items: center; + align-self: stretch; + gap: 20px; + } - [data-slot="icon-svg"] { - flex-shrink: 0; - } + [data-slot="icon-svg"] { + flex-shrink: 0; + } - [data-slot="basic-tool-tool-info"] { - flex-grow: 1; - min-width: 0; - } + [data-slot="basic-tool-tool-info"] { + flex-grow: 1; + min-width: 0; + } - [data-slot="basic-tool-tool-info-structured"] { - width: 100%; - display: flex; - align-items: center; - gap: 8px; - justify-content: space-between; - } + [data-slot="basic-tool-tool-info-structured"] { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + justify-content: space-between; + } - [data-slot="basic-tool-tool-info-main"] { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - overflow: hidden; - } + [data-slot="basic-tool-tool-info-main"] { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + overflow: hidden; + } - [data-slot="basic-tool-tool-title"] { - flex-shrink: 0; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); + [data-slot="basic-tool-tool-title"] { + flex-shrink: 0; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); - &.capitalize { - text-transform: capitalize; - } - } + &.capitalize { + text-transform: capitalize; + } + } - [data-slot="basic-tool-tool-subtitle"] { - flex-shrink: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); + [data-slot="basic-tool-tool-subtitle"] { + flex-shrink: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); - &.clickable { - cursor: pointer; - text-decoration: underline; - transition: color 0.15s ease; + &.clickable { + cursor: pointer; + text-decoration: underline; + transition: color 0.15s ease; - &:hover { - color: var(--text-base); - } - } - } + &:hover { + color: var(--text-base); + } + } + } - [data-slot="basic-tool-tool-arg"] { - flex-shrink: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - } + [data-slot="basic-tool-tool-arg"] { + flex-shrink: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } } diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index d9b3459230..56258bd84e 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -1,172 +1,168 @@ [data-component="button"] { - display: inline-flex; - align-items: center; - justify-content: center; - border-style: solid; - border-width: 1px; - border-radius: var(--radius-md); - text-decoration: none; - user-select: none; - cursor: default; - outline: none; - white-space: nowrap; + display: inline-flex; + align-items: center; + justify-content: center; + border-style: solid; + border-width: 1px; + border-radius: var(--radius-md); + text-decoration: none; + user-select: none; + cursor: default; + padding: 4px 8px; + white-space: nowrap; + transition-property: + background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + outline: none; + line-height: 20px; - &[data-variant="primary"] { - background-color: var(--button-primary-base); - border-color: var(--border-weak-base); - color: var(--icon-invert-base); + &[data-variant="primary"] { + background-color: var(--button-primary-base); + border-color: var(--border-weak-base); + color: var(--icon-invert-base); - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } - &:hover:not(:disabled) { - background-color: var(--icon-strong-hover); - } - &:focus:not(:disabled) { - background-color: var(--icon-strong-focus); - } - &:active:not(:disabled) { - background-color: var(--icon-strong-active); - } - &:disabled { - background-color: var(--icon-strong-disabled); + &:hover:not(:disabled) { + background-color: var(--icon-strong-hover); + } + &:focus:not(:disabled) { + background-color: var(--icon-strong-focus); + } + &:active:not(:disabled) { + background-color: var(--icon-strong-active); + } + &:disabled { + background-color: var(--icon-strong-disabled); - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - } - } + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + } + } - &[data-variant="ghost"] { - border-color: transparent; - background-color: transparent; - color: var(--text-strong); + &[data-variant="ghost"] { + border-color: transparent; + background-color: transparent; + color: var(--text-strong); - [data-slot="icon-svg"] { - color: var(--icon-base); - } + [data-slot="icon-svg"] { + color: var(--icon-base); + } - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - &:disabled { - color: var(--text-weak); - cursor: not-allowed; + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:focus-visible:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + &:disabled { + color: var(--text-weak); + cursor: not-allowed; - [data-slot="icon-svg"] { - color: var(--icon-disabled); - } - } - &[data-selected="true"]:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &[data-active="true"] { - background-color: var(--surface-raised-base-active); - } - } + [data-slot="icon-svg"] { + color: var(--icon-disabled); + } + } + &[data-selected="true"]:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &[data-active="true"] { + background-color: var(--surface-raised-base-active); + } + } - &[data-variant="secondary"] { - border: transparent; - background-color: var(--button-secondary-base); - color: var(--text-strong); - box-shadow: var(--shadow-xs-border); + &[data-variant="secondary"] { + border: transparent; + background-color: var(--button-secondary-base); + color: var(--text-strong); + box-shadow: var(--shadow-xs-border); - &:hover:not(:disabled) { - background-color: var(--button-secondary-hover); - } - &:focus:not(:disabled) { - background-color: var(--button-secondary-base); - } - &:focus-visible:not(:active) { - background-color: var(--button-secondary-base); - box-shadow: var(--shadow-xs-border-focus); - } - &:focus-visible:active { - box-shadow: none; - } - &:active:not(:disabled) { - background-color: var(--button-secondary-base); - scale: 0.99; - transition: all 150ms ease-out; - } - &:disabled { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - color: var(--text-weak); - cursor: not-allowed; - } + &:hover:not(:disabled) { + background-color: var(--button-secondary-hover); + } + &:focus:not(:disabled) { + background-color: var(--button-secondary-base); + } + &:focus-visible:not(:active) { + background-color: var(--button-secondary-base); + box-shadow: var(--shadow-xs-border-focus); + } + &:focus-visible:active { + box-shadow: none; + } + &:active:not(:disabled) { + background-color: var(--button-secondary-base); + scale: 0.99; + } + &:disabled { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + color: var(--text-weak); + cursor: not-allowed; + } - [data-slot="icon-svg"] { - color: var(--icon-strong-base); - } - } + [data-slot="icon-svg"] { + color: var(--icon-strong-base); + } + } - &[data-size="small"] { - height: 22px; - padding: 0 8px; - &[data-icon] { - padding: 0 12px 0 4px; - } + &[data-size="small"] { + padding: 2px 8px; + &[data-icon] { + padding: 2px 12px 2px 4px; + } - font-size: var(--font-size-small); - line-height: var(--line-height-large); - gap: 4px; + gap: 4px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } - &[data-size="normal"] { - height: 24px; - line-height: 24px; - padding: 0 6px; - &[data-icon] { - padding: 0 12px 0 4px; - } + &[data-size="normal"] { + padding: 4px 6px; + &[data-icon] { + padding: 4px 12px 4px 4px; + } - font-size: var(--font-size-small); - gap: 6px; + gap: 6px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } - &[data-size="large"] { - height: 32px; - padding: 6px 12px; + &[data-size="large"] { + padding: 6px 12px; - &[data-icon] { - padding: 0 12px 0 8px; - } + &[data-icon] { + padding: 6px 12px 6px 8px; + } - gap: 4px; + gap: 4px; - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } - &:focus { - outline: none; - } + &:focus { + outline: none; + } } diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx index 7f974b2f76..b2d2004d3c 100644 --- a/packages/ui/src/components/button.tsx +++ b/packages/ui/src/components/button.tsx @@ -4,7 +4,7 @@ import { Icon, IconProps } from "./icon" export interface ButtonProps extends ComponentProps, - Pick, "class" | "classList" | "children"> { + Pick, "class" | "classList" | "children" | "style"> { size?: "small" | "normal" | "large" variant?: "primary" | "secondary" | "ghost" icon?: IconProps["name"] diff --git a/packages/ui/src/components/card.css b/packages/ui/src/components/card.css index 6dae47223d..8ac8390421 100644 --- a/packages/ui/src/components/card.css +++ b/packages/ui/src/components/card.css @@ -1,29 +1,31 @@ [data-component="card"] { - width: 100%; - display: flex; - flex-direction: column; - background-color: var(--surface-inset-base); - border: 1px solid var(--border-weaker-base); - transition: background-color 0.15s ease; - border-radius: var(--radius-md); - padding: 6px 12px; - overflow: clip; + width: 100%; + display: flex; + flex-direction: column; + background-color: var(--surface-inset-base); + border: 1px solid var(--border-weaker-base); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + border-radius: var(--radius-md); + padding: 6px 12px; + overflow: clip; - &[data-variant="error"] { - background-color: var(--surface-critical-weak); - border: 1px solid var(--border-critical-base); - color: rgba(218, 51, 25, 0.6); + &[data-variant="error"] { + background-color: var(--surface-critical-weak); + border: 1px solid var(--border-critical-base); + color: rgba(218, 51, 25, 0.6); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &[data-component="icon"] { - color: var(--icon-critical-active); - } - } + &[data-component="icon"] { + color: var(--icon-critical-active); + } + } } diff --git a/packages/ui/src/components/checkbox.css b/packages/ui/src/components/checkbox.css index b10ebbbd19..44cb1d8ae6 100644 --- a/packages/ui/src/components/checkbox.css +++ b/packages/ui/src/components/checkbox.css @@ -1,121 +1,136 @@ [data-component="checkbox"] { - display: flex; - align-items: center; - gap: 12px; - cursor: default; + display: flex; + align-items: center; + gap: 12px; + cursor: default; - [data-slot="checkbox-checkbox-input"] { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } + [data-slot="checkbox-checkbox-control"] { + transition-property: border-color, background-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="checkbox-checkbox-control"] { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - padding: 2px; - aspect-ratio: 1; - flex-shrink: 0; - border-radius: var(--radius-sm); - border: 1px solid var(--border-weak-base); - /* background-color: var(--surface-weak); */ - } + [data-slot="checkbox-checkbox-indicator"] { + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="checkbox-checkbox-indicator"] { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - color: var(--icon-base); - opacity: 0; - } + [data-slot="checkbox-checkbox-input"] { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } - /* [data-slot="checkbox-checkbox-content"] { */ - /* } */ + [data-slot="checkbox-checkbox-control"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + padding: 2px; + aspect-ratio: 1; + flex-shrink: 0; + border-radius: var(--radius-sm); + border: 1px solid var(--border-weak-base); + /* background-color: var(--surface-weak); */ + } - [data-slot="checkbox-checkbox-label"] { - user-select: none; - color: var(--text-base); + [data-slot="checkbox-checkbox-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + color: var(--icon-base); + opacity: 0; + } - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* [data-slot="checkbox-checkbox-content"] { */ + /* } */ - [data-slot="checkbox-checkbox-description"] { - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="checkbox-checkbox-label"] { + user-select: none; + color: var(--text-base); - [data-slot="checkbox-checkbox-error"] { - color: var(--text-error); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } - &:hover:not([data-disabled], [data-readonly]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + [data-slot="checkbox-checkbox-description"] { + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - &:focus-within:not([data-readonly]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-focus); - box-shadow: 0 0 0 2px var(--surface-focus); - } + [data-slot="checkbox-checkbox-error"] { + color: var(--text-error); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - &[data-checked] [data-slot="checkbox-checkbox-control"], - &[data-indeterminate] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-base); - background-color: var(--surface-weak); - } + &:hover:not([data-disabled], [data-readonly]) + [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &[data-checked]:hover:not([data-disabled], [data-readonly]) [data-slot="checkbox-checkbox-control"], - &[data-indeterminate]:hover:not([data-disabled]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &:focus-within:not([data-readonly]) [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-focus); + box-shadow: 0 0 0 2px var(--surface-focus); + } - &[data-checked] [data-slot="checkbox-checkbox-indicator"], - &[data-indeterminate] [data-slot="checkbox-checkbox-indicator"] { - opacity: 1; - } + &[data-checked] [data-slot="checkbox-checkbox-control"], + &[data-indeterminate] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-base); + background-color: var(--surface-weak); + } - &[data-disabled] { - cursor: not-allowed; - } + &[data-checked]:hover:not([data-disabled], [data-readonly]) + [data-slot="checkbox-checkbox-control"], + &[data-indeterminate]:hover:not([data-disabled]) + [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &[data-disabled] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - } + &[data-checked] [data-slot="checkbox-checkbox-indicator"], + &[data-indeterminate] [data-slot="checkbox-checkbox-indicator"] { + opacity: 1; + } - &[data-invalid] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-error); - } + &[data-disabled] { + cursor: not-allowed; + } - &[data-readonly] { - cursor: default; - pointer-events: none; - } + &[data-disabled] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + } + + &[data-invalid] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-error); + } + + &[data-readonly] { + cursor: default; + pointer-events: none; + } } diff --git a/packages/ui/src/components/code.css b/packages/ui/src/components/code.css index 671b40512d..553219bb86 100644 --- a/packages/ui/src/components/code.css +++ b/packages/ui/src/components/code.css @@ -1,4 +1,4 @@ [data-component="code"] { - content-visibility: auto; - overflow: hidden; + content-visibility: auto; + overflow: hidden; } diff --git a/packages/ui/src/components/collapsible.css b/packages/ui/src/components/collapsible.css index 1f20cf85d9..312eec84a8 100644 --- a/packages/ui/src/components/collapsible.css +++ b/packages/ui/src/components/collapsible.css @@ -1,103 +1,99 @@ [data-component="collapsible"] { - width: 100%; - display: flex; - flex-direction: column; - background-color: var(--surface-inset-base); - border: 1px solid var(--border-weaker-base); - transition: background-color 0.15s ease; - border-radius: var(--radius-md); - overflow: clip; + width: 100%; + display: flex; + flex-direction: column; + background-color: var(--surface-inset-base); + border: 1px solid var(--border-weaker-base); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + border-radius: var(--radius-md); + overflow: clip; - [data-slot="collapsible-trigger"] { - width: 100%; - display: flex; - height: 32px; - padding: 6px 8px 6px 12px; - align-items: center; - align-self: stretch; - cursor: default; - user-select: none; - color: var(--text-base); + [data-slot="collapsible-trigger"] { + width: 100%; + display: flex; + height: 32px; + padding: 6px 8px 6px 12px; + align-items: center; + align-self: stretch; + cursor: default; + user-select: none; + color: var(--text-base); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - /* &:hover { */ - /* background-color: var(--surface-base); */ - /* } */ - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } + /* &:hover { */ + /* background-color: var(--surface-base); */ + /* } */ + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } - [data-slot="collapsible-arrow"] { - flex-shrink: 0; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - } - } + [data-slot="collapsible-arrow"] { + flex-shrink: 0; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } + } - [data-slot="collapsible-content"] { - overflow: hidden; - /* animation: slideUp 250ms ease-out; */ + [data-slot="collapsible-content"] { + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - /* &[data-expanded] { */ - /* animation: slideDown 250ms ease-out; */ - /* } */ - } + > * { + overflow: hidden; + } - &[data-variant="ghost"] { - background-color: transparent; - border: none; + &[data-expanded] { + grid-template-rows: 1fr; + } - > [data-slot="collapsible-trigger"] { - background-color: transparent; - border: none; - padding: 0; + &[data-closed] { + grid-template-rows: 0fr; + } + } - /* &:hover { */ - /* color: var(--text-strong); */ - /* } */ - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } - } - } + &[data-variant="ghost"] { + background-color: transparent; + border: none; - &[data-variant="ghost"][data-scope="filetree"] { - > [data-slot="collapsible-trigger"] { - height: 24px; - } - } -} - -@keyframes slideDown { - from { - height: 0; - } - to { - height: var(--kb-collapsible-content-height); - } -} - -@keyframes slideUp { - from { - height: var(--kb-collapsible-content-height); - } - to { - height: 0; - } + > [data-slot="collapsible-trigger"] { + background-color: transparent; + border: none; + padding: 0; + + /* &:hover { */ + /* color: var(--text-strong); */ + /* } */ + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } + } + } + + &[data-variant="ghost"][data-scope="filetree"] { + > [data-slot="collapsible-trigger"] { + height: 24px; + } + } } diff --git a/packages/ui/src/components/collapsible.tsx b/packages/ui/src/components/collapsible.tsx index 903afc3085..55b7b60333 100644 --- a/packages/ui/src/components/collapsible.tsx +++ b/packages/ui/src/components/collapsible.tsx @@ -1,6 +1,8 @@ import { Collapsible as Kobalte, CollapsibleRootProps } from "@kobalte/core/collapsible" -import { ComponentProps, ParentProps, splitProps } from "solid-js" -import { Icon } from "./icon" +import { Accessor, ComponentProps, createContext, createSignal, ParentProps, splitProps, useContext } from "solid-js" +import { MorphChevron } from "./morph-chevron" + +const CollapsibleContext = createContext>() export interface CollapsibleProps extends ParentProps { class?: string @@ -9,17 +11,30 @@ export interface CollapsibleProps extends ParentProps { } function CollapsibleRoot(props: CollapsibleProps) { - const [local, others] = splitProps(props, ["class", "classList", "variant"]) + const [local, others] = splitProps(props, ["class", "classList", "variant", "open", "onOpenChange", "children"]) + const [internalOpen, setInternalOpen] = createSignal(local.open ?? false) + + const handleOpenChange = (open: boolean) => { + setInternalOpen(open) + local.onOpenChange?.(open) + } + return ( - + + + {local.children} + + ) } @@ -32,9 +47,10 @@ function CollapsibleContent(props: ComponentProps) { } function CollapsibleArrow(props?: ComponentProps<"div">) { + const isOpen = useContext(CollapsibleContext) return (
- +
) } diff --git a/packages/ui/src/components/cycle-label.css b/packages/ui/src/components/cycle-label.css new file mode 100644 index 0000000000..46a6408f01 --- /dev/null +++ b/packages/ui/src/components/cycle-label.css @@ -0,0 +1,52 @@ +.cycle-label { + --c-dur: 200ms; + --c-stag: 30ms; + --c-ease: cubic-bezier(0.25, 0, 0.5, 1); + --c-opacity-start: 0; + --c-opacity-end: 1; + --c-blur-start: 0px; + --c-blur-end: 0px; + --c-skew: 10deg; + + display: inline-flex; + position: relative; + + transform-style: preserve-3d; + perspective: 500px; + transition: width 200ms var(--c-ease); + will-change: width; + overflow: hidden; + + .cycle-char { + display: inline-block; + transform-style: preserve-3d; + min-width: 0.25em; + backface-visibility: hidden; + + transition: + transform var(--c-dur) var(--c-ease), + opacity var(--c-dur) var(--c-ease), + filter var(--c-dur) var(--c-ease); + transition-delay: calc(var(--i, 0) * var(--c-stag)); + + &.enter { + opacity: var(--c-opacity-end); + filter: blur(var(--c-blur-end)); + transform: translateY(0) rotateX(0) skewX(0); + } + + &.exit { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); + } + + &.pre { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transition: none; + transform: translateY(-50%) rotateX(-90deg) + skewX(calc(var(--c-skew) * -1)); + } + } +} diff --git a/packages/ui/src/components/cycle-label.tsx b/packages/ui/src/components/cycle-label.tsx new file mode 100644 index 0000000000..e34385a2c2 --- /dev/null +++ b/packages/ui/src/components/cycle-label.tsx @@ -0,0 +1,132 @@ +import "./cycle-label.css" +import { createEffect, createSignal, JSX, on } from "solid-js" + +export interface CycleLabelProps extends JSX.HTMLAttributes { + value: string + onValueChange?: (value: string) => void + duration?: number | ((value: string) => number) + stagger?: number + opacity?: [number, number] + blur?: [number, number] + skewX?: number + onAnimationStart?: () => void + onAnimationEnd?: () => void +} + +const segmenter = + typeof Intl !== "undefined" && Intl.Segmenter ? new Intl.Segmenter("en", { granularity: "grapheme" }) : null + +const getChars = (text: string): string[] => + segmenter ? Array.from(segmenter.segment(text), (s) => s.segment) : text.split("") + +const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + +export function CycleLabel(props: CycleLabelProps) { + const getDuration = (text: string) => { + const d = props?.duration ?? 200 + return typeof d === "function" ? d(text) : d + } + const stagger = () => props?.stagger ?? 20 + const opacity = () => props?.opacity ?? [0, 1] + const blur = () => props?.blur ?? [0, 0] + const skewX = () => props?.skewX ?? 10 + + let containerRef: HTMLSpanElement | undefined + let isAnimating = false + const [currentText, setCurrentText] = createSignal(props.value) + + const setChars = (el: HTMLElement, text: string, state: "enter" | "exit" | "pre" = "enter") => { + el.innerHTML = "" + const chars = getChars(text) + chars.forEach((char, i) => { + const span = document.createElement("span") + span.textContent = char === " " ? "\u00A0" : char + span.className = `cycle-char ${state}` + span.style.setProperty("--i", String(i)) + el.appendChild(span) + }) + } + + const animateToText = async (newText: string) => { + if (!containerRef || isAnimating) return + if (newText === currentText()) return + + isAnimating = true + props.onAnimationStart?.() + + const dur = getDuration(newText) + const stag = stagger() + + containerRef.style.width = containerRef.offsetWidth + "px" + + const oldChars = containerRef.querySelectorAll(".cycle-char") + oldChars.forEach((c) => c.classList.replace("enter", "exit")) + + const clone = containerRef.cloneNode(false) as HTMLElement + Object.assign(clone.style, { + position: "absolute", + visibility: "hidden", + width: "auto", + transition: "none", + }) + setChars(clone, newText) + document.body.appendChild(clone) + const nextWidth = clone.offsetWidth + clone.remove() + + const exitTime = oldChars.length * stag + dur + await wait(exitTime * 0.3) + + containerRef.style.width = nextWidth + "px" + + const widthDur = 200 + await wait(widthDur * 0.3) + + setChars(containerRef, newText, "pre") + containerRef.offsetWidth + + Array.from(containerRef.children).forEach((c) => (c.className = "cycle-char enter")) + setCurrentText(newText) + props.onValueChange?.(newText) + + const enterTime = getChars(newText).length * stag + dur + await wait(enterTime) + + containerRef.style.width = "" + isAnimating = false + props.onAnimationEnd?.() + } + + createEffect( + on( + () => props.value, + (newValue) => { + if (newValue !== currentText()) { + animateToText(newValue) + } + }, + ), + ) + + const initRef = (el: HTMLSpanElement) => { + containerRef = el + setChars(el, props.value) + } + + return ( + + ) +} diff --git a/packages/ui/src/components/dialog.css b/packages/ui/src/components/dialog.css index 2e66b644fc..5ff9ec595b 100644 --- a/packages/ui/src/components/dialog.css +++ b/packages/ui/src/components/dialog.css @@ -1,181 +1,196 @@ /* [data-component="dialog-trigger"] { } */ [data-component="dialog-overlay"] { - position: fixed; - inset: 0; - z-index: 50; - background-color: hsl(from var(--background-base) h s l / 0.2); + position: fixed; + inset: 0; + z-index: 50; + background-color: hsl(from var(--background-base) h s l / 0.2); + + animation: overlayHide var(--transition-duration) var(--transition-easing) + forwards; + + &[data-expanded] { + animation: overlayShow var(--transition-duration) var(--transition-easing) + forwards; + } + + @starting-style { + animation: none; + } } [data-component="dialog"] { - position: fixed; - inset: 0; - z-index: 50; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; + position: fixed; + inset: 0; + z-index: 50; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; - [data-slot="dialog-container"] { - position: relative; - z-index: 50; - width: min(calc(100vw - 16px), 640px); - height: min(calc(100vh - 16px), 512px); - display: flex; - flex-direction: column; - align-items: center; - justify-items: start; - overflow: visible; + [data-slot="dialog-container"] { + position: relative; + z-index: 50; + width: min(calc(100vw - 16px), 640px); + height: min(calc(100vh - 16px), 512px); + display: flex; + flex-direction: column; + align-items: center; + justify-items: start; - [data-slot="dialog-content"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - width: 100%; - max-height: 100%; - min-height: 280px; - overflow: auto; - pointer-events: auto; + [data-slot="dialog-content"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + width: 100%; + max-height: 100%; + min-height: 280px; + pointer-events: auto; - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + /* padding: 8px; */ + /* padding: 8px 8px 0 8px; */ + border-radius: var(--radius-xl); + background: var(--surface-raised-stronger-non-alpha); + background-clip: padding-box; + box-shadow: var(--shadow-lg-border-base); - /* padding: 8px; */ - /* padding: 8px 8px 0 8px; */ - border-radius: var(--radius-xl); - background: var(--surface-raised-stronger-non-alpha); - background-clip: padding-box; - box-shadow: var(--shadow-lg-border-base); + animation: contentHide var(--transition-duration) var(--transition-easing) + forwards; - [data-slot="dialog-header"] { - display: flex; - padding: 20px; - justify-content: space-between; - align-items: center; - flex-shrink: 0; - align-self: stretch; + &[data-expanded] { + animation: contentShow var(--transition-duration) + var(--transition-easing) forwards; + } - [data-slot="dialog-title"] { - color: var(--text-strong); + @starting-style { + animation: none; + } - /* text-16-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 150% */ - letter-spacing: var(--letter-spacing-tight); - } - /* [data-slot="dialog-close-button"] {} */ - } + [data-slot="dialog-header"] { + display: flex; + padding: 20px; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; - [data-slot="dialog-description"] { - display: flex; - padding: 16px; - padding-left: 24px; - padding-top: 0; - margin-top: -8px; - justify-content: space-between; - align-items: center; - flex-shrink: 0; - align-self: stretch; + [data-slot="dialog-title"] { + color: var(--text-strong); - color: var(--text-base); + /* text-16-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 150% */ + letter-spacing: var(--letter-spacing-tight); + } + /* [data-slot="dialog-close-button"] {} */ + } - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="dialog-description"] { + display: flex; + padding: 16px; + padding-left: 24px; + padding-top: 0; + margin-top: -8px; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; - [data-slot="dialog-body"] { - width: 100%; - position: relative; - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; + color: var(--text-base); - &:focus-visible { - outline: none; - } - } - &:focus-visible { - outline: none; - } - } - } + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } - &[data-fit] { - [data-slot="dialog-container"] { - height: auto; + [data-slot="dialog-body"] { + width: 100%; + position: relative; + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; - [data-slot="dialog-content"] { - min-height: 0; - } - } - } + &:focus-visible { + outline: none; + } + } + &:focus-visible { + outline: none; + } + } + } - &[data-size="large"] [data-slot="dialog-container"] { - width: min(calc(100vw - 32px), 800px); - height: min(calc(100vh - 32px), 600px); - } + &[data-fit] { + [data-slot="dialog-container"] { + height: auto; - &[data-size="x-large"] [data-slot="dialog-container"] { - width: min(calc(100vw - 32px), 960px); - height: min(calc(100vh - 32px), 600px); - } + [data-slot="dialog-content"] { + min-height: 0; + } + } + } + + &[data-size="large"] [data-slot="dialog-container"] { + width: min(calc(100vw - 32px), 800px); + height: min(calc(100vh - 32px), 600px); + } + + &[data-size="x-large"] [data-slot="dialog-container"] { + width: min(calc(100vw - 32px), 960px); + height: min(calc(100vh - 32px), 600px); + } } [data-component="dialog"][data-transition] [data-slot="dialog-content"] { - animation: contentHide 100ms ease-in forwards; + animation: contentHide 100ms ease-in forwards; - &[data-expanded] { - animation: contentShow 150ms ease-out; - } + &[data-expanded] { + animation: contentShow 150ms ease-out; + } } @keyframes overlayShow { - from { - opacity: 0; - } - to { - opacity: 1; - } + from { + opacity: 0; + } + to { + opacity: 1; + } } @keyframes overlayHide { - from { - opacity: 1; - } - to { - opacity: 0; - } + from { + opacity: 1; + } + to { + opacity: 0; + } } @keyframes contentShow { - from { - opacity: 0; - transform: scale(0.98); - } - to { - opacity: 1; - transform: scale(1); - } + from { + opacity: 0; + transform: translateY(2.5%) scale(0.975); + } + to { + opacity: 1; + transform: scale(1); + } } @keyframes contentHide { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.98); - } + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: translateY(-2.5%) scale(0.975); + } } diff --git a/packages/ui/src/components/diff-changes.css b/packages/ui/src/components/diff-changes.css index be3cca885d..6e0c3d01ba 100644 --- a/packages/ui/src/components/diff-changes.css +++ b/packages/ui/src/components/diff-changes.css @@ -1,41 +1,41 @@ [data-component="diff-changes"] { - display: flex; - gap: 8px; - justify-content: flex-end; - align-items: center; + display: flex; + gap: 8px; + justify-content: flex-end; + align-items: center; - [data-slot="diff-changes-additions"] { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - text-align: right; - color: var(--text-diff-add-base); - } + [data-slot="diff-changes-additions"] { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + text-align: right; + color: var(--text-diff-add-base); + } - [data-slot="diff-changes-deletions"] { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - text-align: right; - color: var(--text-diff-delete-base); - } + [data-slot="diff-changes-deletions"] { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + text-align: right; + color: var(--text-diff-delete-base); + } } [data-component="diff-changes"][data-variant="bars"] { - width: 18px; - flex-shrink: 0; + width: 18px; + flex-shrink: 0; - svg { - display: block; - width: 100%; - height: auto; - } + svg { + display: block; + width: 100%; + height: auto; + } } diff --git a/packages/ui/src/components/diff.css b/packages/ui/src/components/diff.css index 1d94e417ae..92c4450126 100644 --- a/packages/ui/src/components/diff.css +++ b/packages/ui/src/components/diff.css @@ -1,35 +1,35 @@ [data-component="diff"] { - content-visibility: auto; + content-visibility: auto; - [data-slot="diff-hunk-separator-line-number"] { - position: sticky; - left: 0; - background-color: var(--surface-diff-hidden-strong); - z-index: 2; - display: flex; - align-items: center; - justify-content: center; + [data-slot="diff-hunk-separator-line-number"] { + position: sticky; + left: 0; + background-color: var(--surface-diff-hidden-strong); + z-index: 2; + display: flex; + align-items: center; + justify-content: center; - [data-slot="diff-hunk-separator-line-number-icon"] { - aspect-ratio: 1; - width: 24px; - height: 24px; - color: var(--icon-strong-base); - } - } - [data-slot="diff-hunk-separator-content"] { - position: sticky; - background-color: var(--surface-diff-hidden-base); - color: var(--text-base); - width: var(--diffs-column-content-width); - left: var(--diffs-column-number-width); - padding-left: 8px; - user-select: none; - cursor: default; - text-align: left; + [data-slot="diff-hunk-separator-line-number-icon"] { + aspect-ratio: 1; + width: 24px; + height: 24px; + color: var(--icon-strong-base); + } + } + [data-slot="diff-hunk-separator-content"] { + position: sticky; + background-color: var(--surface-diff-hidden-base); + color: var(--text-base); + width: var(--diffs-column-content-width); + left: var(--diffs-column-number-width); + padding-left: 8px; + user-select: none; + cursor: default; + text-align: left; - [data-slot="diff-hunk-separator-content-span"] { - mix-blend-mode: var(--text-mix-blend-mode); - } - } + [data-slot="diff-hunk-separator-content-span"] { + mix-blend-mode: var(--text-mix-blend-mode); + } + } } diff --git a/packages/ui/src/components/dropdown-menu.css b/packages/ui/src/components/dropdown-menu.css index cba041613e..cfbfd1cf0e 100644 --- a/packages/ui/src/components/dropdown-menu.css +++ b/packages/ui/src/components/dropdown-menu.css @@ -1,125 +1,136 @@ [data-component="dropdown-menu-content"], [data-component="dropdown-menu-sub-content"] { - min-width: 8rem; - overflow: hidden; - border-radius: var(--radius-md); - border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); - background-clip: padding-box; - background-color: var(--surface-raised-stronger-non-alpha); - padding: 4px; - box-shadow: var(--shadow-md); - z-index: 50; - transform-origin: var(--kb-menu-content-transform-origin); + min-width: 8rem; + overflow: hidden; + border: none; + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + background-clip: padding-box; + background-color: var(--surface-raised-stronger-non-alpha); + padding: 4px; + z-index: 100; + transform-origin: var(--kb-menu-content-transform-origin); - &:focus, - &:focus-visible { - outline: none; - } + &:focus-within, + &:focus { + outline: none; + } - &[data-closed] { - animation: dropdown-menu-close 0.15s ease-out; - } + animation: dropdownMenuContentHide var(--transition-duration) + var(--transition-easing) forwards; - &[data-expanded] { - animation: dropdown-menu-open 0.15s ease-out; - } + @starting-style { + animation: none; + } + + &[data-expanded] { + pointer-events: auto; + animation: dropdownMenuContentShow var(--transition-duration) + var(--transition-easing) forwards; + } } [data-component="dropdown-menu-content"], [data-component="dropdown-menu-sub-content"] { - [data-slot="dropdown-menu-item"], - [data-slot="dropdown-menu-checkbox-item"], - [data-slot="dropdown-menu-radio-item"], - [data-slot="dropdown-menu-sub-trigger"] { - position: relative; - display: flex; - align-items: center; - gap: 8px; - padding: 4px 8px; - border-radius: var(--radius-sm); - cursor: default; - user-select: none; - outline: none; + [data-slot="dropdown-menu-item"], + [data-slot="dropdown-menu-checkbox-item"], + [data-slot="dropdown-menu-radio-item"], + [data-slot="dropdown-menu-sub-trigger"] { + position: relative; + display: flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + border-radius: var(--radius-sm); + cursor: default; + outline: none; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-strong); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); - &[data-highlighted] { - background: var(--surface-raised-base-hover); - } + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; - &[data-disabled] { - color: var(--text-weak); - pointer-events: none; - } - } + &:hover { + background-color: var(--surface-raised-base-hover); + } - [data-slot="dropdown-menu-sub-trigger"] { - &[data-expanded] { - background: var(--surface-raised-base-hover); - } - } + &[data-disabled] { + color: var(--text-weak); + pointer-events: none; + } + } - [data-slot="dropdown-menu-item-indicator"] { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - } + [data-slot="dropdown-menu-sub-trigger"] { + &[data-expanded] { + background: var(--surface-raised-base-hover); + outline: none; + border: none; + } + } - [data-slot="dropdown-menu-item-label"] { - flex: 1; - } + [data-slot="dropdown-menu-item-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + } - [data-slot="dropdown-menu-item-description"] { - font-size: var(--font-size-x-small); - color: var(--text-weak); - } + [data-slot="dropdown-menu-item-label"] { + flex: 1; + } - [data-slot="dropdown-menu-separator"] { - height: 1px; - margin: 4px -4px; - border-top-color: var(--border-weak-base); - } + [data-slot="dropdown-menu-item-description"] { + font-size: var(--font-size-x-small); + color: var(--text-weak); + } - [data-slot="dropdown-menu-group-label"] { - padding: 4px 8px; - font-family: var(--font-family-sans); - font-size: var(--font-size-x-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - } + [data-slot="dropdown-menu-separator"] { + height: 1px; + margin: 4px -4px; + border-top-color: var(--border-weak-base); + } - [data-slot="dropdown-menu-arrow"] { - fill: var(--surface-raised-stronger-non-alpha); - } + [data-slot="dropdown-menu-group-label"] { + padding: 4px 8px; + font-family: var(--font-family-sans); + font-size: var(--font-size-x-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } + + [data-slot="dropdown-menu-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } } -@keyframes dropdown-menu-open { - from { - opacity: 0; - transform: scale(0.96); - } - to { - opacity: 1; - transform: scale(1); - } +@keyframes dropdownMenuContentShow { + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } -@keyframes dropdown-menu-close { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.96); - } +@keyframes dropdownMenuContentHide { + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } } diff --git a/packages/ui/src/components/file-icon.css b/packages/ui/src/components/file-icon.css index e650f6dc72..379247f0c8 100644 --- a/packages/ui/src/components/file-icon.css +++ b/packages/ui/src/components/file-icon.css @@ -1,5 +1,5 @@ [data-component="file-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; + flex-shrink: 0; + width: 16px; + height: 16px; } diff --git a/packages/ui/src/components/hover-card.css b/packages/ui/src/components/hover-card.css index 02d1f10ad1..2a588adc60 100644 --- a/packages/ui/src/components/hover-card.css +++ b/packages/ui/src/components/hover-card.css @@ -1,61 +1,63 @@ [data-slot="hover-card-trigger"] { - display: flex; - width: 100%; - min-width: 0; + display: flex; + width: 100%; + min-width: 0; } [data-component="hover-card-content"] { - z-index: 50; - min-width: 200px; - max-width: 320px; - max-height: calc(100vh - 1rem); - border-radius: 8px; - background-color: var(--surface-raised-stronger-non-alpha); - pointer-events: auto; + z-index: 50; + min-width: 200px; + max-width: 320px; + max-height: calc(100vh - 1rem); + border-radius: 8px; + 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; - box-shadow: var(--shadow-md); + border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); + background-clip: padding-box; + box-shadow: var(--shadow-md); - transform-origin: var(--kb-hovercard-content-transform-origin); + transform-origin: var(--kb-hovercard-content-transform-origin); - &:focus-within { - outline: none; - } + &:focus-within { + outline: none; + } - &[data-closed] { - animation: hover-card-close 0.15s ease-out; - } + &[data-closed] { + animation: hover-card-close var(--transition-duration) + var(--transition-easing); + } - &[data-expanded] { - animation: hover-card-open 0.15s ease-out; - } + &[data-expanded] { + animation: hover-card-open var(--transition-duration) + var(--transition-easing); + } - [data-slot="hover-card-body"] { - padding: 4px; - max-height: inherit; - overflow: hidden; - } + [data-slot="hover-card-body"] { + padding: 4px; + max-height: inherit; + overflow: hidden; + } } @keyframes hover-card-open { - from { - opacity: 0; - transform: scale(0.96); - } - to { - opacity: 1; - transform: scale(1); - } + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } } @keyframes hover-card-close { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.96); - } + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } } diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index aa550e990f..94aa80f026 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -1,140 +1,143 @@ [data-component="icon-button"] { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-sm); - text-decoration: none; - user-select: none; - aspect-ratio: 1; - flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm); + text-decoration: none; + user-select: none; + aspect-ratio: 1; + flex-shrink: 0; + transition-property: background-color, color, opacity, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &[data-variant="primary"] { - background-color: var(--icon-strong-base); + &[data-variant="primary"] { + background-color: var(--icon-strong-base); - [data-slot="icon-svg"] { - /* color: var(--icon-weak-base); */ - color: var(--icon-invert-base); + [data-slot="icon-svg"] { + /* color: var(--icon-weak-base); */ + color: var(--icon-invert-base); - /* &:hover:not(:disabled) { */ - /* color: var(--icon-weak-hover); */ - /* } */ - /* &:active:not(:disabled) { */ - /* color: var(--icon-strong-active); */ - /* } */ - } + /* &:hover:not(:disabled) { */ + /* color: var(--icon-weak-hover); */ + /* } */ + /* &:active:not(:disabled) { */ + /* color: var(--icon-strong-active); */ + /* } */ + } - &:hover:not(:disabled) { - background-color: var(--icon-strong-hover); - } - &:focus:not(:disabled) { - background-color: var(--icon-strong-focus); - } - &:active:not(:disabled) { - background-color: var(--icon-strong-active); - } - &:disabled { - background-color: var(--icon-strong-disabled); + &:hover:not(:disabled) { + background-color: var(--icon-strong-hover); + } + &:focus:not(:disabled) { + background-color: var(--icon-strong-focus); + } + &:active:not(:disabled) { + background-color: var(--icon-strong-active); + } + &:disabled { + background-color: var(--icon-strong-disabled); - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - } - } + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + } + } - &[data-variant="secondary"] { - border: transparent; - background-color: var(--button-secondary-base); - color: var(--text-strong); - box-shadow: var(--shadow-xs-border); + &[data-variant="secondary"] { + border: transparent; + background-color: var(--button-secondary-base); + color: var(--text-strong); + box-shadow: var(--shadow-xs-border); - &:hover:not(:disabled) { - background-color: var(--button-secondary-hover); - } - &:focus:not(:disabled) { - background-color: var(--button-secondary-base); - } - &:focus-visible:not(:active) { - background-color: var(--button-secondary-base); - box-shadow: var(--shadow-xs-border-focus); - } - &:focus-visible:active { - box-shadow: none; - } - &:active:not(:disabled) { - background-color: var(--button-secondary-base); - } + &:hover:not(:disabled) { + background-color: var(--button-secondary-hover); + } + &:focus:not(:disabled) { + background-color: var(--button-secondary-base); + } + &:focus-visible:not(:active) { + background-color: var(--button-secondary-base); + box-shadow: var(--shadow-xs-border-focus); + } + &:focus-visible:active { + box-shadow: none; + } + &:active:not(:disabled) { + background-color: var(--button-secondary-base); + } - [data-slot="icon-svg"] { - color: var(--icon-strong-base); - } + [data-slot="icon-svg"] { + color: var(--icon-strong-base); + } - &:disabled { - background-color: var(--icon-strong-disabled); - color: var(--icon-invert-base); - cursor: not-allowed; - } - } + &:disabled { + background-color: var(--icon-strong-disabled); + color: var(--icon-invert-base); + cursor: not-allowed; + } + } - &[data-variant="ghost"] { - background-color: transparent; - /* color: var(--icon-base); */ + &[data-variant="ghost"] { + background-color: transparent; + /* color: var(--icon-base); */ - [data-slot="icon-svg"] { - color: var(--icon-base); - } + [data-slot="icon-svg"] { + color: var(--icon-base); + } - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-hover); */ - /* } */ - } - &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-active); */ - /* } */ - } - &:selected:not(:disabled) { - background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-selected); */ - /* } */ - } - &:disabled { - color: var(--icon-invert-base); - cursor: not-allowed; - } - } + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-hover); */ + /* } */ + } + &:focus-visible:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-active); */ + /* } */ + } + &[data-selected]:not(:disabled) { + background-color: var(--surface-raised-base-active); + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-selected); */ + /* } */ + } + &:disabled { + color: var(--icon-invert-base); + cursor: not-allowed; + } + } - &[data-size="normal"] { - width: 24px; - height: 24px; + &[data-size="normal"] { + width: 24px; + height: 24px; - font-size: var(--font-size-small); - line-height: var(--line-height-large); - gap: calc(var(--spacing) * 0.5); - } + font-size: var(--font-size-small); + line-height: var(--line-height-large); + gap: calc(var(--spacing) * 0.5); + } - &[data-size="large"] { - height: 32px; - /* padding: 0 8px 0 6px; */ - gap: 8px; + &[data-size="large"] { + height: 32px; + /* padding: 0 8px 0 6px; */ + gap: 8px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } - &:focus { - outline: none; - } + &:focus { + outline: none; + } } diff --git a/packages/ui/src/components/icon.css b/packages/ui/src/components/icon.css index a2ebee30bc..dd760ccbc2 100644 --- a/packages/ui/src/components/icon.css +++ b/packages/ui/src/components/icon.css @@ -1,34 +1,34 @@ [data-component="icon"] { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - /* resize: both; */ - aspect-ratio: 1/1; - color: var(--icon-base); + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + /* resize: both; */ + aspect-ratio: 1 / 1; + color: var(--icon-base); - &[data-size="small"] { - width: 16px; - height: 16px; - } + &[data-size="small"] { + width: 16px; + height: 16px; + } - &[data-size="normal"] { - width: 20px; - height: 20px; - } + &[data-size="normal"] { + width: 20px; + height: 20px; + } - &[data-size="medium"] { - width: 24px; - height: 24px; - } + &[data-size="medium"] { + width: 24px; + height: 24px; + } - &[data-size="large"] { - width: 24px; - height: 24px; - } + &[data-size="large"] { + width: 24px; + height: 24px; + } - [data-slot="icon-svg"] { - width: 100%; - height: auto; - } + [data-slot="icon-svg"] { + width: 100%; + height: auto; + } } diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index 544c6abdd2..f23357293e 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -80,13 +80,13 @@ const icons = { export interface IconProps extends ComponentProps<"svg"> { name: keyof typeof icons - size?: "small" | "normal" | "medium" | "large" + size?: "small" | "normal" | "medium" | "large" | number } export function Icon(props: IconProps) { const [local, others] = splitProps(props, ["name", "size", "class", "classList"]) return ( -
+
"; - inherits: false; - initial-value: 0px; + syntax: ""; + inherits: false; + initial-value: 0px; } @keyframes scroll { - 0% { - --bottom-fade: 20px; - } - 90% { - --bottom-fade: 20px; - } - 100% { - --bottom-fade: 0; - } + 0% { + --bottom-fade: 20px; + } + 90% { + --bottom-fade: 20px; + } + 100% { + --bottom-fade: 0; + } } [data-component="list"] { - display: flex; - flex-direction: column; - gap: 12px; - overflow: hidden; - padding: 0 12px; + display: flex; + flex-direction: column; + gap: 8px; + overflow: hidden; + padding: 0 12px; - [data-slot="list-search-wrapper"] { - display: flex; - flex-shrink: 0; - align-items: center; - gap: 8px; - align-self: stretch; - margin-bottom: 4px; + [data-slot="list-search-wrapper"] { + display: flex; + flex-shrink: 0; + align-items: center; + gap: 8px; + align-self: stretch; + margin-bottom: 4px; - > [data-component="icon-button"] { - width: 24px; - height: 24px; - flex-shrink: 0; - background-color: transparent; - opacity: 0.5; - transition: opacity 0.15s ease; + > [data-component="icon-button"] { + width: 24px; + height: 24px; + flex-shrink: 0; + background-color: transparent; + opacity: 0.5; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &:hover:not(:disabled), - &:focus-visible:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - opacity: 0.7; - } + &:hover:not(:disabled), + &:focus-visible:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + opacity: 0.7; + } - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - } + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + } - [data-slot="list-search"] { - display: flex; - flex: 1; - padding: 8px; - align-items: center; - gap: 12px; + [data-slot="list-search"] { + display: flex; + flex: 1; + padding: 8px; + align-items: center; + gap: 12px; - border-radius: var(--radius-md); - background: var(--surface-base); + border-radius: var(--radius-md); + background: var(--surface-base); - [data-slot="list-search-container"] { - display: flex; - align-items: center; - gap: 8px; - flex: 1 0 0; - max-height: 20px; + [data-slot="list-search-container"] { + display: flex; + align-items: center; + gap: 8px; + flex: 1 0 0; + max-height: 20px; - [data-slot="list-search-input"] { - width: 100%; + [data-slot="list-search-input"] { + width: 100%; - &[data-slot="input-input"] { - line-height: 20px; - max-height: 20px; - } - } - } + &[data-slot="input-input"] { + line-height: 20px; + max-height: 20px; + } + } + } - > [data-component="icon-button"] { - width: 20px; - height: 20px; - background-color: transparent; - opacity: 0.5; - transition: opacity 0.15s ease; + > [data-component="icon-button"] { + width: 20px; + height: 20px; + background-color: transparent; + opacity: 0.5; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &:hover:not(:disabled), - &:focus-visible:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - opacity: 0.7; - } + &:hover:not(:disabled), + &:focus-visible:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + opacity: 0.7; + } - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } - > [data-component="icon-button"] { - background-color: transparent; + > [data-component="icon-button"] { + background-color: transparent; - &:hover:not(:disabled), - &:focus:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - } + &:hover:not(:disabled), + &:focus:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + } - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - } + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + } - [data-slot="list-scroll"] { - display: flex; - flex-direction: column; - gap: 12px; - overflow-y: auto; - overscroll-behavior: contain; - mask: linear-gradient(to bottom, #ffff calc(100% - var(--bottom-fade)), #0000); - animation: scroll; - animation-timeline: --scroll; - scroll-timeline: --scroll y; - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + [data-slot="list-scroll"] { + display: flex; + flex-direction: column; + gap: 12px; + overflow-y: auto; + overscroll-behavior: contain; - [data-slot="list-empty-state"] { - display: flex; - padding: 32px 48px; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 8px; - align-self: stretch; + [data-slot="list-empty-state"] { + display: flex; + padding: 32px 48px; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 8px; + align-self: stretch; - [data-slot="list-message"] { - display: flex; - justify-content: center; - align-items: center; - gap: 2px; - max-width: 100%; - color: var(--text-weak); - white-space: nowrap; + [data-slot="list-message"] { + display: flex; + justify-content: center; + align-items: center; + gap: 2px; + max-width: 100%; + color: var(--text-weak); + white-space: nowrap; - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="list-filter"] { - color: var(--text-strong); - overflow: hidden; - text-overflow: ellipsis; - } - } + [data-slot="list-filter"] { + color: var(--text-strong); + overflow: hidden; + text-overflow: ellipsis; + } + } - [data-slot="list-group"] { - position: relative; - display: flex; - flex-direction: column; + [data-slot="list-group"] { + position: relative; + display: flex; + flex-direction: column; - &:last-child { - padding-bottom: 12px; - } + &:last-child { + padding-bottom: 12px; + } - [data-slot="list-header"] { - display: flex; - z-index: 10; - padding: 8px 12px 8px 8px; - justify-content: space-between; - align-items: center; - align-self: stretch; - background: var(--surface-raised-stronger-non-alpha); - position: sticky; - top: 0; + [data-slot="list-header"] { + display: flex; + z-index: 10; + padding: 8px 12px 8px 8px; + justify-content: space-between; + align-items: center; + align-self: stretch; + background: var(--surface-raised-stronger-non-alpha); + position: sticky; + top: 0; - color: var(--text-weak); + color: var(--text-weak); - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - &::after { - content: ""; - position: absolute; - top: 100%; - left: 0; - right: 0; - height: 16px; - background: linear-gradient(to bottom, var(--surface-raised-stronger-non-alpha), transparent); - pointer-events: none; - opacity: 0; - transition: opacity 0.15s ease; - } + &::after { + content: ""; + position: absolute; + top: 100%; + left: 0; + right: 0; + height: 16px; + background: linear-gradient( + to bottom, + var(--surface-raised-stronger-non-alpha), + transparent + ); + pointer-events: none; + opacity: 0; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - &[data-stuck="true"]::after { - opacity: 1; - } - } + &[data-stuck="true"]::after { + opacity: 1; + } + } - [data-slot="list-items"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; + [data-slot="list-items"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; - [data-slot="list-item"] { - display: flex; - position: relative; - width: 100%; - padding: 6px 8px 6px 8px; - align-items: center; - color: var(--text-strong); - scroll-margin-top: 28px; + [data-slot="list-item"] { + display: flex; + position: relative; + width: 100%; + padding: 6px 8px 6px 8px; + align-items: center; + color: var(--text-strong); + scroll-margin-top: 28px; - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - [data-slot="list-item-selected-icon"] { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - aspect-ratio: 1/1; - [data-component="icon"] { - color: var(--icon-strong-base); - } - } - [data-slot="list-item-active-icon"] { - display: none; - align-items: center; - justify-content: center; - flex-shrink: 0; - aspect-ratio: 1/1; - [data-component="icon"] { - color: var(--icon-strong-base); - } - } + [data-slot="list-item-selected-icon"] { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + aspect-ratio: 1 / 1; + [data-component="icon"] { + color: var(--icon-strong-base); + } + } - [data-slot="list-item-extra-icon"] { - color: var(--icon-base); - margin-left: -4px; - } + [name="check"] { + color: var(--icon-strong-base); + } - [data-slot="list-item-divider"] { - position: absolute; - bottom: 0; - left: var(--list-divider-inset, 16px); - right: var(--list-divider-inset, 16px); - height: 1px; - background: var(--border-weak-base); - pointer-events: none; - } + [data-slot="list-item-active-icon"] { + display: none; + align-items: center; + justify-content: center; + flex-shrink: 0; + aspect-ratio: 1 / 1; + [data-component="icon"] { + color: var(--icon-strong-base); + } + } - [data-slot="list-item"]:last-child [data-slot="list-item-divider"] { - display: none; - } + [data-slot="list-item-extra-icon"] { + color: var(--icon-base); + margin-left: -4px; + } - &[data-active="true"] { - border-radius: var(--radius-md); - background: var(--surface-raised-base-hover); - [data-slot="list-item-active-icon"] { - display: inline-flex; - } - [data-slot="list-item-extra-icon"] { - display: block !important; - color: var(--icon-strong-base) !important; - } - } - &:active { - background: var(--surface-raised-base-active); - } - &:focus-visible { - outline: none; - } - } + [data-slot="list-item-divider"] { + position: absolute; + bottom: 0; + left: var(--list-divider-inset, 16px); + right: var(--list-divider-inset, 16px); + height: 1px; + background: var(--border-weak-base); + pointer-events: none; + } - [data-slot="list-item-add"] { - display: flex; - position: relative; - width: 100%; - padding: 6px 8px 6px 8px; - align-items: center; - color: var(--text-strong); + [data-slot="list-item"]:last-child [data-slot="list-item-divider"] { + display: none; + } - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + &[data-active="true"] { + border-radius: var(--radius-md); + background: var(--surface-raised-base-hover); + [data-slot="list-item-active-icon"] { + display: inline-flex; + } + [data-slot="list-item-extra-icon"] { + display: block !important; + color: var(--icon-strong-base) !important; + } + } + &:active { + background: var(--surface-raised-base-active); + } + &:focus-visible { + outline: none; + } + } - [data-component="input"] { - width: 100%; - } - } - } - } - } + [data-slot="list-item-add"] { + display: flex; + position: relative; + width: 100%; + padding: 6px 8px 6px 8px; + align-items: center; + color: var(--text-strong); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + + [data-component="input"] { + width: 100%; + } + } + } + } + } } diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index 2132897f7c..f612a231e0 100644 --- a/packages/ui/src/components/list.tsx +++ b/packages/ui/src/components/list.tsx @@ -5,6 +5,7 @@ import { useI18n } from "../context/i18n" import { Icon, type IconProps } from "./icon" import { IconButton } from "./icon-button" import { TextField } from "./text-field" +import { ScrollFade } from "./scroll-fade" function findByKey(container: HTMLElement, key: string) { const nodes = container.querySelectorAll('[data-slot="list-item"][data-key]') @@ -267,7 +268,13 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void }) {searchAction()}
-
+ 0 || showAdd()} fallback={ @@ -339,7 +346,7 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void })
-
+
) } diff --git a/packages/ui/src/components/logo.css b/packages/ui/src/components/logo.css index a909782b77..b16c441d2b 100644 --- a/packages/ui/src/components/logo.css +++ b/packages/ui/src/components/logo.css @@ -1,4 +1,4 @@ [data-component="logo-mark"] { - width: 16px; - aspect-ratio: 4/5; + width: 16px; + aspect-ratio: 4 / 5; } diff --git a/packages/ui/src/components/markdown.css b/packages/ui/src/components/markdown.css index ef43187336..5d7f26e3d3 100644 --- a/packages/ui/src/components/markdown.css +++ b/packages/ui/src/components/markdown.css @@ -1,209 +1,211 @@ [data-component="markdown"] { - /* Reset & Base Typography */ - min-width: 0; - max-width: 100%; - overflow-wrap: break-word; - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: var(--font-size-base); /* 14px */ - line-height: var(--line-height-x-large); + /* Reset & Base Typography */ + min-width: 0; + max-width: 100%; + overflow-wrap: break-word; + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); /* 14px */ + line-height: var(--line-height-x-large); - /* Spacing for flow */ - > *:first-child { - margin-top: 0; - } - > *:last-child { - margin-bottom: 0; - } + /* Spacing for flow */ + > *:first-child { + margin-top: 0; + } + > *:last-child { + margin-bottom: 0; + } - /* Headings: Same size, distinguished by color and spacing */ - h1, - h2, - h3, - h4, - h5, - h6 { - font-size: var(--font-size-base); - color: var(--text-strong); - font-weight: var(--font-weight-medium); - margin-top: 2rem; - margin-bottom: 0.75rem; - line-height: var(--line-height-large); - } + /* Headings: Same size, distinguished by color and spacing */ + h1, + h2, + h3, + h4, + h5, + h6 { + font-size: var(--font-size-base); + color: var(--text-strong); + font-weight: var(--font-weight-medium); + margin-top: 2rem; + margin-bottom: 0.75rem; + line-height: var(--line-height-large); + } - /* Emphasis & Strong: Neutral strong color */ - strong, - b { - color: var(--text-strong); - font-weight: var(--font-weight-medium); - } + /* Emphasis & Strong: Neutral strong color */ + strong, + b { + color: var(--text-strong); + font-weight: var(--font-weight-medium); + } - /* Paragraphs */ - p { - margin-bottom: 1rem; - } + /* Paragraphs */ + p { + margin-bottom: 1rem; + } - /* Links */ - a { - color: var(--text-interactive-base); - text-decoration: none; - font-weight: inherit; - } + /* Links */ + a { + color: var(--text-interactive-base); + text-decoration: none; + font-weight: inherit; + } - a:hover { - text-decoration: underline; - text-underline-offset: 2px; - } + a:hover { + text-decoration: underline; + text-underline-offset: 2px; + } - /* Lists */ - ul, - ol { - margin-top: 0.5rem; - margin-bottom: 1rem; - padding-left: 1.5rem; - list-style-position: outside; - } + /* Lists */ + ul, + ol { + margin-top: 0.5rem; + margin-bottom: 1rem; + padding-left: 1.5rem; + list-style-position: outside; + } - ul { - list-style-type: disc; - } + ul { + list-style-type: disc; + } - ol { - list-style-type: decimal; - } + ol { + list-style-type: decimal; + } - li { - margin-bottom: 0.5rem; - } + li { + margin-bottom: 0.5rem; + } - li > p:first-child { - display: inline; - margin: 0; - } + li > p:first-child { + display: inline; + margin: 0; + } - li > p + p { - display: block; - margin-top: 0.5rem; - } + li > p + p { + display: block; + margin-top: 0.5rem; + } - li::marker { - color: var(--text-weak); - } + li::marker { + color: var(--text-weak); + } - /* Nested lists spacing */ - li > ul, - li > ol { - margin-top: 0.25rem; - margin-bottom: 0.25rem; - padding-left: 1rem; /* Minimal indent for nesting only */ - } + /* Nested lists spacing */ + li > ul, + li > ol { + margin-top: 0.25rem; + margin-bottom: 0.25rem; + padding-left: 1rem; /* Minimal indent for nesting only */ + } - /* Blockquotes */ - blockquote { - border-left: 2px solid var(--border-weak-base); - margin: 1.5rem 0; - padding-left: 0.5rem; - color: var(--text-weak); - font-style: normal; - } + /* Blockquotes */ + blockquote { + border-left: 2px solid var(--border-weak-base); + margin: 1.5rem 0; + padding-left: 0.5rem; + color: var(--text-weak); + font-style: normal; + } - /* Horizontal Rule - Invisible spacing only */ - hr { - border: none; - height: 0; - margin: 2.5rem 0; - } + /* Horizontal Rule - Invisible spacing only */ + hr { + border: none; + height: 0; + margin: 2.5rem 0; + } - .shiki { - font-size: 13px; - padding: 8px 12px; - border-radius: 4px; - border: 0.5px solid var(--border-weak-base); - } + .shiki { + font-size: 13px; + padding: 8px 12px; + border-radius: 4px; + border: 0.5px solid var(--border-weak-base); + } - [data-component="markdown-code"] { - position: relative; - } + [data-component="markdown-code"] { + position: relative; + } - [data-slot="markdown-copy-button"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } + [data-slot="markdown-copy-button"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } - [data-component="markdown-code"]:hover [data-slot="markdown-copy-button"] { - opacity: 1; - } + [data-component="markdown-code"]:hover [data-slot="markdown-copy-button"] { + opacity: 1; + } - [data-slot="markdown-copy-button"] [data-slot="check-icon"] { - display: none; - } + [data-slot="markdown-copy-button"] [data-slot="check-icon"] { + display: none; + } - [data-slot="markdown-copy-button"][data-copied="true"] [data-slot="copy-icon"] { - display: none; - } + [data-slot="markdown-copy-button"][data-copied="true"] + [data-slot="copy-icon"] { + display: none; + } - [data-slot="markdown-copy-button"][data-copied="true"] [data-slot="check-icon"] { - display: inline-flex; - } + [data-slot="markdown-copy-button"][data-copied="true"] + [data-slot="check-icon"] { + display: inline-flex; + } - pre { - margin-top: 2rem; - margin-bottom: 2rem; - overflow: auto; + pre { + margin-top: 2rem; + margin-bottom: 2rem; + overflow: auto; - scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } - } + scrollbar-width: none; + &::-webkit-scrollbar { + display: none; + } + } - :not(pre) > code { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - color: var(--syntax-string); - font-weight: var(--font-weight-medium); - /* font-size: 13px; */ + :not(pre) > code { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + color: var(--syntax-string); + font-weight: var(--font-weight-medium); + /* font-size: 13px; */ - /* padding: 2px 2px; */ - /* margin: 0 1.5px; */ - /* border-radius: 2px; */ - /* background: var(--surface-base); */ - /* box-shadow: 0 0 0 0.5px var(--border-weak-base); */ - } + /* padding: 2px 2px; */ + /* margin: 0 1.5px; */ + /* border-radius: 2px; */ + /* background: var(--surface-base); */ + /* box-shadow: 0 0 0 0.5px var(--border-weak-base); */ + } - /* Tables */ - table { - width: 100%; - border-collapse: collapse; - margin: 1.5rem 0; - font-size: var(--font-size-base); - } + /* Tables */ + table { + width: 100%; + border-collapse: collapse; + margin: 1.5rem 0; + font-size: var(--font-size-base); + } - th, - td { - /* Minimal borders for structure, matching TUI "lines" roughly but keeping it web-clean */ - border-bottom: 1px solid var(--border-weaker-base); - padding: 0.75rem 0.5rem; - text-align: left; - vertical-align: top; - } + th, + td { + /* Minimal borders for structure, matching TUI "lines" roughly but keeping it web-clean */ + border-bottom: 1px solid var(--border-weaker-base); + padding: 0.75rem 0.5rem; + text-align: left; + vertical-align: top; + } - th { - color: var(--text-strong); - font-weight: var(--font-weight-medium); - border-bottom: 1px solid var(--border-weak-base); - } + th { + color: var(--text-strong); + font-weight: var(--font-weight-medium); + border-bottom: 1px solid var(--border-weak-base); + } - /* Images */ - img { - max-width: 100%; - height: auto; - border-radius: 4px; - margin: 1.5rem 0; - display: block; - } + /* Images */ + img { + max-width: 100%; + height: auto; + border-radius: 4px; + margin: 1.5rem 0; + display: block; + } } diff --git a/packages/ui/src/components/message-nav.css b/packages/ui/src/components/message-nav.css index b1454ad425..6b82dc91c2 100644 --- a/packages/ui/src/components/message-nav.css +++ b/packages/ui/src/components/message-nav.css @@ -1,122 +1,123 @@ [data-component="message-nav"] { - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: flex-start; - padding-left: 0; - list-style: none; + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + padding-left: 0; + list-style: none; - &[data-size="normal"] { - width: 240px; - gap: 4px; - } + &[data-size="normal"] { + width: 240px; + gap: 4px; + } - &[data-size="compact"] { - width: 24px; - } + &[data-size="compact"] { + width: 24px; + } } [data-slot="message-nav-item"] { - display: flex; - align-items: center; - align-self: stretch; - justify-content: flex-end; + display: flex; + align-items: center; + align-self: stretch; + justify-content: flex-end; - [data-component="message-nav"][data-size="normal"] & { - justify-content: flex-start; - } + [data-component="message-nav"][data-size="normal"] & { + justify-content: flex-start; + } } [data-slot="message-nav-tick-button"] { - display: flex; - align-items: center; - justify-content: flex-start; - height: 12px; - width: 24px; - border: none; - background: none; - padding: 0; + display: flex; + align-items: center; + justify-content: flex-start; + height: 12px; + width: 24px; + border: none; + background: none; + padding: 0; - &[data-active] [data-slot="message-nav-tick-line"] { - background-color: var(--icon-strong-base); - width: 100%; - } + &[data-active] [data-slot="message-nav-tick-line"] { + background-color: var(--icon-strong-base); + width: 100%; + } } [data-slot="message-nav-tick-line"] { - height: 1px; - width: 16px; - background-color: var(--icon-base); - transition: - width 0.2s, - background-color 0.2s; + height: 1px; + width: 16px; + background-color: var(--icon-base); + transition: + width 0.2s, + background-color 0.2s; } -[data-slot="message-nav-tick-button"]:hover [data-slot="message-nav-tick-line"] { - width: 100%; - background-color: var(--icon-strong-base); +[data-slot="message-nav-tick-button"]:hover + [data-slot="message-nav-tick-line"] { + width: 100%; + background-color: var(--icon-strong-base); } [data-slot="message-nav-message-button"] { - display: flex; - align-items: center; - align-self: stretch; - width: 100%; - column-gap: 12px; - cursor: default; - border: none; - background: none; - padding: 4px 12px; - border-radius: var(--radius-sm); + display: flex; + align-items: center; + align-self: stretch; + width: 100%; + column-gap: 12px; + cursor: default; + border: none; + background: none; + padding: 4px 12px; + border-radius: var(--radius-sm); } [data-slot="message-nav-title-preview"] { - font-size: 14px; /* text-14-regular */ - color: var(--text-base); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - text-align: left; + font-size: 14px; /* text-14-regular */ + color: var(--text-base); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + text-align: left; - &[data-active] { - color: var(--text-strong); - } + &[data-active] { + color: var(--text-strong); + } } [data-slot="message-nav-item"]:hover [data-slot="message-nav-message-button"] { - background-color: var(--surface-base); + background-color: var(--surface-base); } [data-slot="message-nav-item"]:active [data-slot="message-nav-message-button"] { - background-color: var(--surface-base-active); + background-color: var(--surface-base-active); } [data-slot="message-nav-item"]:active [data-slot="message-nav-title-preview"] { - color: var(--text-base); + color: var(--text-base); } [data-slot="message-nav-tooltip"] { - z-index: 1000; + z-index: 1000; } [data-slot="message-nav-tooltip-content"] { - display: flex; - padding: 4px 4px 6px 4px; - justify-content: center; - align-items: center; - border-radius: var(--radius-md); - background: var(--surface-raised-stronger-non-alpha); - max-height: calc(100vh - 6rem); - overflow-y: auto; + display: flex; + padding: 4px 4px 6px 4px; + justify-content: center; + align-items: center; + border-radius: var(--radius-md); + background: var(--surface-raised-stronger-non-alpha); + max-height: calc(100vh - 6rem); + overflow-y: auto; - /* border/shadow-xs/base */ - box-shadow: - 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), - 0 1px 2px -1px rgba(19, 16, 16, 0.04), - 0 1px 2px 0 rgba(19, 16, 16, 0.06), - 0 1px 3px 0 rgba(19, 16, 16, 0.08); + /* border/shadow-xs/base */ + box-shadow: + 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), + 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), + 0 1px 3px 0 rgba(19, 16, 16, 0.08); - * { - margin: 0 !important; - } + * { + margin: 0 !important; + } } diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index 2bef792a2c..dba0a59b72 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -1,439 +1,439 @@ [data-component="assistant-message"] { - content-visibility: auto; - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; + content-visibility: auto; + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; } [data-component="user-message"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); - display: flex; - flex-direction: column; - gap: 8px; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); + display: flex; + flex-direction: column; + gap: 8px; - [data-slot="user-message-attachments"] { - display: flex; - flex-wrap: wrap; - gap: 8px; - } + [data-slot="user-message-attachments"] { + display: flex; + flex-wrap: wrap; + gap: 8px; + } - [data-slot="user-message-attachment"] { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - border-radius: 6px; - overflow: hidden; - background: var(--surface-weak); - border: 1px solid var(--border-weak-base); - transition: border-color 0.15s ease; + [data-slot="user-message-attachment"] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 6px; + overflow: hidden; + background: var(--surface-weak); + border: 1px solid var(--border-weak-base); + transition: border-color 0.15s ease; - &:hover { - border-color: var(--border-strong-base); - } + &:hover { + border-color: var(--border-strong-base); + } - &[data-type="image"] { - width: 48px; - height: 48px; - } + &[data-type="image"] { + width: 48px; + height: 48px; + } - &[data-type="file"] { - width: 48px; - height: 48px; - } - } + &[data-type="file"] { + width: 48px; + height: 48px; + } + } - [data-slot="user-message-attachment-image"] { - width: 100%; - height: 100%; - object-fit: cover; - } + [data-slot="user-message-attachment-image"] { + width: 100%; + height: 100%; + object-fit: cover; + } - [data-slot="user-message-attachment-icon"] { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - color: var(--icon-weak); + [data-slot="user-message-attachment-icon"] { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: var(--icon-weak); - [data-component="icon"] { - width: 20px; - height: 20px; - } - } + [data-component="icon"] { + width: 20px; + height: 20px; + } + } - [data-slot="user-message-text"] { - position: relative; - white-space: pre-wrap; - word-break: break-word; - overflow: hidden; - background: var(--surface-weak); - border: 1px solid var(--border-weak-base); - padding: 8px 12px; - border-radius: 4px; + [data-slot="user-message-text"] { + position: relative; + white-space: pre-wrap; + word-break: break-word; + overflow: hidden; + background: var(--surface-weak); + border: 1px solid var(--border-weak-base); + padding: 8px 12px; + border-radius: 4px; - [data-highlight="file"] { - color: var(--syntax-property); - } + [data-highlight="file"] { + color: var(--syntax-property); + } - [data-highlight="agent"] { - color: var(--syntax-type); - } + [data-highlight="agent"] { + color: var(--syntax-type); + } - [data-slot="user-message-copy-wrapper"] { - position: absolute; - top: 7px; - right: 7px; - opacity: 0; - transition: opacity 0.15s ease; - } + [data-slot="user-message-copy-wrapper"] { + position: absolute; + top: 7px; + right: 7px; + opacity: 0; + transition: opacity 0.15s ease; + } - &:hover [data-slot="user-message-copy-wrapper"] { - opacity: 1; - } - } + &:hover [data-slot="user-message-copy-wrapper"] { + opacity: 1; + } + } - .text-text-strong { - color: var(--text-strong); - } + .text-text-strong { + color: var(--text-strong); + } - .font-medium { - font-weight: var(--font-weight-medium); - } + .font-medium { + font-weight: var(--font-weight-medium); + } } [data-component="text-part"] { - width: 100%; + width: 100%; - [data-slot="text-part-body"] { - position: relative; - margin-top: 32px; - } + [data-slot="text-part-body"] { + position: relative; + margin-top: 32px; + } - [data-slot="text-part-copy-wrapper"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } + [data-slot="text-part-copy-wrapper"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } - [data-slot="text-part-body"]:hover [data-slot="text-part-copy-wrapper"] { - opacity: 1; - } + [data-slot="text-part-body"]:hover [data-slot="text-part-copy-wrapper"] { + opacity: 1; + } - [data-component="markdown"] { - margin-top: 0; - font-size: var(--font-size-base); - } + [data-component="markdown"] { + margin-top: 0; + font-size: var(--font-size-base); + } } [data-component="reasoning-part"] { - width: 100%; - color: var(--text-base); - opacity: 0.8; - line-height: var(--line-height-large); + width: 100%; + color: var(--text-base); + opacity: 0.8; + line-height: var(--line-height-large); - [data-component="markdown"] { - margin-top: 24px; - font-style: italic !important; + [data-component="markdown"] { + margin-top: 24px; + font-style: italic !important; - p:has(strong) { - margin-top: 24px; - margin-bottom: 0; + p:has(strong) { + margin-top: 24px; + margin-bottom: 0; - &:first-child { - margin-top: 0; - } - } - } + &:first-child { + margin-top: 0; + } + } + } } [data-component="tool-error"] { - display: flex; - align-items: start; - gap: 8px; + display: flex; + align-items: start; + gap: 8px; - [data-slot="icon-svg"] { - color: var(--icon-critical-base); - margin-top: 4px; - } + [data-slot="icon-svg"] { + color: var(--icon-critical-base); + margin-top: 4px; + } - [data-slot="message-part-tool-error-content"] { - display: flex; - align-items: start; - gap: 8px; - } + [data-slot="message-part-tool-error-content"] { + display: flex; + align-items: start; + gap: 8px; + } - [data-slot="message-part-tool-error-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-on-critical-base); - white-space: nowrap; - } + [data-slot="message-part-tool-error-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-on-critical-base); + white-space: nowrap; + } - [data-slot="message-part-tool-error-message"] { - color: var(--text-on-critical-weak); - max-height: 240px; - overflow-y: auto; - word-break: break-word; - } + [data-slot="message-part-tool-error-message"] { + color: var(--text-on-critical-weak); + max-height: 240px; + overflow-y: auto; + word-break: break-word; + } } [data-component="tool-output"] { - white-space: pre; - padding: 8px 12px; - height: fit-content; - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; + white-space: pre; + padding: 8px 12px; + height: fit-content; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; - [data-component="markdown"] { - width: 100%; - min-width: 0; + [data-component="markdown"] { + width: 100%; + min-width: 0; - pre { - margin: 0; - padding: 0; - background-color: transparent !important; - border: none !important; - } - } + pre { + margin: 0; + padding: 0; + background-color: transparent !important; + border: none !important; + } + } - pre { - margin: 0; - padding: 0; - background: none; - } + pre { + margin: 0; + padding: 0; + background: none; + } - &[data-scrollable] { - height: auto; - max-height: 240px; - overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + &[data-scrollable] { + height: auto; + max-height: 240px; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } - [data-component="markdown"] { - overflow: visible; - } - } + [data-component="markdown"] { + overflow: visible; + } + } } [data-component="edit-trigger"], [data-component="write-trigger"] { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + width: 100%; - [data-slot="message-part-title-area"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - } + [data-slot="message-part-title-area"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + } - [data-slot="message-part-title"] { - flex-shrink: 0; - display: flex; - align-items: center; - gap: 4px; - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); - } + [data-slot="message-part-title"] { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 4px; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); + } - [data-slot="message-part-title-text"] { - text-transform: capitalize; - } + [data-slot="message-part-title-text"] { + text-transform: capitalize; + } - [data-slot="message-part-title-filename"] { - /* No text-transform - preserve original filename casing */ - } + [data-slot="message-part-title-filename"] { + /* No text-transform - preserve original filename casing */ + } - [data-slot="message-part-path"] { - display: flex; - flex-grow: 1; - min-width: 0; - } + [data-slot="message-part-path"] { + display: flex; + flex-grow: 1; + min-width: 0; + } - [data-slot="message-part-directory"] { - color: var(--text-weak); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } + [data-slot="message-part-directory"] { + color: var(--text-weak); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } - [data-slot="message-part-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } + [data-slot="message-part-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } - [data-slot="message-part-actions"] { - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - } + [data-slot="message-part-actions"] { + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + } } [data-component="edit-content"] { - border-top: 1px solid var(--border-weaker-base); - max-height: 420px; - overflow-y: auto; + border-top: 1px solid var(--border-weaker-base); + max-height: 420px; + overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="write-content"] { - border-top: 1px solid var(--border-weaker-base); - max-height: 240px; - overflow-y: auto; + border-top: 1px solid var(--border-weaker-base); + max-height: 240px; + overflow-y: auto; - [data-component="code"] { - padding-bottom: 0px !important; - } + [data-component="code"] { + padding-bottom: 0px !important; + } - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="tool-action"] { - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; } [data-component="todos"] { - padding: 10px 12px 24px 48px; - display: flex; - flex-direction: column; - gap: 8px; + padding: 10px 12px 24px 48px; + display: flex; + flex-direction: column; + gap: 8px; - [data-slot="message-part-todo-content"] { - &[data-completed="completed"] { - text-decoration: line-through; - color: var(--text-weaker); - } - } + [data-slot="message-part-todo-content"] { + &[data-completed="completed"] { + text-decoration: line-through; + color: var(--text-weaker); + } + } } [data-component="task-tools"] { - padding: 8px 12px; - display: flex; - flex-direction: column; - gap: 6px; + padding: 8px 12px; + display: flex; + flex-direction: column; + gap: 6px; - [data-slot="task-tool-item"] { - display: flex; - align-items: center; - gap: 8px; - color: var(--text-weak); + [data-slot="task-tool-item"] { + display: flex; + align-items: center; + gap: 8px; + color: var(--text-weak); - [data-slot="icon-svg"] { - flex-shrink: 0; - color: var(--icon-weak); - } - } + [data-slot="icon-svg"] { + flex-shrink: 0; + color: var(--icon-weak); + } + } - [data-slot="task-tool-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-weak); - } + [data-slot="task-tool-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-weak); + } - [data-slot="task-tool-subtitle"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - color: var(--text-weaker); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + [data-slot="task-tool-subtitle"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + color: var(--text-weaker); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } } [data-component="diagnostics"] { - display: flex; - flex-direction: column; - gap: 4px; - padding: 8px 12px; - background-color: var(--surface-critical-weak); - border-top: 1px solid var(--border-critical-base); + display: flex; + flex-direction: column; + gap: 4px; + padding: 8px 12px; + background-color: var(--surface-critical-weak); + border-top: 1px solid var(--border-critical-base); - [data-slot="diagnostic"] { - display: flex; - align-items: baseline; - gap: 6px; - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - line-height: var(--line-height-large); - } + [data-slot="diagnostic"] { + display: flex; + align-items: baseline; + gap: 6px; + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + line-height: var(--line-height-large); + } - [data-slot="diagnostic-label"] { - color: var(--text-on-critical-base); - font-weight: var(--font-weight-medium); - text-transform: uppercase; - letter-spacing: -0.5px; - flex-shrink: 0; - } + [data-slot="diagnostic-label"] { + color: var(--text-on-critical-base); + font-weight: var(--font-weight-medium); + text-transform: uppercase; + letter-spacing: -0.5px; + flex-shrink: 0; + } - [data-slot="diagnostic-location"] { - color: var(--text-on-critical-weak); - flex-shrink: 0; - } + [data-slot="diagnostic-location"] { + color: var(--text-on-critical-weak); + flex-shrink: 0; + } - [data-slot="diagnostic-message"] { - color: var(--text-on-critical-base); - word-break: break-word; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - } + [data-slot="diagnostic-message"] { + color: var(--text-on-critical-base); + word-break: break-word; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; + line-clamp: 3; + overflow: hidden; + } } [data-component="user-message"] [data-slot="user-message-text"], @@ -446,383 +446,383 @@ [data-component="todos"], [data-component="diagnostics"], .error-card { - -webkit-user-select: text; - user-select: text; + -webkit-user-select: text; + user-select: text; } [data-component="tool-part-wrapper"] { - width: 100%; + width: 100%; - &[data-permission="true"], - &[data-question="true"] { - position: sticky; - top: calc(2px + var(--sticky-header-height, 40px)); - bottom: 0px; - z-index: 20; - border-radius: 6px; - border: none; - box-shadow: var(--shadow-xs-border-base); - background-color: var(--surface-raised-base); - overflow: visible; - overflow-anchor: none; + &[data-permission="true"], + &[data-question="true"] { + position: sticky; + top: calc(2px + var(--sticky-header-height, 40px)); + bottom: 0px; + z-index: 20; + border-radius: 6px; + border: none; + box-shadow: var(--shadow-xs-border-base); + background-color: var(--surface-raised-base); + overflow: visible; + overflow-anchor: none; - & > *:first-child { - border-top-left-radius: 6px; - border-top-right-radius: 6px; - overflow: hidden; - } + & > *:first-child { + border-top-left-radius: 6px; + border-top-right-radius: 6px; + overflow: hidden; + } - & > *:last-child { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - overflow: hidden; - } + & > *:last-child { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + overflow: hidden; + } - [data-component="collapsible"] { - border: none; - } + [data-component="collapsible"] { + border: none; + } - [data-component="card"] { - border: none; - } - } + [data-component="card"] { + border: none; + } + } - &[data-permission="true"] { - &::before { - content: ""; - position: absolute; - inset: -1.5px; - top: -5px; - border-radius: 7.5px; - border: 1.5px solid transparent; - background: - linear-gradient(var(--background-base) 0 0) padding-box, - conic-gradient( - from var(--border-angle), - transparent 0deg, - transparent 0deg, - var(--border-warning-strong, var(--border-warning-selected)) 300deg, - var(--border-warning-base) 360deg - ) - border-box; - animation: chase-border 2.5s linear infinite; - pointer-events: none; - z-index: -1; - } - } + &[data-permission="true"] { + &::before { + content: ""; + position: absolute; + inset: -1.5px; + top: -5px; + border-radius: 7.5px; + border: 1.5px solid transparent; + background: + linear-gradient(var(--background-base) 0 0) padding-box, + conic-gradient( + from var(--border-angle), + transparent 0deg, + transparent 0deg, + var(--border-warning-strong, var(--border-warning-selected)) 300deg, + var(--border-warning-base) 360deg + ) + border-box; + animation: chase-border 2.5s linear infinite; + pointer-events: none; + z-index: -1; + } + } - &[data-question="true"] { - background: var(--background-base); - border: 1px solid var(--border-weak-base); - } + &[data-question="true"] { + background: var(--background-base); + border: 1px solid var(--border-weak-base); + } } @property --border-angle { - syntax: ""; - initial-value: 0deg; - inherits: false; + syntax: ""; + initial-value: 0deg; + inherits: false; } @keyframes chase-border { - from { - --border-angle: 0deg; - } + from { + --border-angle: 0deg; + } - to { - --border-angle: 360deg; - } + to { + --border-angle: 360deg; + } } [data-component="permission-prompt"] { - display: flex; - flex-direction: column; - padding: 8px 12px; - background-color: var(--surface-raised-strong); - border-radius: 0 0 6px 6px; + display: flex; + flex-direction: column; + padding: 8px 12px; + background-color: var(--surface-raised-strong); + border-radius: 0 0 6px 6px; - [data-slot="permission-actions"] { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; - } + [data-slot="permission-actions"] { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; + } } [data-component="question-prompt"] { - display: flex; - flex-direction: column; - padding: 12px; - background-color: var(--surface-inset-base); - border-radius: 0 0 6px 6px; - gap: 12px; + display: flex; + flex-direction: column; + padding: 12px; + background-color: var(--surface-inset-base); + border-radius: 0 0 6px 6px; + gap: 12px; - [data-slot="question-tabs"] { - display: flex; - gap: 4px; - flex-wrap: wrap; + [data-slot="question-tabs"] { + display: flex; + gap: 4px; + flex-wrap: wrap; - [data-slot="question-tab"] { - padding: 4px 12px; - font-size: 13px; - border-radius: 4px; - background-color: var(--surface-base); - color: var(--text-base); - border: none; - cursor: pointer; - transition: - color 0.15s, - background-color 0.15s; + [data-slot="question-tab"] { + padding: 4px 12px; + font-size: 13px; + border-radius: 4px; + background-color: var(--surface-base); + color: var(--text-base); + border: none; + cursor: pointer; + transition: + color 0.15s, + background-color 0.15s; - &:hover { - background-color: var(--surface-base-hover); - } + &:hover { + background-color: var(--surface-base-hover); + } - &[data-active="true"] { - background-color: var(--surface-raised-base); - } + &[data-active="true"] { + background-color: var(--surface-raised-base); + } - &[data-answered="true"] { - color: var(--text-strong); - } - } - } + &[data-answered="true"] { + color: var(--text-strong); + } + } + } - [data-slot="question-content"] { - display: flex; - flex-direction: column; - gap: 8px; + [data-slot="question-content"] { + display: flex; + flex-direction: column; + gap: 8px; - [data-slot="question-text"] { - font-size: 14px; - color: var(--text-base); - line-height: 1.5; - } - } + [data-slot="question-text"] { + font-size: 14px; + color: var(--text-base); + line-height: 1.5; + } + } - [data-slot="question-options"] { - display: flex; - flex-direction: column; - gap: 4px; + [data-slot="question-options"] { + display: flex; + flex-direction: column; + gap: 4px; - [data-slot="question-option"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 2px; - padding: 8px 12px; - background-color: var(--surface-base); - border: 1px solid var(--border-weaker-base); - border-radius: 6px; - cursor: pointer; - text-align: left; - width: 100%; - transition: - background-color 0.15s, - border-color 0.15s; - position: relative; + [data-slot="question-option"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + padding: 8px 12px; + background-color: var(--surface-base); + border: 1px solid var(--border-weaker-base); + border-radius: 6px; + cursor: pointer; + text-align: left; + width: 100%; + transition: + background-color 0.15s, + border-color 0.15s; + position: relative; - &:hover { - background-color: var(--surface-base-hover); - border-color: var(--border-default); - } + &:hover { + background-color: var(--surface-base-hover); + border-color: var(--border-default); + } - &[data-picked="true"] { - [data-component="icon"] { - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); - color: var(--text-strong); - } - } + &[data-picked="true"] { + [data-component="icon"] { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--text-strong); + } + } - [data-slot="option-label"] { - font-size: 14px; - color: var(--text-base); - font-weight: 500; - } + [data-slot="option-label"] { + font-size: 14px; + color: var(--text-base); + font-weight: 500; + } - [data-slot="option-description"] { - font-size: 12px; - color: var(--text-weak); - } - } + [data-slot="option-description"] { + font-size: 12px; + color: var(--text-weak); + } + } - [data-slot="custom-input-form"] { - display: flex; - gap: 8px; - padding: 8px 0; - align-items: stretch; + [data-slot="custom-input-form"] { + display: flex; + gap: 8px; + padding: 8px 0; + align-items: stretch; - [data-slot="custom-input"] { - flex: 1; - padding: 8px 12px; - font-size: 14px; - border: 1px solid var(--border-default); - border-radius: 6px; - background-color: var(--surface-base); - color: var(--text-base); - outline: none; + [data-slot="custom-input"] { + flex: 1; + padding: 8px 12px; + font-size: 14px; + border: 1px solid var(--border-default); + border-radius: 6px; + background-color: var(--surface-base); + color: var(--text-base); + outline: none; - &:focus { - border-color: var(--border-focus); - } + &:focus { + border-color: var(--border-focus); + } - &::placeholder { - color: var(--text-weak); - } - } + &::placeholder { + color: var(--text-weak); + } + } - [data-component="button"] { - height: auto; - } - } - } + [data-component="button"] { + height: auto; + } + } + } - [data-slot="question-review"] { - display: flex; - flex-direction: column; - gap: 12px; + [data-slot="question-review"] { + display: flex; + flex-direction: column; + gap: 12px; - [data-slot="review-title"] { - display: none; - } + [data-slot="review-title"] { + display: none; + } - [data-slot="review-item"] { - display: flex; - flex-direction: column; - gap: 2px; - font-size: 13px; + [data-slot="review-item"] { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 13px; - [data-slot="review-label"] { - color: var(--text-weak); - } + [data-slot="review-label"] { + color: var(--text-weak); + } - [data-slot="review-value"] { - color: var(--text-strong); + [data-slot="review-value"] { + color: var(--text-strong); - &[data-answered="false"] { - color: var(--text-weak); - } - } - } - } + &[data-answered="false"] { + color: var(--text-weak); + } + } + } + } - [data-slot="question-actions"] { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; - } + [data-slot="question-actions"] { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; + } } [data-component="question-answers"] { - display: flex; - flex-direction: column; - gap: 12px; - padding: 8px 12px; + display: flex; + flex-direction: column; + gap: 12px; + padding: 8px 12px; - [data-slot="question-answer-item"] { - display: flex; - flex-direction: column; - gap: 2px; - font-size: 13px; + [data-slot="question-answer-item"] { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 13px; - [data-slot="question-text"] { - color: var(--text-weak); - } + [data-slot="question-text"] { + color: var(--text-weak); + } - [data-slot="answer-text"] { - color: var(--text-strong); - } - } + [data-slot="answer-text"] { + color: var(--text-strong); + } + } } [data-component="apply-patch-files"] { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } [data-component="apply-patch-file"] { - display: flex; - flex-direction: column; - border-top: 1px solid var(--border-weaker-base); + display: flex; + flex-direction: column; + border-top: 1px solid var(--border-weaker-base); - &:first-child { - border-top: 1px solid var(--border-weaker-base); - } + &:first-child { + border-top: 1px solid var(--border-weaker-base); + } - [data-slot="apply-patch-file-header"] { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - background-color: var(--surface-inset-base); - } + [data-slot="apply-patch-file-header"] { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background-color: var(--surface-inset-base); + } - [data-slot="apply-patch-file-action"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-base); - flex-shrink: 0; + [data-slot="apply-patch-file-action"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-base); + flex-shrink: 0; - &[data-type="delete"] { - color: var(--text-critical-base); - } + &[data-type="delete"] { + color: var(--text-critical-base); + } - &[data-type="add"] { - color: var(--text-success-base); - } + &[data-type="add"] { + color: var(--text-success-base); + } - &[data-type="move"] { - color: var(--text-warning-base); - } - } + &[data-type="move"] { + color: var(--text-warning-base); + } + } - [data-slot="apply-patch-file-path"] { - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - color: var(--text-weak); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex-grow: 1; - } + [data-slot="apply-patch-file-path"] { + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + color: var(--text-weak); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-grow: 1; + } - [data-slot="apply-patch-deletion-count"] { - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - color: var(--text-critical-base); - flex-shrink: 0; - } + [data-slot="apply-patch-deletion-count"] { + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + color: var(--text-critical-base); + flex-shrink: 0; + } } [data-component="apply-patch-file-diff"] { - max-height: 420px; - overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + max-height: 420px; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="tool-loaded-file"] { - display: flex; - align-items: center; - gap: 8px; - padding: 4px 0 4px 28px; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - color: var(--text-weak); + display: flex; + align-items: center; + gap: 8px; + padding: 4px 0 4px 28px; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + color: var(--text-weak); - [data-component="icon"] { - flex-shrink: 0; - color: var(--icon-weak); - } + [data-component="icon"] { + flex-shrink: 0; + color: var(--icon-weak); + } } diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 7aad01acea..9c975d5490 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -49,6 +49,7 @@ import { Tooltip } from "./tooltip" import { IconButton } from "./icon-button" import { createAutoScroll } from "../hooks" import { createResizeObserver } from "@solid-primitives/resize-observer" +import { MorphChevron } from "./morph-chevron" interface Diagnostic { range: { @@ -415,7 +416,7 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp toggleExpanded() }} > - +
props.expanded, + (expanded, prev) => { + if (prev === undefined) { + // Set initial state without animation + path?.setAttribute("d", expanded ? EXPANDED : COLLAPSED) + return + } + if (expanded) { + expandAnim?.beginElement() + } else { + collapseAnim?.beginElement() + } + }, + ), + ) + + return ( + + ) +} diff --git a/packages/ui/src/components/popover.css b/packages/ui/src/components/popover.css index b49542afd9..5a8ad10a0d 100644 --- a/packages/ui/src/components/popover.css +++ b/packages/ui/src/components/popover.css @@ -1,98 +1,136 @@ [data-slot="popover-trigger"] { - display: inline-flex; + display: inline-flex; } [data-component="popover-content"] { - z-index: 50; - min-width: 200px; - max-width: 320px; - border-radius: var(--radius-md); - background-color: var(--surface-raised-stronger-non-alpha); + z-index: 50; + min-width: 200px; + max-width: 320px; + border-radius: var(--radius-md); + background-color: var(--surface-raised-stronger-non-alpha); - border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); - background-clip: padding-box; - box-shadow: var(--shadow-md); + border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); + background-clip: padding-box; + box-shadow: var(--shadow-md); - transform-origin: var(--kb-popover-content-transform-origin); + transform-origin: var(--kb-popover-content-transform-origin); - &:focus-within { - outline: none; - } + animation: popoverContentHide var(--transition-duration) + var(--transition-easing) forwards; - &[data-closed] { - animation: popover-close 0.15s ease-out; - } + @starting-style { + animation: none; + } - &[data-expanded] { - animation: popover-open 0.15s ease-out; - } + &[data-expanded] { + pointer-events: auto; + animation: popoverContentShow var(--transition-duration) + var(--transition-easing) forwards; + } - [data-slot="popover-header"] { - display: flex; - padding: 12px; - padding-bottom: 0; - justify-content: space-between; - align-items: center; - gap: 8px; + [data-origin-top-right] { + transform-origin: top right; + } - [data-slot="popover-title"] { - flex: 1; - color: var(--text-strong); - margin: 0; + [data-origin-top-left] { + transform-origin: top left; + } - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } + [data-origin-bottom-right] { + transform-origin: bottom right; + } - [data-slot="popover-close-button"] { - flex-shrink: 0; - } - } + [data-origin-bottom-left] { + transform-origin: bottom left; + } - [data-slot="popover-description"] { - padding: 0 12px; - margin: 0; - color: var(--text-base); + &:focus-within { + outline: none; + } - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="popover-header"] { + display: flex; + padding: 12px; + padding-bottom: 0; + justify-content: space-between; + align-items: center; + gap: 8px; - [data-slot="popover-body"] { - padding: 12px; - } + [data-slot="popover-title"] { + flex: 1; + color: var(--text-strong); + margin: 0; - [data-slot="popover-arrow"] { - fill: var(--surface-raised-stronger-non-alpha); - } + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="popover-close-button"] { + flex-shrink: 0; + } + } + + [data-slot="popover-description"] { + padding: 0 12px; + margin: 0; + color: var(--text-base); + + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="popover-body"] { + padding: 12px; + } + + [data-slot="popover-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } } -@keyframes popover-open { - from { - opacity: 0; - transform: scale(0.96); - } - to { - opacity: 1; - transform: scale(1); - } +@keyframes popoverContentShow { + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } -@keyframes popover-close { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.96); - } +@keyframes popoverContentHide { + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } +} + +[data-component="model-popover-content"] { + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; + animation: popoverContentHide var(--transition-duration) + var(--transition-easing) forwards; + + @starting-style { + animation: none; + } + + &[data-expanded] { + pointer-events: auto; + animation: popoverContentShow var(--transition-duration) + var(--transition-easing) forwards; + } } diff --git a/packages/ui/src/components/progress-circle.css b/packages/ui/src/components/progress-circle.css index afaf72af61..e06cc3070c 100644 --- a/packages/ui/src/components/progress-circle.css +++ b/packages/ui/src/components/progress-circle.css @@ -1,12 +1,10 @@ [data-component="progress-circle"] { - transform: rotate(-90deg); + color: inherit; - [data-slot="progress-circle-background"] { - stroke: var(--border-weak-base); - } - - [data-slot="progress-circle-progress"] { - stroke: var(--border-active); - transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); - } + [data-slot="progress-circle-background"] { + transform-origin: 50% 50%; + transform: rotate(270deg); + stroke-opacity: 0.5; + transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); + } } diff --git a/packages/ui/src/components/progress-circle.tsx b/packages/ui/src/components/progress-circle.tsx index 02bd36bb71..40d1e2022f 100644 --- a/packages/ui/src/components/progress-circle.tsx +++ b/packages/ui/src/components/progress-circle.tsx @@ -1,4 +1,4 @@ -import { type ComponentProps, createMemo, splitProps } from "solid-js" +import { type ComponentProps, splitProps } from "solid-js" export interface ProgressCircleProps extends Pick, "class" | "classList"> { percentage: number @@ -9,26 +9,15 @@ export interface ProgressCircleProps extends Pick, "class" export function ProgressCircle(props: ProgressCircleProps) { const [split, rest] = splitProps(props, ["percentage", "size", "strokeWidth", "class", "classList"]) - const size = () => split.size || 16 - const strokeWidth = () => split.strokeWidth || 3 - - const viewBoxSize = 16 - const center = viewBoxSize / 2 - const radius = () => center - strokeWidth() / 2 - const circumference = createMemo(() => 2 * Math.PI * radius()) - - const offset = createMemo(() => { - const clampedPercentage = Math.max(0, Math.min(100, split.percentage || 0)) - const progress = clampedPercentage / 100 - return circumference() * (1 - progress) - }) + const size = () => split.size || 18 + const r = 7 return ( - - + { + const pct = Math.min(100, Math.max(0, split.percentage)) + const angle = (pct / 100) * 2 * Math.PI - Math.PI / 2 + const x = 9 + r * Math.cos(angle) + const y = 9 + r * Math.sin(angle) + const largeArc = pct > 50 ? 1 : 0 + return `M9 2A${r} ${r} 0 ${largeArc} 1 ${x} ${y}L9 9Z` + })()} + fill="currentColor" /> ) diff --git a/packages/ui/src/components/provider-icon.css b/packages/ui/src/components/provider-icon.css index 142c5ca7cd..a125315b34 100644 --- a/packages/ui/src/components/provider-icon.css +++ b/packages/ui/src/components/provider-icon.css @@ -1,5 +1,5 @@ [data-component="provider-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; + flex-shrink: 0; + width: 16px; + height: 16px; } diff --git a/packages/ui/src/components/radio-group.css b/packages/ui/src/components/radio-group.css index 3d672bb300..a6af7ca0f7 100644 --- a/packages/ui/src/components/radio-group.css +++ b/packages/ui/src/components/radio-group.css @@ -1,157 +1,169 @@ [data-component="radio-group"] { - display: flex; - flex-direction: column; - gap: calc(var(--spacing) * 2); + display: flex; + flex-direction: column; + gap: calc(var(--spacing) * 2); - [data-slot="radio-group-wrapper"] { - all: unset; - background-color: var(--surface-base); - border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); - margin: 0; - padding: 0; - position: relative; - width: fit-content; - } + [data-slot="radio-group-wrapper"] { + all: unset; + background-color: var(--surface-base); + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + margin: 0; + padding: 0; + position: relative; + width: fit-content; + } - [data-slot="radio-group-items"] { - display: inline-flex; - list-style: none; - flex-direction: row; - } + [data-slot="radio-group-items"] { + display: inline-flex; + list-style: none; + flex-direction: row; + } - [data-slot="radio-group-indicator"] { - background: var(--button-secondary-base); - border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); - content: ""; - opacity: var(--indicator-opacity, 1); - position: absolute; - transition: - opacity 300ms ease-in-out, - box-shadow 100ms ease-in-out, - width 150ms ease, - height 150ms ease, - transform 150ms ease; - } + [data-slot="radio-group-indicator"] { + background: var(--button-secondary-base); + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + content: ""; + opacity: var(--indicator-opacity, 1); + position: absolute; + transition-property: opacity, box-shadow, width, height, transform; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="radio-group-item"] { - position: relative; - } + [data-slot="radio-group-item"] { + position: relative; + } - /* Separator between items */ - [data-slot="radio-group-item"]:not(:first-of-type)::before { - background: var(--border-weak-base); - border-radius: var(--radius-xs); - content: ""; - inset: 6px 0; - position: absolute; - transition: opacity 150ms ease; - width: 1px; - transform: translateX(-0.5px); - } + /* Separator between items */ + [data-slot="radio-group-item"]:not(:first-of-type)::before { + background: var(--border-weak-base); + border-radius: var(--radius-xs); + content: ""; + inset: 6px 0; + position: absolute; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + width: 1px; + transform: translateX(-0.5px); + } - /* Hide separator when item or previous item is checked */ - [data-slot="radio-group-item"]:has([data-slot="radio-group-item-input"][data-checked])::before, - [data-slot="radio-group-item"]:has([data-slot="radio-group-item-input"][data-checked]) - + [data-slot="radio-group-item"]::before { - opacity: 0; - } + /* Hide separator when item or previous item is checked */ + [data-slot="radio-group-item"]:has( + [data-slot="radio-group-item-input"][data-checked] + )::before, + [data-slot="radio-group-item"]:has( + [data-slot="radio-group-item-input"][data-checked] + ) + + [data-slot="radio-group-item"]::before { + opacity: 0; + } - [data-slot="radio-group-item-label"] { - color: var(--text-weak); - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - border-radius: var(--radius-md); - cursor: pointer; - display: flex; - flex-wrap: nowrap; - gap: calc(var(--spacing) * 1); - line-height: 1; - padding: 6px 12px; - place-content: center; - position: relative; - transition-duration: 150ms; - transition-property: color, opacity; - transition-timing-function: ease-in-out; - user-select: none; - } + [data-slot="radio-group-item-label"] { + color: var(--text-weak); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + border-radius: var(--radius-md); + cursor: pointer; + display: flex; + flex-wrap: nowrap; + gap: calc(var(--spacing) * 1); + line-height: 1; + padding: 6px 12px; + place-content: center; + position: relative; + transition-property: color, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; + } - [data-slot="radio-group-item-input"] { - all: unset; - } + [data-slot="radio-group-item-input"] { + all: unset; + } - /* Checked state */ - [data-slot="radio-group-item-input"][data-checked] + [data-slot="radio-group-item-label"] { - color: var(--text-strong); - } + /* Checked state */ + [data-slot="radio-group-item-input"][data-checked] + + [data-slot="radio-group-item-label"] { + color: var(--text-strong); + } - /* Disabled state */ - [data-slot="radio-group-item-input"][data-disabled] + [data-slot="radio-group-item-label"] { - cursor: not-allowed; - opacity: 0.5; - } + /* Disabled state */ + [data-slot="radio-group-item-input"][data-disabled] + + [data-slot="radio-group-item-label"] { + cursor: not-allowed; + opacity: 0.5; + } - /* Hover state for unchecked, enabled items */ - [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + [data-slot="radio-group-item-label"] { - cursor: pointer; - user-select: none; - } + /* Hover state for unchecked, enabled items */ + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + + [data-slot="radio-group-item-label"] { + cursor: pointer; + user-select: none; + } - [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) - + [data-slot="radio-group-item-label"]:hover { - color: var(--text-base); - } + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + + [data-slot="radio-group-item-label"]:hover { + color: var(--text-base); + } - [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) - + [data-slot="radio-group-item-label"]:active { - opacity: 0.7; - } + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + + [data-slot="radio-group-item-label"]:active { + opacity: 0.7; + } - /* Focus state */ - [data-slot="radio-group-wrapper"]:has([data-slot="radio-group-item-input"]:focus-visible) - [data-slot="radio-group-indicator"] { - box-shadow: var(--shadow-xs-border-focus); - } + /* Focus state */ + [data-slot="radio-group-wrapper"]:has( + [data-slot="radio-group-item-input"]:focus-visible + ) + [data-slot="radio-group-indicator"] { + box-shadow: var(--shadow-xs-border-focus); + } - /* Hide indicator when nothing is checked */ - [data-slot="radio-group-wrapper"]:not(:has([data-slot="radio-group-item-input"][data-checked])) - [data-slot="radio-group-indicator"] { - --indicator-opacity: 0; - } + /* Hide indicator when nothing is checked */ + [data-slot="radio-group-wrapper"]:not( + :has([data-slot="radio-group-item-input"][data-checked]) + ) + [data-slot="radio-group-indicator"] { + --indicator-opacity: 0; + } - /* Vertical orientation */ - &[aria-orientation="vertical"] [data-slot="radio-group-items"] { - flex-direction: column; - } + /* Vertical orientation */ + &[aria-orientation="vertical"] [data-slot="radio-group-items"] { + flex-direction: column; + } - &[aria-orientation="vertical"] [data-slot="radio-group-item"]:not(:first-of-type)::before { - height: 1px; - width: auto; - inset: 0 6px; - transform: translateY(-0.5px); - } + &[aria-orientation="vertical"] + [data-slot="radio-group-item"]:not(:first-of-type)::before { + height: 1px; + width: auto; + inset: 0 6px; + transform: translateY(-0.5px); + } - /* Small size variant */ - &[data-size="small"] { - [data-slot="radio-group-item-label"] { - font-size: 12px; - padding: 4px 8px; - } + /* Small size variant */ + &[data-size="small"] { + [data-slot="radio-group-item-label"] { + font-size: 12px; + padding: 4px 8px; + } - [data-slot="radio-group-item"]:not(:first-of-type)::before { - inset: 4px 0; - } + [data-slot="radio-group-item"]:not(:first-of-type)::before { + inset: 4px 0; + } - &[aria-orientation="vertical"] [data-slot="radio-group-item"]:not(:first-of-type)::before { - inset: 0 4px; - } - } + &[aria-orientation="vertical"] + [data-slot="radio-group-item"]:not(:first-of-type)::before { + inset: 0 4px; + } + } - /* Disabled root state */ - &[data-disabled] { - opacity: 0.5; - cursor: not-allowed; - } + /* Disabled root state */ + &[data-disabled] { + opacity: 0.5; + cursor: not-allowed; + } } diff --git a/packages/ui/src/components/reasoning-icon.css b/packages/ui/src/components/reasoning-icon.css new file mode 100644 index 0000000000..81545cdf4f --- /dev/null +++ b/packages/ui/src/components/reasoning-icon.css @@ -0,0 +1,10 @@ +[data-component="reasoning-icon"] { + color: var(--icon-strong-base); + + [data-slot="reasoning-icon-percentage"] { + transition: clip-path 200ms cubic-bezier(0.25, 0, 0.5, 1); + clip-path: inset( + calc(100% - var(--reasoning-icon-percentage) * 100%) 0 0 0 + ); + } +} diff --git a/packages/ui/src/components/reasoning-icon.tsx b/packages/ui/src/components/reasoning-icon.tsx new file mode 100644 index 0000000000..0ad60e9640 --- /dev/null +++ b/packages/ui/src/components/reasoning-icon.tsx @@ -0,0 +1,32 @@ +import { type ComponentProps, splitProps } from "solid-js" + +export interface ReasoningIconProps extends Pick, "class" | "classList"> { + percentage: number + size?: number + strokeWidth?: number +} + +export function ReasoningIcon(props: ReasoningIconProps) { + const [split, rest] = splitProps(props, ["percentage", "size", "strokeWidth", "class", "classList"]) + + const size = () => split.size || 16 + const strokeWidth = () => split.strokeWidth || 1.25 + + return ( + + + + + ) +} diff --git a/packages/ui/src/components/resize-handle.css b/packages/ui/src/components/resize-handle.css index c309ff838b..5c26b490f7 100644 --- a/packages/ui/src/components/resize-handle.css +++ b/packages/ui/src/components/resize-handle.css @@ -1,58 +1,60 @@ [data-component="resize-handle"] { - position: absolute; - z-index: 10; + position: absolute; + z-index: 10; - &::after { - content: ""; - position: absolute; - opacity: 0; - transition: opacity 0.15s ease-in-out; - } + &::after { + content: ""; + position: absolute; + opacity: 0; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - &:hover::after, - &:active::after { - opacity: 1; - } + &:hover::after, + &:active::after { + opacity: 1; + } - &[data-direction="horizontal"] { - inset-block: 0; - inset-inline-end: 0; - width: 8px; - transform: translateX(50%); - cursor: col-resize; + &[data-direction="horizontal"] { + inset-block: 0; + inset-inline-end: 0; + width: 8px; + transform: translateX(50%); + cursor: col-resize; - &[data-edge="start"] { - inset-inline-start: 0; - inset-inline-end: auto; - transform: translateX(-50%); - } + &[data-edge="start"] { + inset-inline-start: 0; + inset-inline-end: auto; + transform: translateX(-50%); + } - &::after { - width: 3px; - inset-block: 0; - inset-inline-start: 50%; - transform: translateX(-50%); - } - } + &::after { + width: 3px; + inset-block: 0; + inset-inline-start: 50%; + transform: translateX(-50%); + } + } - &[data-direction="vertical"] { - inset-inline: 0; - inset-block-start: 0; - height: 8px; - transform: translateY(-50%); - cursor: row-resize; + &[data-direction="vertical"] { + inset-inline: 0; + inset-block-start: 0; + height: 8px; + transform: translateY(-50%); + cursor: row-resize; - &[data-edge="end"] { - inset-block-start: auto; - inset-block-end: 0; - transform: translateY(50%); - } + &[data-edge="end"] { + inset-block-start: auto; + inset-block-end: 0; + transform: translateY(50%); + } - &::after { - height: 3px; - inset-inline: 0; - inset-block-start: 50%; - transform: translateY(-50%); - } - } + &::after { + height: 3px; + inset-inline: 0; + inset-block-start: 50%; + transform: translateY(-50%); + } + } } diff --git a/packages/ui/src/components/scroll-fade.css b/packages/ui/src/components/scroll-fade.css new file mode 100644 index 0000000000..1e6b30d27a --- /dev/null +++ b/packages/ui/src/components/scroll-fade.css @@ -0,0 +1,122 @@ +[data-component="scroll-fade"] { + overflow: auto; + overscroll-behavior: contain; + scrollbar-width: none; + box-sizing: border-box; + color: inherit; + font: inherit; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + + &[data-direction="horizontal"] { + overflow-x: auto; + overflow-y: hidden; + + /* Both fades */ + &[data-fade-start][data-fade-end] { + mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + + /* Only start fade */ + &[data-fade-start]:not([data-fade-end]) { + mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black 100% + ); + -webkit-mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black 100% + ); + } + + /* Only end fade */ + &:not([data-fade-start])[data-fade-end] { + mask-image: linear-gradient( + to right, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to right, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + } + + &[data-direction="vertical"] { + overflow-y: auto; + overflow-x: hidden; + + &[data-fade-start][data-fade-end] { + mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + + /* Only start fade */ + &[data-fade-start]:not([data-fade-end]) { + mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black 100% + ); + } + + /* Only end fade */ + &:not([data-fade-start])[data-fade-end] { + mask-image: linear-gradient( + to bottom, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to bottom, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + } +} diff --git a/packages/ui/src/components/scroll-fade.tsx b/packages/ui/src/components/scroll-fade.tsx new file mode 100644 index 0000000000..0effb678a5 --- /dev/null +++ b/packages/ui/src/components/scroll-fade.tsx @@ -0,0 +1,207 @@ +import { type JSX, createEffect, createSignal, onCleanup, onMount, splitProps } from "solid-js" +import "./scroll-fade.css" + +export interface ScrollFadeProps extends JSX.HTMLAttributes { + direction?: "horizontal" | "vertical" + fadeStartSize?: number + fadeEndSize?: number + trackTransformSelector?: string + ref?: (el: HTMLDivElement) => void +} + +export function ScrollFade(props: ScrollFadeProps) { + const [local, others] = splitProps(props, [ + "children", + "direction", + "fadeStartSize", + "fadeEndSize", + "trackTransformSelector", + "class", + "style", + "ref", + ]) + + const direction = () => local.direction ?? "vertical" + const fadeStartSize = () => local.fadeStartSize ?? 20 + const fadeEndSize = () => local.fadeEndSize ?? 20 + + const getTransformOffset = (element: Element): number => { + const style = getComputedStyle(element) + const transform = style.transform + if (!transform || transform === "none") return 0 + + const match = transform.match(/matrix(?:3d)?\(([^)]+)\)/) + if (!match) return 0 + + const values = match[1].split(",").map((v) => parseFloat(v.trim())) + const isHorizontal = direction() === "horizontal" + + if (transform.startsWith("matrix3d")) { + return isHorizontal ? -(values[12] || 0) : -(values[13] || 0) + } else { + return isHorizontal ? -(values[4] || 0) : -(values[5] || 0) + } + } + + let containerRef: HTMLDivElement | undefined + + const [fadeStart, setFadeStart] = createSignal(0) + const [fadeEnd, setFadeEnd] = createSignal(0) + const [isScrollable, setIsScrollable] = createSignal(false) + + let lastScrollPos = 0 + let lastTransformPos = 0 + let lastScrollSize = 0 + let lastClientSize = 0 + + const updateFade = () => { + if (!containerRef) return + + const isHorizontal = direction() === "horizontal" + const scrollPos = isHorizontal ? containerRef.scrollLeft : containerRef.scrollTop + const scrollSize = isHorizontal ? containerRef.scrollWidth : containerRef.scrollHeight + const clientSize = isHorizontal ? containerRef.clientWidth : containerRef.clientHeight + + let transformPos = 0 + if (local.trackTransformSelector) { + const transformElement = containerRef.querySelector(local.trackTransformSelector) + if (transformElement) { + transformPos = getTransformOffset(transformElement) + } + } + + const effectiveScrollPos = Math.max(scrollPos, transformPos) + + if ( + effectiveScrollPos === lastScrollPos && + transformPos === lastTransformPos && + scrollSize === lastScrollSize && + clientSize === lastClientSize + ) { + return + } + + lastScrollPos = effectiveScrollPos + lastTransformPos = transformPos + lastScrollSize = scrollSize + lastClientSize = clientSize + + const maxScroll = scrollSize - clientSize + const canScroll = maxScroll > 1 + + setIsScrollable(canScroll) + + if (!canScroll) { + setFadeStart(0) + setFadeEnd(0) + return + } + + const progress = maxScroll > 0 ? effectiveScrollPos / maxScroll : 0 + + const startProgress = Math.min(progress / 0.1, 1) + setFadeStart(startProgress * fadeStartSize()) + + const endProgress = progress > 0.9 ? (1 - progress) / 0.1 : 1 + setFadeEnd(Math.max(0, endProgress) * fadeEndSize()) + } + + onMount(() => { + if (!containerRef) return + + updateFade() + + let rafId: number | undefined + let isPolling = false + let pollTimeout: ReturnType | undefined + + const startPolling = () => { + if (isPolling) return + isPolling = true + + const pollScroll = () => { + updateFade() + rafId = requestAnimationFrame(pollScroll) + } + rafId = requestAnimationFrame(pollScroll) + } + + const stopPolling = () => { + if (!isPolling) return + isPolling = false + if (rafId !== undefined) { + cancelAnimationFrame(rafId) + rafId = undefined + } + } + + const schedulePollingStop = () => { + if (pollTimeout !== undefined) clearTimeout(pollTimeout) + pollTimeout = setTimeout(stopPolling, 1000) + } + + const onActivity = () => { + updateFade() + if (local.trackTransformSelector) { + startPolling() + schedulePollingStop() + } + } + + containerRef.addEventListener("scroll", onActivity, { passive: true }) + + const resizeObserver = new ResizeObserver(() => { + lastScrollSize = 0 + lastClientSize = 0 + onActivity() + }) + resizeObserver.observe(containerRef) + + const mutationObserver = new MutationObserver(() => { + lastScrollSize = 0 + lastClientSize = 0 + requestAnimationFrame(onActivity) + }) + mutationObserver.observe(containerRef, { + childList: true, + subtree: true, + characterData: true, + }) + + onCleanup(() => { + containerRef?.removeEventListener("scroll", onActivity) + resizeObserver.disconnect() + mutationObserver.disconnect() + stopPolling() + if (pollTimeout !== undefined) clearTimeout(pollTimeout) + }) + }) + + createEffect(() => { + local.children + requestAnimationFrame(updateFade) + }) + + return ( +
{ + containerRef = el + local.ref?.(el) + }} + data-component="scroll-fade" + data-direction={direction()} + data-scrollable={isScrollable() || undefined} + data-fade-start={fadeStart() > 0 || undefined} + data-fade-end={fadeEnd() > 0 || undefined} + class={local.class} + style={{ + ...(typeof local.style === "object" ? local.style : {}), + "--scroll-fade-start": `${fadeStart()}px`, + "--scroll-fade-end": `${fadeEnd()}px`, + }} + {...others} + > + {local.children} +
+ ) +} diff --git a/packages/ui/src/components/scroll-reveal.tsx b/packages/ui/src/components/scroll-reveal.tsx new file mode 100644 index 0000000000..3e9c8b362b --- /dev/null +++ b/packages/ui/src/components/scroll-reveal.tsx @@ -0,0 +1,141 @@ +import { type JSX, onCleanup, splitProps } from "solid-js" +import { ScrollFade, type ScrollFadeProps } from './scroll-fade' + +const SCROLL_SPEED = 60 +const PAUSE_DURATION = 800 + +type ScrollAnimationState = { + rafId: number | null + startTime: number + running: boolean +} + +const startScrollAnimation = (containerEl: HTMLElement): ScrollAnimationState | null => { + containerEl.offsetHeight + + const extraWidth = containerEl.scrollWidth - containerEl.clientWidth + + if (extraWidth <= 0) { + return null + } + + const scrollDuration = (extraWidth / SCROLL_SPEED) * 1000 + const totalDuration = PAUSE_DURATION + scrollDuration + PAUSE_DURATION + scrollDuration + PAUSE_DURATION + + const state: ScrollAnimationState = { + rafId: null, + startTime: performance.now(), + running: true, + } + + const animate = (currentTime: number) => { + if (!state.running) return + + const elapsed = currentTime - state.startTime + const progress = (elapsed % totalDuration) / totalDuration + + const pausePercent = PAUSE_DURATION / totalDuration + const scrollPercent = scrollDuration / totalDuration + + const pauseEnd1 = pausePercent + const scrollEnd1 = pauseEnd1 + scrollPercent + const pauseEnd2 = scrollEnd1 + pausePercent + const scrollEnd2 = pauseEnd2 + scrollPercent + + let scrollPos = 0 + + if (progress < pauseEnd1) { + scrollPos = 0 + } else if (progress < scrollEnd1) { + const scrollProgress = (progress - pauseEnd1) / scrollPercent + scrollPos = scrollProgress * extraWidth + } else if (progress < pauseEnd2) { + scrollPos = extraWidth + } else if (progress < scrollEnd2) { + const scrollProgress = (progress - pauseEnd2) / scrollPercent + scrollPos = extraWidth * (1 - scrollProgress) + } else { + scrollPos = 0 + } + + containerEl.scrollLeft = scrollPos + state.rafId = requestAnimationFrame(animate) + } + + state.rafId = requestAnimationFrame(animate) + return state +} + +const stopScrollAnimation = (state: ScrollAnimationState | null, containerEl?: HTMLElement) => { + if (state) { + state.running = false + if (state.rafId !== null) { + cancelAnimationFrame(state.rafId) + } + } + if (containerEl) { + containerEl.scrollLeft = 0 + } +} + +export interface ScrollRevealProps extends Omit { + hoverDelay?: number +} + +export function ScrollReveal(props: ScrollRevealProps) { + const [local, others] = splitProps(props, ["children", "hoverDelay", "ref"]) + + const hoverDelay = () => local.hoverDelay ?? 300 + + let containerRef: HTMLDivElement | undefined + let hoverTimeout: ReturnType | undefined + let scrollAnimationState: ScrollAnimationState | null = null + + const handleMouseEnter: JSX.EventHandler = () => { + hoverTimeout = setTimeout(() => { + if (!containerRef) return + + containerRef.offsetHeight + + const isScrollable = containerRef.scrollWidth > containerRef.clientWidth + 1 + + if (isScrollable) { + stopScrollAnimation(scrollAnimationState, containerRef) + scrollAnimationState = startScrollAnimation(containerRef) + } + }, hoverDelay()) + } + + const handleMouseLeave: JSX.EventHandler = () => { + if (hoverTimeout) { + clearTimeout(hoverTimeout) + hoverTimeout = undefined + } + stopScrollAnimation(scrollAnimationState, containerRef) + scrollAnimationState = null + } + + onCleanup(() => { + if (hoverTimeout) { + clearTimeout(hoverTimeout) + } + stopScrollAnimation(scrollAnimationState, containerRef) + }) + + return ( + { + containerRef = el + local.ref?.(el) + }} + fadeStartSize={8} + fadeEndSize={8} + direction="horizontal" + onMouseEnter={handleMouseEnter} + onMouseLeave={handleMouseLeave} + {...others} + > + {local.children} + + ) +} diff --git a/packages/ui/src/components/select.css b/packages/ui/src/components/select.css index 25dd2eb40b..aafe421aa1 100644 --- a/packages/ui/src/components/select.css +++ b/packages/ui/src/components/select.css @@ -1,202 +1,165 @@ [data-component="select"] { - [data-slot="select-select-trigger"] { - padding: 0 4px 0 8px; - box-shadow: none; + [data-slot="select-select-trigger"] { + display: flex; + padding: 4px 8px !important; + align-items: center; + justify-content: space-between; + box-shadow: none; + transition-property: background-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - [data-slot="select-select-trigger-value"] { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - [data-slot="select-select-trigger-icon"] { - width: 16px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - color: var(--text-weak); - transition: transform 0.1s ease-in-out; - } + [data-slot="select-select-trigger-value"] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + [data-slot="select-select-trigger-icon"] { + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: var(--icon-base); + } - &[data-expanded] { - &[data-variant="secondary"] { - background-color: var(--button-secondary-hover); - } - &[data-variant="ghost"] { - background-color: var(--surface-raised-base-active); - } - &[data-variant="primary"] { - background-color: var(--icon-strong-active); - } - } - - &:not([data-expanded]):focus-visible { - &[data-variant="secondary"] { - background-color: var(--button-secondary-base); - } - &[data-variant="ghost"] { - background-color: var(--surface-raised-base-hover); - } - &[data-variant="primary"] { - background-color: var(--icon-strong-base); - } - } - } - - &[data-trigger-style="settings"] { - [data-slot="select-select-trigger"] { - padding: 6px 6px 6px 12px; - box-shadow: none; - border-radius: 6px; - min-width: 160px; - height: 32px; - justify-content: flex-end; - gap: 12px; - background-color: transparent; - - [data-slot="select-select-trigger-value"] { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-size: var(--font-size-base); - font-weight: var(--font-weight-regular); - } - [data-slot="select-select-trigger-icon"] { - width: 16px; - height: 20px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - color: var(--text-weak); - background-color: var(--surface-raised-base); - border-radius: 4px; - transition: transform 0.1s ease-in-out; - } - - &[data-slot="select-select-trigger"]:hover:not(:disabled), - &[data-slot="select-select-trigger"][data-expanded], - &[data-slot="select-select-trigger"][data-expanded]:hover:not(:disabled) { - background-color: var(--input-base); - box-shadow: var(--shadow-xs-border-base); - } - - &:not([data-expanded]):focus { - background-color: transparent; - box-shadow: none; - } - } - } + &:hover, + &[data-expanded] { + &[data-variant="secondary"] { + background-color: var(--button-secondary-hover); + } + &[data-variant="ghost"] { + background-color: var(--surface-raised-base-active); + } + &[data-variant="primary"] { + background-color: var(--icon-strong-active); + } + } + &:not([data-expanded]):focus, + &:not([data-expanded]):focus-visible { + &[data-variant="secondary"] { + background-color: var(--button-secondary-base); + } + &[data-variant="ghost"] { + background-color: transparent; + } + &[data-variant="primary"] { + background-color: var(--icon-strong-base); + } + } + } } [data-component="select-content"] { - min-width: 104px; - max-width: 23rem; - overflow: hidden; - border-radius: var(--radius-md); - background-color: var(--surface-raised-stronger-non-alpha); - padding: 4px; - box-shadow: var(--shadow-xs-border); - z-index: 60; + min-width: 8rem; + max-width: 23rem; + overflow: hidden; + border-radius: var(--radius-md); + background-color: var(--surface-raised-stronger-non-alpha); + padding: 4px; + box-shadow: var(--shadow-xs-border); + z-index: 50; + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; - &[data-expanded] { - animation: select-open 0.15s ease-out; - } + animation: selectContentHide var(--transition-duration) + var(--transition-easing) forwards; - [data-slot="select-select-content-list"] { - overflow-y: auto; - max-height: 12rem; - white-space: nowrap; - overflow-x: hidden; - display: flex; - flex-direction: column; + @starting-style { + animation: none; + } - &:focus { - outline: none; - } + &[data-expanded] { + pointer-events: auto; + animation: selectContentShow var(--transition-duration) + var(--transition-easing) forwards; + } - > *:not([role="presentation"]) + *:not([role="presentation"]) { - margin-top: 2px; - } - } + [data-slot="select-select-content-list"] { + overflow-y: auto; + max-height: 12rem; + white-space: nowrap; + overflow-x: hidden; + display: flex; + flex-direction: column; + &:focus { + outline: none; + } + > *:not([role="presentation"]) + *:not([role="presentation"]) { + margin-top: 2px; + } + } + [data-slot="select-select-item"] { + position: relative; + display: flex; + align-items: center; + padding: 4px 8px; + gap: 12px; + border-radius: var(--radius-sm); - [data-slot="select-select-item"] { - position: relative; - display: flex; - align-items: center; - padding: 2px 8px; - gap: 12px; - border-radius: 4px; - cursor: default; + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + outline: none; + user-select: none; - color: var(--text-strong); + &:hover { + background-color: var(--surface-raised-base-hover); + } + &[data-disabled] { + background-color: var(--surface-raised-base); + pointer-events: none; + } + [data-slot="select-select-item-indicator"] { + display: flex; + align-items: center; + justify-content: center; + margin-left: auto; + width: 16px; + height: 16px; + color: var(--icon-strong-base); - transition: - background-color 0.2s ease-in-out, - color 0.2s ease-in-out; - outline: none; - user-select: none; - - &[data-highlighted] { - background: var(--surface-raised-base-hover); - } - &[data-disabled] { - background-color: var(--surface-raised-base); - pointer-events: none; - } - [data-slot="select-select-item-indicator"] { - display: flex; - align-items: center; - justify-content: center; - margin-left: auto; - width: 16px; - height: 16px; - } - &:focus { - outline: none; - } - &:hover { - background: var(--surface-raised-base-hover); - } - } + svg { + color: var(--icon-strong-base); + } + } + &:focus { + outline: none; + } + &:hover { + background: var(--surface-raised-base-hover); + } + } } -[data-component="select-content"][data-trigger-style="settings"] { - min-width: 160px; - border-radius: 8px; - padding: 0; - - [data-slot="select-select-content-list"] { - padding: 4px; - } - - [data-slot="select-select-item"] { - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } +@keyframes selectContentShow { + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } -@keyframes select-open { - from { - opacity: 0; - transform: scale(0.95); - } - to { - opacity: 1; - transform: scale(1); - } +@keyframes selectContentHide { + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } } diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index 0386c329ec..fef00500a7 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -1,8 +1,10 @@ import { Select as Kobalte } from "@kobalte/core/select" -import { createMemo, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" +import { createMemo, createSignal, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" import { pipe, groupBy, entries, map } from "remeda" +import { Show } from "solid-js" import { Button, ButtonProps } from "./button" import { Icon } from "./icon" +import { MorphChevron } from "./morph-chevron" export type SelectProps = Omit>, "value" | "onSelect" | "children"> & { placeholder?: string @@ -38,6 +40,8 @@ export function Select(props: SelectProps & Omit) "triggerVariant", ]) + const [isOpen, setIsOpen] = createSignal(false) + const state = { key: undefined as string | undefined, cleanup: undefined as (() => void) | void, @@ -85,7 +89,7 @@ export function Select(props: SelectProps & Omit) data-component="select" data-trigger-style={local.triggerVariant} placement={local.triggerVariant === "settings" ? "bottom-end" : "bottom-start"} - gutter={4} + gutter={8} value={local.current} options={grouped()} optionValue={(x) => (local.value ? local.value(x) : (x as string))} @@ -115,7 +119,7 @@ export function Select(props: SelectProps & Omit) : (itemProps.item.rawValue as string)} - + )} @@ -124,6 +128,7 @@ export function Select(props: SelectProps & Omit) stop() }} onOpenChange={(open) => { + setIsOpen(open) local.onOpenChange?.(open) if (!open) stop() }} @@ -149,7 +154,12 @@ export function Select(props: SelectProps & Omit) }} - + + + + + + diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index 20d2fef152..d2ec356f4e 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -1,217 +1,216 @@ [data-component="session-review"] { - display: flex; - flex-direction: column; - gap: 8px; - height: 100%; - overflow-y: auto; - scrollbar-width: none; - contain: strict; - &::-webkit-scrollbar { - display: none; - } + display: flex; + flex-direction: column; + gap: 8px; + height: 100%; + overflow-y: auto; + scrollbar-width: none; + contain: strict; + &::-webkit-scrollbar { + display: none; + } - /* [data-slot="session-review-container"] { */ - /* height: 100%; */ - /* } */ + /* [data-slot="session-review-container"] { */ + /* height: 100%; */ + /* } */ - [data-slot="session-review-header"] { - position: sticky; - top: 0; - z-index: 20; - background-color: var(--background-stronger); - height: 32px; - flex-shrink: 0; - display: flex; - justify-content: space-between; - align-items: center; - align-self: stretch; - } + [data-slot="session-review-header"] { + position: sticky; + top: 0; + z-index: 20; + background-color: var(--background-stronger); + height: 32px; + flex-shrink: 0; + display: flex; + justify-content: space-between; + align-items: center; + align-self: stretch; + } - [data-slot="session-review-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-strong); - } + [data-slot="session-review-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-strong); + } - [data-slot="session-review-actions"] { - display: flex; - align-items: center; - column-gap: 16px; - padding-right: 1px; - } + [data-slot="session-review-actions"] { + display: flex; + align-items: center; + column-gap: 16px; + padding-right: 1px; + } - [data-component="sticky-accordion-header"] { - top: 40px; + [data-component="sticky-accordion-header"] { + top: 40px; - &[data-expanded]::before { - top: -40px; - } - } + &[data-expanded]::before { + top: -40px; + } + } - [data-slot="accordion-trigger"] { - background-color: var(--background-stronger) !important; - } + [data-slot="accordion-trigger"] { + background-color: var(--background-stronger) !important; + } - [data-slot="session-review-accordion-item"][data-selected] { - [data-slot="session-review-accordion-content"] { - box-shadow: var(--shadow-xs-border-select); - border-radius: var(--radius-lg); - } - } + [data-slot="session-review-accordion-item"][data-selected] { + [data-slot="session-review-accordion-content"] { + box-shadow: var(--shadow-xs-border-select); + border-radius: var(--radius-lg); + } + } - [data-slot="accordion-item"] { - [data-slot="accordion-content"] { - display: none; - } - &[data-expanded] { - [data-slot="accordion-content"] { - display: block; - } - } - } + [data-slot="accordion-item"] { + [data-slot="accordion-content"] { + /* Use grid-template-rows for smooth height transition */ + display: grid; + } + } - [data-slot="accordion-content"] { - -webkit-user-select: text; - user-select: text; - } + [data-slot="accordion-content"] { + -webkit-user-select: text; + user-select: text; + } - [data-slot="session-review-accordion-content"] { - position: relative; - overflow: hidden; - } + [data-slot="session-review-accordion-content"] { + position: relative; + overflow: hidden; + } - [data-slot="session-review-trigger-content"] { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - gap: 20px; - } + [data-slot="session-review-trigger-content"] { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + gap: 20px; + } - [data-slot="session-review-file-info"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 20px; - min-width: 0; - } + [data-slot="session-review-file-info"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 20px; + min-width: 0; + } - [data-slot="session-review-file-name-container"] { - display: flex; - flex-grow: 1; - min-width: 0; - } + [data-slot="session-review-file-name-container"] { + display: flex; + flex-grow: 1; + min-width: 0; + } - [data-slot="session-review-directory"] { - color: var(--text-base); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } + [data-slot="session-review-directory"] { + color: var(--text-base); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } - [data-slot="session-review-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } + [data-slot="session-review-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } - [data-slot="session-review-view-button"] { - display: flex; - align-items: center; - justify-content: center; - padding: 2px; - margin-left: 8px; - border: none; - background: transparent; - color: var(--text-base); - cursor: pointer; - border-radius: 4px; - opacity: 0; - transition: opacity 0.15s ease; + [data-slot="session-review-view-button"] { + display: flex; + align-items: center; + justify-content: center; + padding: 2px; + margin-left: 8px; + border: none; + background: transparent; + color: var(--text-base); + cursor: pointer; + border-radius: 4px; + opacity: 0; + transition-property: opacity, background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &:hover { - color: var(--text-strong); - background: var(--surface-base); - } - } + &:hover { + color: var(--text-strong); + background: var(--surface-base); + } + } - [data-slot="accordion-trigger"]:hover [data-slot="session-review-view-button"] { - opacity: 1; - } + [data-slot="accordion-trigger"]:hover + [data-slot="session-review-view-button"] { + opacity: 1; + } - [data-slot="session-review-trigger-actions"] { - flex-shrink: 0; - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - } + [data-slot="session-review-trigger-actions"] { + flex-shrink: 0; + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + } - [data-slot="session-review-change"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - } + [data-slot="session-review-change"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + } - [data-slot="session-review-change"][data-type="added"] { - color: var(--icon-diff-add-base); - } + [data-slot="session-review-change"][data-type="added"] { + color: var(--icon-diff-add-base); + } - [data-slot="session-review-change"][data-type="removed"] { - color: var(--icon-diff-delete-base); - } + [data-slot="session-review-change"][data-type="removed"] { + color: var(--icon-diff-delete-base); + } - [data-slot="session-review-file-container"] { - padding: 0; - } + [data-slot="session-review-file-container"] { + padding: 0; + } - [data-slot="session-review-image-container"] { - padding: 12px; - display: flex; - justify-content: center; - background: var(--background-stronger); - } + [data-slot="session-review-image-container"] { + padding: 12px; + display: flex; + justify-content: center; + background: var(--background-stronger); + } - [data-slot="session-review-image"] { - max-width: 100%; - max-height: 60vh; - object-fit: contain; - border-radius: 8px; - border: 1px solid var(--border-weak-base); - background: var(--background-base); - } + [data-slot="session-review-image"] { + max-width: 100%; + max-height: 60vh; + object-fit: contain; + border-radius: 8px; + border: 1px solid var(--border-weak-base); + background: var(--background-base); + } - [data-slot="session-review-image-placeholder"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - color: var(--text-weak); - } + [data-slot="session-review-image-placeholder"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + color: var(--text-weak); + } - [data-slot="session-review-audio-container"] { - padding: 12px; - display: flex; - justify-content: center; - background: var(--background-stronger); - } + [data-slot="session-review-audio-container"] { + padding: 12px; + display: flex; + justify-content: center; + background: var(--background-stronger); + } - [data-slot="session-review-audio"] { - width: 100%; - max-width: 560px; - } + [data-slot="session-review-audio"] { + width: 100%; + max-width: 560px; + } - [data-slot="session-review-audio-placeholder"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - color: var(--text-weak); - } + [data-slot="session-review-audio-placeholder"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + color: var(--text-weak); + } - [data-slot="session-review-diff-wrapper"] { - position: relative; - overflow: hidden; - --line-comment-z: 5; - --line-comment-popover-z: 30; - } + [data-slot="session-review-diff-wrapper"] { + position: relative; + overflow: hidden; + --line-comment-z: 5; + --line-comment-popover-z: 30; + } } diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 84ec934e24..b5a359707c 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -290,8 +290,8 @@ export const SessionReview = (props: SessionReviewProps) => {
{i18n.t("ui.sessionReview.title")}
- + options={["unified", "split"]} current={diffStyle()} value={(style) => style} label={(style) => @@ -501,6 +501,7 @@ export const SessionReview = (props: SessionReviewProps) => { value={diff.file} id={diffId(diff.file)} data-file={diff.file} + expanded={open().includes(diff.file)} data-slot="session-review-accordion-item" data-selected={props.focusedFile === diff.file ? "" : undefined} > diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index d1ade879e2..db73e801e1 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -1,572 +1,580 @@ [data-component="session-turn"] { - --session-turn-sticky-height: 0px; - --sticky-header-height: calc(var(--session-title-height, 0px) + var(--session-turn-sticky-height, 0px) + 24px); - /* flex: 1; */ - height: 100%; - min-height: 0; - min-width: 0; - display: flex; - align-items: flex-start; - justify-content: flex-start; - - [data-slot="session-turn-content"] { - flex-grow: 1; - width: 100%; - height: 100%; - min-width: 0; - overflow-y: auto; - scrollbar-width: none; - } - - [data-slot="session-turn-content"]::-webkit-scrollbar { - display: none; - } - - [data-slot="session-turn-message-container"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - min-width: 0; - gap: 18px; - overflow-anchor: none; - - [data-slot="session-turn-badge"] { - display: inline-flex; - align-items: center; - padding: 2px 6px; - border-radius: 4px; - font-family: var(--font-family-mono); - font-size: var(--font-size-x-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-normal); - white-space: nowrap; - color: var(--text-base); - background: var(--surface-raised-base); - } - } - - [data-slot="session-turn-attachments"] { - width: 100%; - min-width: 0; - align-self: stretch; - } - - [data-slot="session-turn-sticky"] { - width: calc(100% + 9px); - position: sticky; - top: var(--session-title-height, 0px); - z-index: 20; - background-color: var(--background-stronger); - margin-left: -9px; - padding-left: 9px; - /* padding-bottom: 12px; */ - display: flex; - flex-direction: column; - gap: 12px; - - &::before { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - background-color: var(--background-stronger); - z-index: -1; - } - - &::after { - content: ""; - position: absolute; - top: 100%; - left: 0; - right: 0; - height: 32px; - background: linear-gradient(to bottom, var(--background-stronger), transparent); - pointer-events: none; - } - } - - [data-slot="session-turn-message-header"] { - display: flex; - align-items: center; - align-self: stretch; - height: 32px; - } - - [data-slot="session-turn-message-content"] { - margin-top: 0; - max-width: 100%; - } - - [data-component="user-message"] [data-slot="user-message-text"] { - max-height: var(--user-message-collapsed-height, 64px); - } - - [data-component="user-message"][data-expanded="true"] [data-slot="user-message-text"] { - max-height: none; - } - - [data-component="user-message"][data-can-expand="true"] [data-slot="user-message-text"] { - padding-right: 36px; - padding-bottom: 28px; - } - - [data-component="user-message"][data-can-expand="true"]:not([data-expanded="true"]) - [data-slot="user-message-text"]::after { - content: ""; - position: absolute; - left: 0; - right: 0; - height: 8px; - bottom: 0px; - background: - linear-gradient(to bottom, transparent, var(--surface-weak)), - linear-gradient(to bottom, transparent, var(--surface-weak)); - pointer-events: none; - } - - [data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"] { - display: none; - position: absolute; - bottom: 6px; - right: 6px; - padding: 0; - } - - [data-component="user-message"][data-can-expand="true"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"], - [data-component="user-message"][data-expanded="true"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"] { - display: inline-flex; - align-items: center; - justify-content: center; - height: 22px; - width: 22px; - border: none; - border-radius: 6px; - background: transparent; - cursor: pointer; - color: var(--text-weak); - - [data-slot="icon-svg"] { - transition: transform 0.15s ease; - } - } - - [data-component="user-message"][data-expanded="true"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"] - [data-slot="icon-svg"] { - transform: rotate(180deg); - } - - [data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"]:hover { - background: var(--surface-raised-base); - color: var(--text-base); - } - - [data-slot="session-turn-user-badges"] { - display: flex; - align-items: center; - gap: 6px; - padding-left: 16px; - } - - [data-slot="session-turn-message-title"] { - width: 100%; - font-size: var(--font-size-large); - font-weight: 500; - color: var(--text-strong); - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - white-space: nowrap; - } - - [data-slot="session-turn-message-title"] h1 { - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - white-space: nowrap; - font-size: inherit; - font-weight: inherit; - } - - [data-slot="session-turn-typewriter"] { - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - white-space: nowrap; - } - - [data-slot="session-turn-summary-section"] { - width: 100%; - display: flex; - flex-direction: column; - gap: 24px; - align-items: flex-start; - align-self: stretch; - } - - [data-slot="session-turn-summary-header"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 4px; - align-self: stretch; - - [data-slot="session-turn-response"] { - position: relative; - width: 100%; - } - - [data-slot="session-turn-response-copy-wrapper"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } - - [data-slot="session-turn-response"]:hover [data-slot="session-turn-response-copy-wrapper"] { - opacity: 1; - } - - p { - font-size: var(--font-size-base); - line-height: var(--line-height-x-large); - } - } - - [data-slot="session-turn-summary-title"] { - font-size: 13px; - /* text-12-medium */ - font-weight: 500; - color: var(--text-weak); - } - - [data-slot="session-turn-markdown"], - [data-slot="session-turn-accordion"] [data-slot="accordion-content"] { - -webkit-user-select: text; - user-select: text; - } - - [data-slot="session-turn-markdown"] { - &[data-diffs="true"] { - font-size: 15px; - } - - &[data-fade="true"] > * { - animation: fadeUp 0.4s ease-out forwards; - opacity: 0; - - &:nth-child(1) { - animation-delay: 0.1s; - } - - &:nth-child(2) { - animation-delay: 0.2s; - } - - &:nth-child(3) { - animation-delay: 0.3s; - } - - &:nth-child(4) { - animation-delay: 0.4s; - } - - &:nth-child(5) { - animation-delay: 0.5s; - } - - &:nth-child(6) { - animation-delay: 0.6s; - } - - &:nth-child(7) { - animation-delay: 0.7s; - } - - &:nth-child(8) { - animation-delay: 0.8s; - } - - &:nth-child(9) { - animation-delay: 0.9s; - } - - &:nth-child(10) { - animation-delay: 1s; - } - - &:nth-child(11) { - animation-delay: 1.1s; - } - - &:nth-child(12) { - animation-delay: 1.2s; - } - - &:nth-child(13) { - animation-delay: 1.3s; - } - - &:nth-child(14) { - animation-delay: 1.4s; - } - - &:nth-child(15) { - animation-delay: 1.5s; - } - - &:nth-child(16) { - animation-delay: 1.6s; - } - - &:nth-child(17) { - animation-delay: 1.7s; - } - - &:nth-child(18) { - animation-delay: 1.8s; - } - - &:nth-child(19) { - animation-delay: 1.9s; - } - - &:nth-child(20) { - animation-delay: 2s; - } - - &:nth-child(21) { - animation-delay: 2.1s; - } - - &:nth-child(22) { - animation-delay: 2.2s; - } - - &:nth-child(23) { - animation-delay: 2.3s; - } - - &:nth-child(24) { - animation-delay: 2.4s; - } - - &:nth-child(25) { - animation-delay: 2.5s; - } - - &:nth-child(26) { - animation-delay: 2.6s; - } - - &:nth-child(27) { - animation-delay: 2.7s; - } - - &:nth-child(28) { - animation-delay: 2.8s; - } - - &:nth-child(29) { - animation-delay: 2.9s; - } - - &:nth-child(30) { - animation-delay: 3s; - } - } - } - - [data-slot="session-turn-summary-section"] { - position: relative; - - [data-slot="session-turn-summary-copy"] { - position: absolute; - top: 0; - right: 0; - opacity: 0; - transition: opacity 0.15s ease; - } - - &:hover [data-slot="session-turn-summary-copy"] { - opacity: 1; - } - } - - [data-slot="session-turn-accordion"] { - width: 100%; - } - - [data-component="sticky-accordion-header"] { - top: var(--sticky-header-height, 0px); - - &[data-expanded]::before { - top: calc(-1 * var(--sticky-header-height, 0px)); - } - } - - [data-slot="session-turn-accordion-trigger-content"] { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - gap: 20px; - - [data-expandable="false"] { - pointer-events: none; - } - } - - [data-slot="session-turn-file-info"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 20px; - min-width: 0; - } - - [data-slot="session-turn-file-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; - } - - [data-slot="session-turn-file-path"] { - display: flex; - flex-grow: 1; - min-width: 0; - } - - [data-slot="session-turn-directory"] { - color: var(--text-base); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } - - [data-slot="session-turn-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } - - [data-slot="session-turn-accordion-actions"] { - flex-shrink: 0; - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - } - - [data-slot="session-turn-accordion-content"] { - max-height: 240px; - /* max-h-60 */ - overflow-y: auto; - scrollbar-width: none; - } - - [data-slot="session-turn-accordion-content"]::-webkit-scrollbar { - display: none; - } - - [data-slot="session-turn-response-section"] { - width: calc(100% + 9px); - min-width: 0; - margin-left: -9px; - padding-left: 9px; - } - - [data-slot="session-turn-collapsible"] { - gap: 32px; - overflow: visible; - } - - [data-slot="session-turn-collapsible-trigger-content"] { - max-width: 100%; - display: flex; - align-items: center; - gap: 8px; - color: var(--text-weak); - - [data-slot="session-turn-trigger-icon"] { - color: var(--icon-base); - } - - [data-component="spinner"] { - width: 12px; - height: 12px; - margin-right: 4px; - } - - [data-component="icon"] { - width: 14px; - height: 14px; - } - } - - [data-slot="session-turn-retry-message"] { - font-weight: 500; - color: var(--syntax-critical); - } - - [data-slot="session-turn-retry-seconds"] { - color: var(--text-weak); - } - - [data-slot="session-turn-retry-attempt"] { - color: var(--text-weak); - } - - [data-slot="session-turn-status-text"] { - overflow: hidden; - text-overflow: ellipsis; - } - - [data-slot="session-turn-details-text"] { - font-size: 13px; - /* text-12-medium */ - font-weight: 500; - } - - .error-card { - color: var(--text-on-critical-base); - max-height: 240px; - overflow-y: auto; - } - - [data-slot="session-turn-collapsible-content-inner"] { - width: 100%; - min-width: 0; - display: flex; - flex-direction: column; - align-self: stretch; - gap: 12px; - margin-left: 12px; - padding-left: 12px; - padding-right: 12px; - border-left: 1px solid var(--border-base); - - > :first-child > [data-component="markdown"]:first-child { - margin-top: 0; - } - } - - [data-slot="session-turn-permission-parts"] { - width: 100%; - min-width: 0; - display: flex; - flex-direction: column; - gap: 12px; - } + --session-turn-sticky-height: 0px; + --sticky-header-height: calc( + var(--session-title-height, 0px) + + var(--session-turn-sticky-height, 0px) + + 24px + ); + /* flex: 1; */ + height: 100%; + min-height: 0; + min-width: 0; + display: flex; + align-items: flex-start; + justify-content: flex-start; + + [data-slot="session-turn-content"] { + flex-grow: 1; + width: 100%; + height: 100%; + min-width: 0; + overflow-y: auto; + scrollbar-width: none; + } + + [data-slot="session-turn-content"]::-webkit-scrollbar { + display: none; + } + + [data-slot="session-turn-message-container"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + min-width: 0; + gap: 18px; + overflow-anchor: none; + + [data-slot="session-turn-badge"] { + display: inline-flex; + align-items: center; + padding: 2px 6px; + border-radius: 4px; + font-family: var(--font-family-mono); + font-size: var(--font-size-x-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-normal); + white-space: nowrap; + color: var(--text-base); + background: var(--surface-raised-base); + } + } + + [data-slot="session-turn-attachments"] { + width: 100%; + min-width: 0; + align-self: stretch; + } + + [data-slot="session-turn-sticky"] { + width: calc(100% + 9px); + position: sticky; + top: var(--session-title-height, 0px); + z-index: 20; + background-color: var(--background-stronger); + margin-left: -9px; + padding-left: 9px; + /* padding-bottom: 12px; */ + display: flex; + flex-direction: column; + gap: 12px; + + &::before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: var(--background-stronger); + z-index: -1; + } + + &::after { + content: ""; + position: absolute; + top: 100%; + left: 0; + right: 0; + height: 32px; + background: linear-gradient( + to bottom, + var(--background-stronger), + transparent + ); + pointer-events: none; + } + } + + [data-slot="session-turn-message-header"] { + display: flex; + align-items: center; + align-self: stretch; + height: 32px; + } + + [data-slot="session-turn-message-content"] { + margin-top: 0; + max-width: 100%; + } + + [data-component="user-message"] [data-slot="user-message-text"] { + max-height: var(--user-message-collapsed-height, 64px); + transition: max-height 200ms cubic-bezier(0.25, 0, 0.5, 1); + } + + [data-component="user-message"][data-expanded="true"] + [data-slot="user-message-text"] { + max-height: 2000px; + } + + [data-component="user-message"][data-can-expand="true"] + [data-slot="user-message-text"] { + padding-right: 36px; + padding-bottom: 28px; + } + + [data-component="user-message"][data-can-expand="true"]:not( + [data-expanded="true"] + ) + [data-slot="user-message-text"]::after { + content: ""; + position: absolute; + left: 0; + right: 0; + height: 8px; + bottom: 0px; + background: + linear-gradient(to bottom, transparent, var(--surface-weak)), + linear-gradient(to bottom, transparent, var(--surface-weak)); + pointer-events: none; + } + + [data-component="user-message"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"] { + display: none; + position: absolute; + bottom: 6px; + right: 6px; + padding: 0; + } + + [data-component="user-message"][data-can-expand="true"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"], + [data-component="user-message"][data-expanded="true"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"] { + display: inline-flex; + align-items: center; + justify-content: center; + height: 22px; + width: 22px; + border: none; + border-radius: 6px; + background: transparent; + cursor: pointer; + color: var(--text-weak); + } + + [data-component="user-message"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"]:hover { + background: var(--surface-raised-base); + color: var(--text-base); + } + + [data-slot="session-turn-user-badges"] { + display: flex; + align-items: center; + gap: 6px; + padding-left: 16px; + } + + [data-slot="session-turn-message-title"] { + width: 100%; + font-size: var(--font-size-large); + font-weight: 500; + color: var(--text-strong); + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + white-space: nowrap; + } + + [data-slot="session-turn-message-title"] h1 { + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + white-space: nowrap; + font-size: inherit; + font-weight: inherit; + } + + [data-slot="session-turn-typewriter"] { + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + white-space: nowrap; + } + + [data-slot="session-turn-summary-section"] { + width: 100%; + display: flex; + flex-direction: column; + gap: 24px; + align-items: flex-start; + align-self: stretch; + } + + [data-slot="session-turn-summary-header"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; + align-self: stretch; + + [data-slot="session-turn-response"] { + position: relative; + width: 100%; + } + + [data-slot="session-turn-response-copy-wrapper"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } + + [data-slot="session-turn-response"]:hover + [data-slot="session-turn-response-copy-wrapper"] { + opacity: 1; + } + + p { + font-size: var(--font-size-base); + line-height: var(--line-height-x-large); + } + } + + [data-slot="session-turn-summary-title"] { + font-size: 13px; + /* text-12-medium */ + font-weight: 500; + color: var(--text-weak); + } + + [data-slot="session-turn-markdown"], + [data-slot="session-turn-accordion"] [data-slot="accordion-content"] { + -webkit-user-select: text; + user-select: text; + } + + [data-slot="session-turn-markdown"] { + &[data-diffs="true"] { + font-size: 15px; + } + + &[data-fade="true"] > * { + animation: fadeUp 0.4s ease-out forwards; + opacity: 0; + + &:nth-child(1) { + animation-delay: 0.1s; + } + + &:nth-child(2) { + animation-delay: 0.2s; + } + + &:nth-child(3) { + animation-delay: 0.3s; + } + + &:nth-child(4) { + animation-delay: 0.4s; + } + + &:nth-child(5) { + animation-delay: 0.5s; + } + + &:nth-child(6) { + animation-delay: 0.6s; + } + + &:nth-child(7) { + animation-delay: 0.7s; + } + + &:nth-child(8) { + animation-delay: 0.8s; + } + + &:nth-child(9) { + animation-delay: 0.9s; + } + + &:nth-child(10) { + animation-delay: 1s; + } + + &:nth-child(11) { + animation-delay: 1.1s; + } + + &:nth-child(12) { + animation-delay: 1.2s; + } + + &:nth-child(13) { + animation-delay: 1.3s; + } + + &:nth-child(14) { + animation-delay: 1.4s; + } + + &:nth-child(15) { + animation-delay: 1.5s; + } + + &:nth-child(16) { + animation-delay: 1.6s; + } + + &:nth-child(17) { + animation-delay: 1.7s; + } + + &:nth-child(18) { + animation-delay: 1.8s; + } + + &:nth-child(19) { + animation-delay: 1.9s; + } + + &:nth-child(20) { + animation-delay: 2s; + } + + &:nth-child(21) { + animation-delay: 2.1s; + } + + &:nth-child(22) { + animation-delay: 2.2s; + } + + &:nth-child(23) { + animation-delay: 2.3s; + } + + &:nth-child(24) { + animation-delay: 2.4s; + } + + &:nth-child(25) { + animation-delay: 2.5s; + } + + &:nth-child(26) { + animation-delay: 2.6s; + } + + &:nth-child(27) { + animation-delay: 2.7s; + } + + &:nth-child(28) { + animation-delay: 2.8s; + } + + &:nth-child(29) { + animation-delay: 2.9s; + } + + &:nth-child(30) { + animation-delay: 3s; + } + } + } + + [data-slot="session-turn-summary-section"] { + position: relative; + + [data-slot="session-turn-summary-copy"] { + position: absolute; + top: 0; + right: 0; + opacity: 0; + transition: opacity 0.15s ease; + } + + &:hover [data-slot="session-turn-summary-copy"] { + opacity: 1; + } + } + + [data-slot="session-turn-accordion"] { + width: 100%; + } + + [data-component="sticky-accordion-header"] { + top: var(--sticky-header-height, 0px); + + &[data-expanded]::before { + top: calc(-1 * var(--sticky-header-height, 0px)); + } + } + + [data-slot="session-turn-accordion-trigger-content"] { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + gap: 20px; + + [data-expandable="false"] { + pointer-events: none; + } + } + + [data-slot="session-turn-file-info"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 20px; + min-width: 0; + } + + [data-slot="session-turn-file-icon"] { + flex-shrink: 0; + width: 16px; + height: 16px; + } + + [data-slot="session-turn-file-path"] { + display: flex; + flex-grow: 1; + min-width: 0; + } + + [data-slot="session-turn-directory"] { + color: var(--text-base); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } + + [data-slot="session-turn-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } + + [data-slot="session-turn-accordion-actions"] { + flex-shrink: 0; + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + color: var(--icon-base); + } + + [data-slot="session-turn-accordion-content"] { + max-height: 240px; + /* max-h-60 */ + overflow-y: auto; + scrollbar-width: none; + } + + [data-slot="session-turn-accordion-content"]::-webkit-scrollbar { + display: none; + } + + [data-slot="session-turn-response-section"] { + width: calc(100% + 9px); + min-width: 0; + margin-left: -9px; + padding-left: 9px; + } + + [data-slot="session-turn-collapsible"] { + gap: 32px; + overflow: visible; + } + + [data-slot="session-turn-collapsible-trigger-content"] { + max-width: 100%; + display: flex; + align-items: center; + gap: 8px; + color: var(--text-weak); + + [data-slot="session-turn-trigger-icon"] { + color: var(--icon-base); + } + + [data-component="spinner"] { + width: 12px; + height: 12px; + margin-right: 4px; + } + + [data-component="icon"] { + width: 14px; + height: 14px; + } + } + + [data-slot="session-turn-retry-message"] { + font-weight: 500; + color: var(--syntax-critical); + } + + [data-slot="session-turn-retry-seconds"] { + color: var(--text-weak); + } + + [data-slot="session-turn-retry-attempt"] { + color: var(--text-weak); + } + + [data-slot="session-turn-status-text"] { + overflow: hidden; + text-overflow: ellipsis; + } + + [data-slot="session-turn-details-text"] { + font-size: 13px; + /* text-12-medium */ + font-weight: 500; + } + + .error-card { + color: var(--text-on-critical-base); + max-height: 240px; + overflow-y: auto; + } + + [data-slot="session-turn-collapsible-content-inner"] { + width: 100%; + min-width: 0; + display: flex; + flex-direction: column; + align-self: stretch; + gap: 12px; + margin-left: 12px; + padding-left: 12px; + padding-right: 12px; + border-left: 1px solid var(--border-base); + + > :first-child > [data-component="markdown"]:first-child { + margin-top: 0; + } + } + + [data-slot="session-turn-permission-parts"] { + width: 100%; + min-width: 0; + display: flex; + flex-direction: column; + gap: 12px; + } } diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index 3f176db702..af06757f2f 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -553,7 +553,7 @@ export function SessionTurn( data-slot="session-turn-collapsible-trigger-content" variant="ghost" size="small" - onClick={props.onStepsExpandedToggle ?? (() => {})} + onClick={props.onStepsExpandedToggle ?? (() => { })} aria-expanded={props.stepsExpanded} > diff --git a/packages/ui/src/components/spinner.css b/packages/ui/src/components/spinner.css index 2ca474dc3c..928a21c5ef 100644 --- a/packages/ui/src/components/spinner.css +++ b/packages/ui/src/components/spinner.css @@ -1,6 +1,6 @@ [data-component="spinner"] { - color: inherit; - flex-shrink: 0; - width: 18px; - aspect-ratio: 1; + color: inherit; + flex-shrink: 0; + width: 18px; + aspect-ratio: 1; } diff --git a/packages/ui/src/components/sticky-accordion-header.css b/packages/ui/src/components/sticky-accordion-header.css index 0fbc354fbe..acf9eb703b 100644 --- a/packages/ui/src/components/sticky-accordion-header.css +++ b/packages/ui/src/components/sticky-accordion-header.css @@ -1,16 +1,16 @@ [data-component="sticky-accordion-header"] { - position: sticky; - top: 0px; + position: sticky; + top: 0px; - &[data-expanded] { - z-index: 10; + &[data-expanded] { + z-index: 10; - &::before { - content: ""; - z-index: -10; - position: absolute; - inset: 0; - background-color: var(--background-stronger); - } - } + &::before { + content: ""; + z-index: -10; + position: absolute; + inset: 0; + background-color: var(--background-stronger); + } + } } diff --git a/packages/ui/src/components/switch.css b/packages/ui/src/components/switch.css index 89e8447322..4951e59989 100644 --- a/packages/ui/src/components/switch.css +++ b/packages/ui/src/components/switch.css @@ -1,132 +1,133 @@ [data-component="switch"] { - position: relative; - display: flex; - align-items: center; - gap: 8px; - cursor: default; + position: relative; + display: flex; + align-items: center; + gap: 8px; + cursor: default; - [data-slot="switch-input"] { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } + [data-slot="switch-input"] { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } - [data-slot="switch-control"] { - display: inline-flex; - align-items: center; - width: 28px; - height: 16px; - flex-shrink: 0; - border-radius: 3px; - border: 1px solid var(--border-weak-base); - background: var(--surface-base); - transition: - background-color 150ms, - border-color 150ms; - } + [data-slot="switch-control"] { + display: inline-flex; + align-items: center; + width: 28px; + height: 16px; + flex-shrink: 0; + border-radius: 3px; + border: 1px solid var(--border-weak-base); + background: var(--surface-base); + transition-property: background-color, border-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="switch-thumb"] { - width: 14px; - height: 14px; - box-sizing: content-box; + [data-slot="switch-thumb"] { + width: 14px; + height: 14px; + box-sizing: content-box; - border-radius: 2px; - border: 1px solid var(--border-base); - background: var(--icon-invert-base); + border-radius: 2px; + border: 1px solid var(--border-base); + background: var(--icon-invert-base); - /* shadows/shadow-xs */ - box-shadow: - 0 1px 2px -1px rgba(19, 16, 16, 0.04), - 0 1px 2px 0 rgba(19, 16, 16, 0.06), - 0 1px 3px 0 rgba(19, 16, 16, 0.08); + /* shadows/shadow-xs */ + box-shadow: + 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), + 0 1px 3px 0 rgba(19, 16, 16, 0.08); - transform: translateX(-1px); - transition: - transform 150ms, - background-color 150ms; - } + transform: translateX(-1px); + transition-property: transform, background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="switch-label"] { - user-select: none; - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="switch-label"] { + user-select: none; + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="switch-description"] { - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="switch-description"] { + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="switch-error"] { - color: var(--text-error); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="switch-error"] { + color: var(--text-error); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - &:hover:not([data-disabled], [data-readonly]) [data-slot="switch-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &:hover:not([data-disabled], [data-readonly]) [data-slot="switch-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &:focus-within:not([data-readonly]) [data-slot="switch-control"] { - border-color: var(--border-focus); - box-shadow: 0 0 0 2px var(--surface-focus); - } + &:focus-within:not([data-readonly]) [data-slot="switch-control"] { + border-color: var(--border-focus); + box-shadow: 0 0 0 2px var(--surface-focus); + } - &[data-checked] [data-slot="switch-control"] { - box-sizing: border-box; - border-color: var(--icon-strong-base); - background-color: var(--icon-strong-base); - } + &[data-checked] [data-slot="switch-control"] { + box-sizing: border-box; + border-color: var(--icon-strong-base); + background-color: var(--icon-strong-base); + } - &[data-checked] [data-slot="switch-thumb"] { - border: none; - transform: translateX(12px); - background-color: var(--icon-invert-base); - } + &[data-checked] [data-slot="switch-thumb"] { + border: none; + transform: translateX(12px); + background-color: var(--icon-invert-base); + } - &[data-checked]:hover:not([data-disabled], [data-readonly]) [data-slot="switch-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &[data-checked]:hover:not([data-disabled], [data-readonly]) + [data-slot="switch-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &[data-disabled] { - cursor: not-allowed; - } + &[data-disabled] { + cursor: not-allowed; + } - &[data-disabled] [data-slot="switch-control"] { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - } + &[data-disabled] [data-slot="switch-control"] { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + } - &[data-disabled] [data-slot="switch-thumb"] { - background-color: var(--icon-disabled); - } + &[data-disabled] [data-slot="switch-thumb"] { + background-color: var(--icon-disabled); + } - &[data-invalid] [data-slot="switch-control"] { - border-color: var(--border-error); - } + &[data-invalid] [data-slot="switch-control"] { + border-color: var(--border-error); + } - &[data-readonly] { - cursor: default; - pointer-events: none; - } + &[data-readonly] { + cursor: default; + pointer-events: none; + } } diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css index 56c3e083f5..c7829f7224 100644 --- a/packages/ui/src/components/tabs.css +++ b/packages/ui/src/components/tabs.css @@ -1,451 +1,454 @@ [data-component="tabs"] { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - background-color: var(--background-stronger); - overflow: clip; - - [data-slot="tabs-list"] { - height: 48px; - width: 100%; - position: relative; - display: flex; - align-items: center; - overflow-x: auto; - - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } - - /* After element to fill remaining space */ - &::after { - content: ""; - display: block; - flex-grow: 1; - height: 100%; - border-bottom: 1px solid var(--border-weak-base); - background-color: var(--background-base); - } - - &:empty::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - position: relative; - height: 100%; - display: flex; - align-items: center; - gap: 12px; - color: var(--text-base); - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - - white-space: nowrap; - flex-shrink: 0; - max-width: 280px; - border-bottom: 1px solid var(--border-weak-base); - border-right: 1px solid var(--border-weak-base); - background-color: var(--background-base); - - [data-slot="tabs-trigger"] { - display: flex; - align-items: center; - justify-content: center; - padding: 14px 24px 14px 12px; - outline: none; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - - &:focus-visible { - outline: none; - box-shadow: none; - } - } - - [data-slot="tabs-trigger-close-button"] { - display: flex; - align-items: center; - justify-content: center; - } - - [data-component="icon-button"] { - margin: -0.25rem; - } - - &:disabled { - pointer-events: none; - color: var(--text-weaker); - } - &:focus-visible { - outline: none; - box-shadow: none; - } - &:has([data-hidden]) { - [data-slot="tabs-trigger-close-button"] { - opacity: 0; - } - - &:hover { - [data-slot="tabs-trigger-close-button"] { - opacity: 1; - } - } - } - &:has([data-selected]) { - color: var(--text-strong); - background-color: transparent; - border-bottom-color: transparent; - [data-slot="tabs-trigger-close-button"] { - opacity: 1; - } - } - &:hover:not(:disabled):not([data-selected]) { - color: var(--text-strong); - } - &:has([data-slot="tabs-trigger-close-button"]) { - padding-right: 12px; - - [data-slot="tabs-trigger"] { - padding-right: 0; - } - } - } - - [data-slot="tabs-content"] { - overflow-y: auto; - flex: 1; - - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } - - &:focus-visible { - outline: none; - } - } - - &[data-variant="alt"] { - [data-slot="tabs-list"] { - padding-left: 24px; - padding-right: 24px; - gap: 12px; - border-bottom: 1px solid var(--border-weak-base); - background-color: transparent; - - &::after { - border: none; - background-color: transparent; - } - &:empty::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - border: none; - color: var(--text-base); - background-color: transparent; - border-bottom-width: 2px; - border-bottom-style: solid; - border-bottom-color: transparent; - gap: 4px; - - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); - - [data-slot="tabs-trigger"] { - height: 100%; - padding: 4px; - background-color: transparent; - border-bottom-width: 2px; - border-bottom-color: transparent; - } - - [data-slot="tabs-trigger-close-button"] { - display: flex; - align-items: center; - justify-content: center; - } - - [data-component="icon-button"] { - width: 16px; - height: 16px; - margin: 0; - } - - &:has([data-selected]) { - color: var(--text-strong); - background-color: transparent; - border-bottom-color: var(--icon-strong-base); - } - - &:hover:not(:disabled):not([data-selected]) { - color: var(--text-strong); - } - - &:has([data-slot="tabs-trigger-close-button"]) { - padding-right: 0; - [data-slot="tabs-trigger"] { - padding-right: 0; - } - } - } - - /* [data-slot="tabs-content"] { */ - /* } */ - } - - &[data-variant="pill"][data-orientation="horizontal"] { - background-color: transparent; - - [data-slot="tabs-list"] { - height: auto; - padding: 6px 0; - gap: 4px; - background-color: var(--background-base); - - &::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - height: 32px; - border: none; - border-radius: var(--radius-sm); - background-color: transparent; - gap: 0; - - /* text-13-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - - [data-slot="tabs-trigger"] { - height: 100%; - width: 100%; - padding: 0 12px; - background-color: transparent; - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - color: var(--text-strong); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-active); - color: var(--text-strong); - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - } - } - } - - &[data-variant="pill"][data-orientation="horizontal"][data-scope="filetree"] { - [data-slot="tabs-list"] { - height: 48px; - padding-inline: 12px; - gap: 8px; - align-items: center; - } - - [data-slot="tabs-trigger-wrapper"] { - height: 26px; - border-radius: 6px; - color: var(--text-weak); - - &:not(:has([data-selected])):hover:not(:disabled) { - color: var(--text-base); - } - - &:has([data-selected]) { - color: var(--text-strong); - } - } - } - - &[data-orientation="vertical"] { - flex-direction: row; - - [data-slot="tabs-list"] { - flex-direction: column; - width: auto; - height: 100%; - overflow-x: hidden; - overflow-y: auto; - padding: 8px; - gap: 4px; - background-color: var(--background-base); - border-right: 1px solid var(--border-weak-base); - - &::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - width: 100%; - height: 32px; - border: none; - border-radius: 8px; - background-color: transparent; - - [data-slot="tabs-trigger"] { - height: 100%; - padding: 0 8px; - gap: 8px; - justify-content: flex-start; - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-active); - color: var(--text-strong); - } - } - - [data-slot="tabs-content"] { - overflow-x: auto; - overflow-y: auto; - } - - &[data-variant="alt"] { - [data-slot="tabs-list"] { - padding: 8px; - gap: 4px; - border: none; - - &::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - height: 32px; - border: none; - border-radius: 8px; - - [data-slot="tabs-trigger"] { - border: none; - padding: 0 8px; - gap: 8px; - justify-content: flex-start; - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-hover); - color: var(--text-strong); - } - } - } - - &[data-variant="settings"] { - [data-slot="tabs-list"] { - width: 150px; - min-width: 150px; - - @media (min-width: 640px) { - width: 200px; - min-width: 200px; - } - padding: 12px; - gap: 0; - background-color: var(--background-base); - border-right: 1px solid var(--border-weak-base); - - &::after { - display: none; - } - } - - [data-slot="tabs-section-title"] { - width: 100%; - padding: 0 0 0 4px; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - color: var(--text-weak); - } - - [data-slot="tabs-trigger-wrapper"] { - height: 32px; - border: none; - border-radius: var(--radius-md); - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - - [data-slot="tabs-trigger"] { - border: none; - padding: 0 8px; - gap: 12px; - justify-content: flex-start; - width: 100%; - height: 100%; - } - - [data-component="icon"] { - color: var(--icon-base); - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-active); - color: var(--text-strong); - - [data-component="icon"] { - color: var(--icon-strong-base); - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - } - } - - [data-slot="tabs-content"] { - background-color: var(--surface-raised-stronger-non-alpha); - } - } - } + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background-color: var(--background-stronger); + overflow: clip; + + [data-slot="tabs-list"] { + height: 48px; + width: 100%; + position: relative; + display: flex; + align-items: center; + overflow-x: auto; + + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + + /* After element to fill remaining space */ + &::after { + content: ""; + display: block; + flex-grow: 1; + height: 100%; + border-bottom: 1px solid var(--border-weak-base); + background-color: var(--background-base); + } + + &:empty::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + position: relative; + height: 100%; + display: flex; + align-items: center; + gap: 12px; + color: var(--text-base); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + + white-space: nowrap; + flex-shrink: 0; + max-width: 280px; + border-bottom: 1px solid var(--border-weak-base); + border-right: 1px solid var(--border-weak-base); + background-color: var(--background-base); + transition-property: background-color, border-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + + [data-slot="tabs-trigger"] { + display: flex; + align-items: center; + justify-content: center; + padding: 14px 24px 14px 12px; + outline: none; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + + &:focus-visible { + outline: none; + box-shadow: none; + } + } + + [data-slot="tabs-trigger-close-button"] { + display: flex; + align-items: center; + justify-content: center; + } + + [data-component="icon-button"] { + margin: -0.25rem; + } + + &:disabled { + pointer-events: none; + color: var(--text-weaker); + } + &:focus-visible { + outline: none; + box-shadow: none; + } + &:has([data-hidden]) { + [data-slot="tabs-trigger-close-button"] { + opacity: 0; + } + + &:hover { + [data-slot="tabs-trigger-close-button"] { + opacity: 1; + } + } + } + &:has([data-selected]) { + color: var(--text-strong); + background-color: transparent; + border-bottom-color: transparent; + [data-slot="tabs-trigger-close-button"] { + opacity: 1; + } + } + &:hover:not(:disabled):not([data-selected]) { + color: var(--text-strong); + } + &:has([data-slot="tabs-trigger-close-button"]) { + padding-right: 12px; + + [data-slot="tabs-trigger"] { + padding-right: 0; + } + } + } + + [data-slot="tabs-content"] { + overflow-y: auto; + flex: 1; + + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + + &:focus-visible { + outline: none; + } + } + + &[data-variant="alt"] { + [data-slot="tabs-list"] { + padding-left: 24px; + padding-right: 24px; + gap: 12px; + border-bottom: 1px solid var(--border-weak-base); + background-color: transparent; + + &::after { + border: none; + background-color: transparent; + } + &:empty::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + border: none; + color: var(--text-base); + background-color: transparent; + border-bottom-width: 2px; + border-bottom-style: solid; + border-bottom-color: transparent; + gap: 4px; + + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); + + [data-slot="tabs-trigger"] { + height: 100%; + padding: 4px; + background-color: transparent; + border-bottom-width: 2px; + border-bottom-color: transparent; + } + + [data-slot="tabs-trigger-close-button"] { + display: flex; + align-items: center; + justify-content: center; + } + + [data-component="icon-button"] { + width: 16px; + height: 16px; + margin: 0; + } + + &:has([data-selected]) { + color: var(--text-strong); + background-color: transparent; + border-bottom-color: var(--icon-strong-base); + } + + &:hover:not(:disabled):not([data-selected]) { + color: var(--text-strong); + } + + &:has([data-slot="tabs-trigger-close-button"]) { + padding-right: 0; + [data-slot="tabs-trigger"] { + padding-right: 0; + } + } + } + + /* [data-slot="tabs-content"] { */ + /* } */ + } + + &[data-variant="pill"][data-orientation="horizontal"] { + background-color: transparent; + + [data-slot="tabs-list"] { + height: auto; + padding: 6px 0; + gap: 4px; + background-color: var(--background-base); + + &::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + height: 32px; + border: none; + border-radius: var(--radius-sm); + background-color: transparent; + gap: 0; + + /* text-13-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + + [data-slot="tabs-trigger"] { + height: 100%; + width: 100%; + padding: 0 12px; + background-color: transparent; + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + color: var(--text-strong); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-active); + color: var(--text-strong); + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + } + } + } + + &[data-variant="pill"][data-orientation="horizontal"][data-scope="filetree"] { + [data-slot="tabs-list"] { + height: 48px; + padding-inline: 12px; + gap: 8px; + align-items: center; + } + + [data-slot="tabs-trigger-wrapper"] { + height: 26px; + border-radius: 6px; + color: var(--text-weak); + + &:not(:has([data-selected])):hover:not(:disabled) { + color: var(--text-base); + } + + &:has([data-selected]) { + color: var(--text-strong); + } + } + } + + &[data-orientation="vertical"] { + flex-direction: row; + + [data-slot="tabs-list"] { + flex-direction: column; + width: auto; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + padding: 8px; + gap: 4px; + background-color: var(--background-base); + border-right: 1px solid var(--border-weak-base); + + &::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + width: 100%; + height: 32px; + border: none; + border-radius: 8px; + background-color: transparent; + + [data-slot="tabs-trigger"] { + height: 100%; + padding: 0 8px; + gap: 8px; + justify-content: flex-start; + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-active); + color: var(--text-strong); + } + } + + [data-slot="tabs-content"] { + overflow-x: auto; + overflow-y: auto; + } + + &[data-variant="alt"] { + [data-slot="tabs-list"] { + padding: 8px; + gap: 4px; + border: none; + + &::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + height: 32px; + border: none; + border-radius: 8px; + + [data-slot="tabs-trigger"] { + border: none; + padding: 0 8px; + gap: 8px; + justify-content: flex-start; + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-hover); + color: var(--text-strong); + } + } + } + + &[data-variant="settings"] { + [data-slot="tabs-list"] { + width: 150px; + min-width: 150px; + + @media (min-width: 640px) { + width: 200px; + min-width: 200px; + } + padding: 12px; + gap: 0; + background-color: var(--background-base); + border-right: 1px solid var(--border-weak-base); + + &::after { + display: none; + } + } + + [data-slot="tabs-section-title"] { + width: 100%; + padding: 0 0 0 4px; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + color: var(--text-weak); + } + + [data-slot="tabs-trigger-wrapper"] { + height: 32px; + border: none; + border-radius: var(--radius-md); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + + [data-slot="tabs-trigger"] { + border: none; + padding: 0 8px; + gap: 12px; + justify-content: flex-start; + width: 100%; + height: 100%; + } + + [data-component="icon"] { + color: var(--icon-base); + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-active); + color: var(--text-strong); + + [data-component="icon"] { + color: var(--icon-strong-base); + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + } + } + + [data-slot="tabs-content"] { + background-color: var(--surface-raised-stronger-non-alpha); + } + } + } } diff --git a/packages/ui/src/components/tag.css b/packages/ui/src/components/tag.css index 0e8b7b9f10..fef2c9ff20 100644 --- a/packages/ui/src/components/tag.css +++ b/packages/ui/src/components/tag.css @@ -1,37 +1,40 @@ [data-component="tag"] { - display: inline-flex; - align-items: center; - justify-content: center; - user-select: none; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; - border-radius: var(--radius-xs); - border: 0.5px solid var(--border-weak-base); - background: var(--surface-raised-base); - color: var(--text-base); + border-radius: var(--radius-xs); + border: 0.5px solid var(--border-weak-base); + background: var(--surface-raised-base); + color: var(--text-base); + transition-property: background-color, border-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &[data-size="normal"] { - height: 18px; - padding: 0 6px; + &[data-size="normal"] { + height: 18px; + padding: 0 6px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } - &[data-size="large"] { - height: 22px; - padding: 0 8px; + &[data-size="large"] { + height: 22px; + padding: 0 8px; - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } } diff --git a/packages/ui/src/components/text-field.css b/packages/ui/src/components/text-field.css index c94376be74..5568ac2dda 100644 --- a/packages/ui/src/components/text-field.css +++ b/packages/ui/src/components/text-field.css @@ -1,134 +1,134 @@ [data-component="input"] { - width: 100%; + width: 100%; - [data-slot="input-input"] { - width: 100%; - color: var(--text-strong); + [data-slot="input-input"] { + width: 100%; + color: var(--text-strong); - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - &:focus { - outline: none; - } + &:focus { + outline: none; + } - &::placeholder { - color: var(--text-weak); - } - } + &::placeholder { + color: var(--text-weak); + } + } - &[data-variant="normal"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; + &[data-variant="normal"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; - [data-slot="input-label"] { - color: var(--text-weak); + [data-slot="input-label"] { + color: var(--text-weak); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: 18px; /* 150% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: 18px; /* 150% */ + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="input-wrapper"] { - display: flex; - align-items: start; - justify-content: space-between; - width: 100%; - padding-right: 4px; + [data-slot="input-wrapper"] { + display: flex; + align-items: start; + justify-content: space-between; + width: 100%; + padding-right: 4px; - border-radius: var(--radius-md); - border: 1px solid var(--border-weak-base); - background: var(--input-base); + border-radius: var(--radius-md); + border: 1px solid var(--border-weak-base); + background: var(--input-base); - &:focus-within:not(:has([data-readonly])) { - border-color: transparent; - /* border/shadow-xs/select */ - box-shadow: - 0 0 0 3px var(--border-weak-selected), - 0 0 0 1px var(--border-selected), - 0 1px 2px -1px rgba(19, 16, 16, 0.25), - 0 1px 2px 0 rgba(19, 16, 16, 0.08), - 0 1px 3px 0 rgba(19, 16, 16, 0.12); - } + &:focus-within:not(:has([data-readonly])) { + border-color: transparent; + /* border/shadow-xs/select */ + box-shadow: + 0 0 0 3px var(--border-weak-selected), + 0 0 0 1px var(--border-selected), + 0 1px 2px -1px rgba(19, 16, 16, 0.25), + 0 1px 2px 0 rgba(19, 16, 16, 0.08), + 0 1px 3px 0 rgba(19, 16, 16, 0.12); + } - &:has([data-invalid]) { - background: var(--surface-critical-weak); - border: 1px solid var(--border-critical-selected); - } + &:has([data-invalid]) { + background: var(--surface-critical-weak); + border: 1px solid var(--border-critical-selected); + } - &:not(:has([data-slot="input-copy-button"])) { - padding-right: 0; - } - } + &:not(:has([data-slot="input-copy-button"])) { + padding-right: 0; + } + } - [data-slot="input-input"] { - color: var(--text-strong); + [data-slot="input-input"] { + color: var(--text-strong); - display: flex; - height: 32px; - padding: 2px 12px; - align-items: center; - flex: 1; - min-width: 0; + display: flex; + height: 32px; + padding: 2px 12px; + align-items: center; + flex: 1; + min-width: 0; - background: transparent; - border: none; + background: transparent; + border: none; - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - &:focus { - outline: none; - } + &:focus { + outline: none; + } - &::placeholder { - color: var(--text-weak); - } - } + &::placeholder { + color: var(--text-weak); + } + } - textarea[data-slot="input-input"] { - height: auto; - min-height: 32px; - padding: 6px 12px; - resize: none; - } + textarea[data-slot="input-input"] { + height: auto; + min-height: 32px; + padding: 6px 12px; + resize: none; + } - [data-slot="input-copy-button"] { - flex-shrink: 0; - margin-top: 4px; - color: var(--icon-base); + [data-slot="input-copy-button"] { + flex-shrink: 0; + margin-top: 4px; + color: var(--icon-base); - &:hover { - color: var(--icon-strong-base); - } - } + &:hover { + color: var(--icon-strong-base); + } + } - [data-slot="input-error"] { - color: var(--text-on-critical-base); + [data-slot="input-error"] { + color: var(--text-on-critical-base); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: 18px; /* 150% */ - letter-spacing: var(--letter-spacing-normal); - } - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: 18px; /* 150% */ + letter-spacing: var(--letter-spacing-normal); + } + } } diff --git a/packages/ui/src/components/toast.css b/packages/ui/src/components/toast.css index 1459bb1890..d02896e783 100644 --- a/packages/ui/src/components/toast.css +++ b/packages/ui/src/components/toast.css @@ -1,205 +1,205 @@ [data-component="toast-region"] { - position: fixed; - bottom: 48px; - right: 32px; - z-index: 1000; - display: flex; - flex-direction: column; - gap: 8px; - max-width: 400px; - width: 100%; - pointer-events: none; + position: fixed; + bottom: 48px; + right: 32px; + z-index: 1000; + display: flex; + flex-direction: column; + gap: 8px; + max-width: 400px; + width: 100%; + pointer-events: none; - [data-slot="toast-list"] { - display: flex; - flex-direction: column; - gap: 8px; - list-style: none; - margin: 0; - padding: 0; - } + [data-slot="toast-list"] { + display: flex; + flex-direction: column; + gap: 8px; + list-style: none; + margin: 0; + padding: 0; + } } [data-component="toast"] { - display: flex; - align-items: flex-start; - gap: 20px; - padding: 16px 20px; - pointer-events: auto; - transition: all 150ms ease-out; + display: flex; + align-items: flex-start; + gap: 20px; + padding: 16px 20px; + pointer-events: auto; + transition: all 150ms ease-out; - border-radius: var(--radius-lg); - border: 1px solid var(--border-weak-base); - background: var(--surface-float-base); - color: var(--text-invert-base); - box-shadow: var(--shadow-md); + border-radius: var(--radius-lg); + border: 1px solid var(--border-weak-base); + background: var(--surface-float-base); + color: var(--text-invert-base); + box-shadow: var(--shadow-md); - [data-slot="toast-inner"] { - display: flex; - align-items: flex-start; - gap: 10px; - } + [data-slot="toast-inner"] { + display: flex; + align-items: flex-start; + gap: 10px; + } - &[data-opened] { - animation: toastPopIn 150ms ease-out; - } + &[data-opened] { + animation: toastPopIn 150ms ease-out; + } - &[data-closed] { - animation: toastPopOut 100ms ease-in forwards; - } + &[data-closed] { + animation: toastPopOut 100ms ease-in forwards; + } - &[data-swipe="move"] { - transform: translateX(var(--kb-toast-swipe-move-x)); - } + &[data-swipe="move"] { + transform: translateX(var(--kb-toast-swipe-move-x)); + } - &[data-swipe="cancel"] { - transform: translateX(0); - transition: transform 200ms ease-out; - } + &[data-swipe="cancel"] { + transform: translateX(0); + transition: transform 200ms ease-out; + } - &[data-swipe="end"] { - animation: toastSwipeOut 100ms ease-out forwards; - } + &[data-swipe="end"] { + animation: toastSwipeOut 100ms ease-out forwards; + } - /* &[data-variant="success"] { */ - /* border-color: var(--color-semantic-positive); */ - /* } */ - /**/ - /* &[data-variant="error"] { */ - /* border-color: var(--color-semantic-danger); */ - /* } */ - /**/ - /* &[data-variant="loading"] { */ - /* border-color: var(--color-semantic-info); */ - /* } */ + /* &[data-variant="success"] { */ + /* border-color: var(--color-semantic-positive); */ + /* } */ + /**/ + /* &[data-variant="error"] { */ + /* border-color: var(--color-semantic-danger); */ + /* } */ + /**/ + /* &[data-variant="loading"] { */ + /* border-color: var(--color-semantic-info); */ + /* } */ - [data-slot="toast-icon"] { - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; + [data-slot="toast-icon"] { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; - [data-component="icon"] { - color: var(--text-invert-stronger); - /* color: var(--icon-invert-base); */ - } - } + [data-component="icon"] { + color: var(--text-invert-stronger); + /* color: var(--icon-invert-base); */ + } + } - [data-slot="toast-content"] { - flex: 1; - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; - } + [data-slot="toast-content"] { + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; + } - [data-slot="toast-title"] { - color: var(--text-invert-strong); + [data-slot="toast-title"] { + color: var(--text-invert-strong); - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - margin: 0; - } + margin: 0; + } - [data-slot="toast-description"] { - color: var(--text-invert-base); - text-wrap-style: pretty; + [data-slot="toast-description"] { + color: var(--text-invert-base); + text-wrap-style: pretty; - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); - margin: 0; - } + margin: 0; + } - [data-slot="toast-actions"] { - display: flex; - gap: 16px; - margin-top: 8px; - } + [data-slot="toast-actions"] { + display: flex; + gap: 16px; + margin-top: 8px; + } - [data-slot="toast-action"] { - background: none; - border: none; - padding: 0; - cursor: pointer; + [data-slot="toast-action"] { + background: none; + border: none; + padding: 0; + cursor: pointer; - color: var(--text-invert-weak); - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); + color: var(--text-invert-weak); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); - &:hover { - text-decoration: underline; - } + &:hover { + text-decoration: underline; + } - &:first-child { - color: var(--text-invert-strong); - } - } + &:first-child { + color: var(--text-invert-strong); + } + } - [data-slot="toast-close-button"] { - flex-shrink: 0; - } + [data-slot="toast-close-button"] { + flex-shrink: 0; + } - [data-slot="toast-progress-track"] { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 3px; - background-color: var(--surface-base); - border-radius: 0 0 var(--radius-lg) var(--radius-lg); - overflow: hidden; - } + [data-slot="toast-progress-track"] { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 3px; + background-color: var(--surface-base); + border-radius: 0 0 var(--radius-lg) var(--radius-lg); + overflow: hidden; + } - [data-slot="toast-progress-fill"] { - height: 100%; - width: var(--kb-toast-progress-fill-width); - background-color: var(--color-primary); - transition: width 250ms linear; - } + [data-slot="toast-progress-fill"] { + height: 100%; + width: var(--kb-toast-progress-fill-width); + background-color: var(--color-primary); + transition: width 250ms linear; + } } @keyframes toastPopIn { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } } @keyframes toastPopOut { - from { - opacity: 1; - transform: translateY(0); - } - to { - opacity: 0; - transform: translateY(20px); - } + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(20px); + } } @keyframes toastSwipeOut { - from { - transform: translateX(var(--kb-toast-swipe-end-x)); - } - to { - transform: translateX(100%); - } + from { + transform: translateX(var(--kb-toast-swipe-end-x)); + } + to { + transform: translateX(100%); + } } diff --git a/packages/ui/src/components/tooltip.css b/packages/ui/src/components/tooltip.css index f02c2ca639..4abeb81aa6 100644 --- a/packages/ui/src/components/tooltip.css +++ b/packages/ui/src/components/tooltip.css @@ -1,74 +1,74 @@ [data-component="tooltip-trigger"] { - display: flex; + display: flex; } [data-slot="tooltip-keybind"] { - display: flex; - align-items: center; - gap: 12px; + display: flex; + align-items: center; + gap: 12px; } [data-slot="tooltip-keybind-key"] { - color: var(--text-invert-base); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); + color: var(--text-invert-base); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); } [data-component="tooltip"] { - z-index: 1000; - max-width: 320px; - border-radius: var(--radius-sm); - background-color: var(--surface-float-base); - color: var(--text-invert-strong); - background: var(--surface-float-base); - padding: 2px 8px; - border: 1px solid var(--border-weak-base, rgba(0, 0, 0, 0.07)); + z-index: 1000; + max-width: 320px; + border-radius: var(--radius-sm); + background-color: var(--surface-float-base); + color: var(--text-invert-strong); + background: var(--surface-float-base); + padding: 2px 8px; + border: 1px solid var(--border-weak-base, rgba(0, 0, 0, 0.07)); - box-shadow: var(--shadow-md); - pointer-events: none !important; - /* transition: all 150ms ease-out; */ - /* transform: translate3d(0, 0, 0); */ - /* transform-origin: var(--kb-tooltip-content-transform-origin); */ + box-shadow: var(--shadow-md); + pointer-events: none !important; + /* transition: all 150ms ease-out; */ + /* transform: translate3d(0, 0, 0); */ + /* transform-origin: var(--kb-tooltip-content-transform-origin); */ - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &[data-expanded] { - opacity: 1; - /* transform: translate3d(0, 0, 0); */ - } + &[data-expanded] { + opacity: 1; + /* transform: translate3d(0, 0, 0); */ + } - &[data-closed]:not([data-force-open="true"]) { - opacity: 0; - } + &[data-closed]:not([data-force-open="true"]) { + opacity: 0; + } - /* &[data-placement="top"] { */ - /* &[data-closed] { */ - /* transform: translate3d(0, 4px, 0); */ - /* } */ - /* } */ - /**/ - /* &[data-placement="bottom"] { */ - /* &[data-closed] { */ - /* transform: translate3d(0, -4px, 0); */ - /* } */ - /* } */ - /**/ - /* &[data-placement="left"] { */ - /* &[data-closed] { */ - /* transform: translate3d(4px, 0, 0); */ - /* } */ - /* } */ - /**/ - /* &[data-placement="right"] { */ - /* &[data-closed] { */ - /* transform: translate3d(-4px, 0, 0); */ - /* } */ - /* } */ + /* &[data-placement="top"] { */ + /* &[data-closed] { */ + /* transform: translate3d(0, 4px, 0); */ + /* } */ + /* } */ + /**/ + /* &[data-placement="bottom"] { */ + /* &[data-closed] { */ + /* transform: translate3d(0, -4px, 0); */ + /* } */ + /* } */ + /**/ + /* &[data-placement="left"] { */ + /* &[data-closed] { */ + /* transform: translate3d(4px, 0, 0); */ + /* } */ + /* } */ + /**/ + /* &[data-placement="right"] { */ + /* &[data-closed] { */ + /* transform: translate3d(-4px, 0, 0); */ + /* } */ + /* } */ } diff --git a/packages/ui/src/components/typewriter.css b/packages/ui/src/components/typewriter.css index e978312a9f..f99f2d8dac 100644 --- a/packages/ui/src/components/typewriter.css +++ b/packages/ui/src/components/typewriter.css @@ -1,14 +1,14 @@ @keyframes blink { - 0%, - 50% { - opacity: 1; - } - 51%, - 100% { - opacity: 0; - } + 0%, + 50% { + opacity: 1; + } + 51%, + 100% { + opacity: 0; + } } .blinking-cursor { - animation: blink 1s step-end infinite; + animation: blink 1s step-end infinite; } diff --git a/packages/ui/src/context/dialog.tsx b/packages/ui/src/context/dialog.tsx index afba5f648c..bd47b86d3f 100644 --- a/packages/ui/src/context/dialog.tsx +++ b/packages/ui/src/context/dialog.tsx @@ -28,6 +28,7 @@ const Context = createContext>() function init() { const [active, setActive] = createSignal() + const [renders, setRenders] = createSignal>({}) const timer = { current: undefined as ReturnType | undefined } const lock = { value: false } @@ -118,12 +119,28 @@ function init() { setActive({ id, node, dispose, owner, onClose, setClosing }) } + const render = (element: JSX.Element, id: string, owner: Owner) => { + setRenders((renders) => ({ ...renders, [id]: element })) + show(() => element, owner, () => { + setRenders((renders) => { + const { [id]: _, ...rest } = renders + return rest + }) + }) + } + + const isActive = (id: string) => { + return renders()[id] !== undefined + } + return { get active() { return active() }, + isActive, close, show, + render, } } @@ -152,10 +169,17 @@ export function useDialog() { get active() { return ctx.active }, + isActive(id: string) { + return ctx.isActive(id) + }, show(element: DialogElement, onClose?: () => void) { const base = ctx.active?.owner ?? owner ctx.show(element, base, onClose) }, + render(element: JSX.Element, id: string) { + const base = ctx.active?.owner ?? owner + ctx.render(element, id, base) + }, close() { ctx.close() }, diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css index 3ed0310ef2..7c8548734d 100644 --- a/packages/ui/src/styles/index.css +++ b/packages/ui/src/styles/index.css @@ -33,8 +33,10 @@ @import "../components/markdown.css" layer(components); @import "../components/message-part.css" layer(components); @import "../components/message-nav.css" layer(components); +@import "../components/morph-chevron.css" layer(components); @import "../components/popover.css" layer(components); @import "../components/progress-circle.css" layer(components); +@import "../components/reasoning-icon.css" layer(components); @import "../components/radio-group.css" layer(components); @import "../components/resize-handle.css" layer(components); @import "../components/select.css" layer(components); diff --git a/packages/ui/src/styles/utilities.css b/packages/ui/src/styles/utilities.css index 8c954f1fe4..990259acc2 100644 --- a/packages/ui/src/styles/utilities.css +++ b/packages/ui/src/styles/utilities.css @@ -1,131 +1,174 @@ :root { - interpolate-size: allow-keywords; + interpolate-size: allow-keywords; - [data-popper-positioner] { - pointer-events: none; - } + /* Transition tokens */ + --transition-duration: 200ms; + --transition-easing: cubic-bezier(0.25, 0, 0.5, 1); + --transition-fast: 150ms; + --transition-slow: 300ms; - /* ::selection { */ - /* background-color: color-mix(in srgb, var(--color-primary) 33%, transparent); */ - /* background-color: var(--color-primary); */ - /* color: var(--color-background); */ - /* } */ + /* Allow height transitions from 0 to auto */ + @supports (interpolate-size: allow-keywords) { + interpolate-size: allow-keywords; + } - ::-webkit-scrollbar-track { - background: transparent; - } + [data-popper-positioner] { + pointer-events: none; + } - ::-webkit-scrollbar-thumb { - background-color: var(--surface-float-base); - border-radius: var(--radius-md); - } + /* ::selection { */ + /* background-color: color-mix(in srgb, var(--color-primary) 33%, transparent); */ + /* background-color: var(--color-primary); */ + /* color: var(--color-background); */ + /* } */ - * { - scrollbar-color: var(--surface-float-base) transparent; - } + ::-webkit-scrollbar-track { + background: transparent; + } + + ::-webkit-scrollbar-thumb { + background-color: var(--surface-float-base); + border-radius: var(--radius-md); + } + + * { + scrollbar-color: var(--surface-float-base) transparent; + } } .no-scrollbar { - &::-webkit-scrollbar { - display: none; - } - /* Hide scrollbar for IE, Edge and Firefox */ - & { - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; /* Firefox */ - } + &::-webkit-scrollbar { + display: none; + } + /* Hide scrollbar for IE, Edge and Firefox */ + & { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } } .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } .truncate-start { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; } .text-12-regular { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); } .text-12-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); } .text-12-mono { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-feature-settings-mono); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-mono); + font-feature-settings: var(--font-feature-settings-mono); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); } .text-14-regular { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); } .text-14-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); } .text-14-mono { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-feature-settings-mono); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-mono); + font-feature-settings: var(--font-feature-settings-mono); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); } .text-16-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 150% */ - letter-spacing: var(--letter-spacing-tight); + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 150% */ + letter-spacing: var(--letter-spacing-tight); } .text-20-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-x-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 120% */ - letter-spacing: var(--letter-spacing-tightest); + font-family: var(--font-family-sans); + font-size: var(--font-size-x-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 120% */ + letter-spacing: var(--letter-spacing-tightest); +} + +/* Transition utility classes */ +.transition-colors { + transition-property: background-color, border-color, color, fill, stroke; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-opacity { + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-transform { + transition-property: transform; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-shadow { + transition-property: box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-interactive { + transition-property: + background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } From fe66ca163cbb9d689cf296c4c2f7a63414c1cf45 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Fri, 30 Jan 2026 17:58:31 +0000 Subject: [PATCH 06/58] chore: generate --- packages/app/src/components/prompt-input.tsx | 24 +- .../app/src/components/settings-general.tsx | 32 +- packages/ui/src/components/accordion.css | 184 +-- packages/ui/src/components/avatar.css | 64 +- packages/ui/src/components/basic-tool.css | 168 +-- packages/ui/src/components/button.css | 287 ++-- packages/ui/src/components/card.css | 52 +- packages/ui/src/components/checkbox.css | 227 ++- packages/ui/src/components/code.css | 4 +- packages/ui/src/components/collapsible.css | 170 +-- packages/ui/src/components/cycle-label.css | 85 +- packages/ui/src/components/dialog.css | 306 ++-- packages/ui/src/components/diff-changes.css | 66 +- packages/ui/src/components/diff.css | 60 +- packages/ui/src/components/dropdown-menu.css | 214 ++- packages/ui/src/components/file-icon.css | 6 +- packages/ui/src/components/hover-card.css | 90 +- packages/ui/src/components/icon-button.css | 246 ++-- packages/ui/src/components/icon.css | 54 +- packages/ui/src/components/icon.tsx | 5 +- packages/ui/src/components/image-preview.css | 110 +- packages/ui/src/components/inline-input.css | 28 +- packages/ui/src/components/keybind.css | 30 +- packages/ui/src/components/line-comment.css | 140 +- packages/ui/src/components/list.css | 568 ++++---- packages/ui/src/components/list.tsx | 8 +- packages/ui/src/components/logo.css | 4 +- packages/ui/src/components/markdown.css | 354 +++-- packages/ui/src/components/message-nav.css | 165 ++- packages/ui/src/components/message-part.css | 1292 ++++++++--------- packages/ui/src/components/morph-chevron.css | 16 +- packages/ui/src/components/popover.css | 200 ++- .../ui/src/components/progress-circle.css | 14 +- packages/ui/src/components/provider-icon.css | 6 +- packages/ui/src/components/radio-group.css | 279 ++-- packages/ui/src/components/reasoning-icon.css | 12 +- packages/ui/src/components/reasoning-icon.tsx | 18 +- packages/ui/src/components/resize-handle.css | 100 +- packages/ui/src/components/scroll-fade.css | 182 +-- packages/ui/src/components/scroll-reveal.tsx | 2 +- packages/ui/src/components/select.css | 286 ++-- packages/ui/src/components/session-review.css | 365 +++-- packages/ui/src/components/session-turn.css | 1139 +++++++-------- packages/ui/src/components/session-turn.tsx | 2 +- packages/ui/src/components/spinner.css | 8 +- .../components/sticky-accordion-header.css | 24 +- packages/ui/src/components/switch.css | 223 ++- packages/ui/src/components/tabs.css | 904 ++++++------ packages/ui/src/components/tag.css | 66 +- packages/ui/src/components/text-field.css | 218 +-- packages/ui/src/components/toast.css | 330 ++--- packages/ui/src/components/tooltip.css | 116 +- packages/ui/src/components/typewriter.css | 18 +- packages/ui/src/context/dialog.tsx | 16 +- packages/ui/src/styles/utilities.css | 231 ++- 55 files changed, 4865 insertions(+), 4953 deletions(-) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 313f0402d0..6e614eb1d7 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -925,7 +925,7 @@ export const PromptInput: Component = (props) => { .abort({ sessionID, }) - .catch(() => { }) + .catch(() => {}) } const addToHistory = (prompt: Prompt, mode: "normal" | "shell") => { @@ -1351,18 +1351,18 @@ export const PromptInput: Component = (props) => { const contextParts: Array< | { - id: string - type: "text" - text: string - synthetic?: boolean - } + id: string + type: "text" + text: string + synthetic?: boolean + } | { - id: string - type: "file" - mime: string - url: string - filename?: string - } + id: string + type: "file" + mime: string + url: string + filename?: string + } > = [] const commentNote = (path: string, selection: FileSelection | undefined, comment: string) => { diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx index 3010cbc40f..054fa6ef4a 100644 --- a/packages/app/src/components/settings-general.tsx +++ b/packages/app/src/components/settings-general.tsx @@ -61,24 +61,24 @@ export const SettingsGeneral: Component = () => { const actions = platform.update && platform.restart ? [ - { - label: language.t("toast.update.action.installRestart"), - onClick: async () => { - await platform.update!() - await platform.restart!() + { + label: language.t("toast.update.action.installRestart"), + onClick: async () => { + await platform.update!() + await platform.restart!() + }, }, - }, - { - label: language.t("toast.update.action.notYet"), - onClick: "dismiss" as const, - }, - ] + { + label: language.t("toast.update.action.notYet"), + onClick: "dismiss" as const, + }, + ] : [ - { - label: language.t("toast.update.action.notYet"), - onClick: "dismiss" as const, - }, - ] + { + label: language.t("toast.update.action.notYet"), + onClick: "dismiss" as const, + }, + ] showToast({ persistent: true, diff --git a/packages/ui/src/components/accordion.css b/packages/ui/src/components/accordion.css index 441bd0542f..b310eeedb6 100644 --- a/packages/ui/src/components/accordion.css +++ b/packages/ui/src/components/accordion.css @@ -1,107 +1,107 @@ [data-component="accordion"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - align-self: stretch; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + align-self: stretch; - [data-slot="accordion-item"] { - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - overflow: clip; + [data-slot="accordion-item"] { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + overflow: clip; - [data-slot="accordion-header"] { - width: 100%; - display: flex; - align-items: center; - margin: 0; - padding: 0; + [data-slot="accordion-header"] { + width: 100%; + display: flex; + align-items: center; + margin: 0; + padding: 0; - [data-slot="accordion-trigger"] { - width: 100%; - display: flex; - height: 32px; - padding: 8px 12px; - justify-content: space-between; - align-items: center; - align-self: stretch; - cursor: default; - user-select: none; + [data-slot="accordion-trigger"] { + width: 100%; + display: flex; + height: 32px; + padding: 8px 12px; + justify-content: space-between; + align-items: center; + align-self: stretch; + cursor: default; + user-select: none; - background-color: var(--surface-base); - border: 1px solid var(--border-weak-base); - border-radius: var(--radius-md); - overflow: clip; - color: var(--text-strong); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + background-color: var(--surface-base); + border: 1px solid var(--border-weak-base); + border-radius: var(--radius-md); + overflow: clip; + color: var(--text-strong); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &:hover { - background-color: var(--surface-base); - } - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } - } - } + &:hover { + background-color: var(--surface-base); + } + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } + } + } - [data-slot="accordion-arrow"] { - flex-shrink: 0; - width: 16px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - color: var(--text-weak); - } + [data-slot="accordion-arrow"] { + flex-shrink: 0; + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } - [data-slot="accordion-content"] { - display: grid; - grid-template-rows: 0fr; - transition-property: grid-template-rows, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - width: 100%; + [data-slot="accordion-content"] { + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + width: 100%; - > * { - overflow: hidden; - } - } + > * { + overflow: hidden; + } + } - [data-slot="accordion-content"][data-expanded] { - grid-template-rows: 1fr; - } + [data-slot="accordion-content"][data-expanded] { + grid-template-rows: 1fr; + } - [data-slot="accordion-content"][data-closed] { - grid-template-rows: 0fr; - } + [data-slot="accordion-content"][data-closed] { + grid-template-rows: 0fr; + } - &[data-expanded] [data-slot="accordion-trigger"] { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } + &[data-expanded] [data-slot="accordion-trigger"] { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } - &[data-expanded] [data-slot="accordion-content"] { - border: 1px solid var(--border-weak-base); - border-top: none; - border-bottom-left-radius: var(--radius-md); - border-bottom-right-radius: var(--radius-md); - height: auto; - } - } + &[data-expanded] [data-slot="accordion-content"] { + border: 1px solid var(--border-weak-base); + border-top: none; + border-bottom-left-radius: var(--radius-md); + border-bottom-right-radius: var(--radius-md); + height: auto; + } + } } diff --git a/packages/ui/src/components/avatar.css b/packages/ui/src/components/avatar.css index dff6bb7b89..5872160771 100644 --- a/packages/ui/src/components/avatar.css +++ b/packages/ui/src/components/avatar.css @@ -1,49 +1,49 @@ [data-component="avatar"] { - --avatar-bg: var(--color-surface-info-base); - --avatar-fg: var(--color-text-base); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - border-radius: var(--radius-sm); - border: 1px solid var(--color-border-weak-base); - font-family: var(--font-mono); - font-weight: 500; - text-transform: uppercase; - background-color: var(--avatar-bg); - color: var(--avatar-fg); + --avatar-bg: var(--color-surface-info-base); + --avatar-fg: var(--color-text-base); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + border-radius: var(--radius-sm); + border: 1px solid var(--color-border-weak-base); + font-family: var(--font-mono); + font-weight: 500; + text-transform: uppercase; + background-color: var(--avatar-bg); + color: var(--avatar-fg); } [data-component="avatar"][data-has-image] { - background-color: transparent; - border: none; + background-color: transparent; + border: none; } [data-component="avatar"][data-size="small"] { - width: 1.25rem; - height: 1.25rem; - font-size: 0.75rem; - line-height: 1; + width: 1.25rem; + height: 1.25rem; + font-size: 0.75rem; + line-height: 1; } [data-component="avatar"][data-size="normal"] { - width: 1.5rem; - height: 1.5rem; - font-size: 1.125rem; - line-height: 1.5rem; + width: 1.5rem; + height: 1.5rem; + font-size: 1.125rem; + line-height: 1.5rem; } [data-component="avatar"][data-size="large"] { - width: 2rem; - height: 2rem; - font-size: 1.25rem; - line-height: 2rem; + width: 2rem; + height: 2rem; + font-size: 1.25rem; + line-height: 2rem; } [data-component="avatar"] [data-slot="avatar-image"] { - width: 100%; - height: 100%; - display: block; - object-fit: cover; - border-radius: inherit; + width: 100%; + height: 100%; + display: block; + object-fit: cover; + border-radius: inherit; } diff --git a/packages/ui/src/components/basic-tool.css b/packages/ui/src/components/basic-tool.css index cc58cfa730..2c6bfeb672 100644 --- a/packages/ui/src/components/basic-tool.css +++ b/packages/ui/src/components/basic-tool.css @@ -1,97 +1,97 @@ [data-component="tool-trigger"] { - content-visibility: auto; - width: 100%; - display: flex; - align-items: center; - align-self: stretch; - gap: 20px; - justify-content: space-between; + content-visibility: auto; + width: 100%; + display: flex; + align-items: center; + align-self: stretch; + gap: 20px; + justify-content: space-between; - [data-slot="basic-tool-tool-trigger-content"] { - width: 100%; - display: flex; - align-items: center; - align-self: stretch; - gap: 20px; - } + [data-slot="basic-tool-tool-trigger-content"] { + width: 100%; + display: flex; + align-items: center; + align-self: stretch; + gap: 20px; + } - [data-slot="icon-svg"] { - flex-shrink: 0; - } + [data-slot="icon-svg"] { + flex-shrink: 0; + } - [data-slot="basic-tool-tool-info"] { - flex-grow: 1; - min-width: 0; - } + [data-slot="basic-tool-tool-info"] { + flex-grow: 1; + min-width: 0; + } - [data-slot="basic-tool-tool-info-structured"] { - width: 100%; - display: flex; - align-items: center; - gap: 8px; - justify-content: space-between; - } + [data-slot="basic-tool-tool-info-structured"] { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + justify-content: space-between; + } - [data-slot="basic-tool-tool-info-main"] { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - overflow: hidden; - } + [data-slot="basic-tool-tool-info-main"] { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + overflow: hidden; + } - [data-slot="basic-tool-tool-title"] { - flex-shrink: 0; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); + [data-slot="basic-tool-tool-title"] { + flex-shrink: 0; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); - &.capitalize { - text-transform: capitalize; - } - } + &.capitalize { + text-transform: capitalize; + } + } - [data-slot="basic-tool-tool-subtitle"] { - flex-shrink: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); + [data-slot="basic-tool-tool-subtitle"] { + flex-shrink: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); - &.clickable { - cursor: pointer; - text-decoration: underline; - transition: color 0.15s ease; + &.clickable { + cursor: pointer; + text-decoration: underline; + transition: color 0.15s ease; - &:hover { - color: var(--text-base); - } - } - } + &:hover { + color: var(--text-base); + } + } + } - [data-slot="basic-tool-tool-arg"] { - flex-shrink: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - } + [data-slot="basic-tool-tool-arg"] { + flex-shrink: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } } diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index 56258bd84e..02a7ade712 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -1,168 +1,167 @@ [data-component="button"] { - display: inline-flex; - align-items: center; - justify-content: center; - border-style: solid; - border-width: 1px; - border-radius: var(--radius-md); - text-decoration: none; - user-select: none; - cursor: default; - padding: 4px 8px; - white-space: nowrap; - transition-property: - background-color, border-color, color, box-shadow, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - outline: none; - line-height: 20px; + display: inline-flex; + align-items: center; + justify-content: center; + border-style: solid; + border-width: 1px; + border-radius: var(--radius-md); + text-decoration: none; + user-select: none; + cursor: default; + padding: 4px 8px; + white-space: nowrap; + transition-property: background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + outline: none; + line-height: 20px; - &[data-variant="primary"] { - background-color: var(--button-primary-base); - border-color: var(--border-weak-base); - color: var(--icon-invert-base); + &[data-variant="primary"] { + background-color: var(--button-primary-base); + border-color: var(--border-weak-base); + color: var(--icon-invert-base); - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } - &:hover:not(:disabled) { - background-color: var(--icon-strong-hover); - } - &:focus:not(:disabled) { - background-color: var(--icon-strong-focus); - } - &:active:not(:disabled) { - background-color: var(--icon-strong-active); - } - &:disabled { - background-color: var(--icon-strong-disabled); + &:hover:not(:disabled) { + background-color: var(--icon-strong-hover); + } + &:focus:not(:disabled) { + background-color: var(--icon-strong-focus); + } + &:active:not(:disabled) { + background-color: var(--icon-strong-active); + } + &:disabled { + background-color: var(--icon-strong-disabled); - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - } - } + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + } + } - &[data-variant="ghost"] { - border-color: transparent; - background-color: transparent; - color: var(--text-strong); + &[data-variant="ghost"] { + border-color: transparent; + background-color: transparent; + color: var(--text-strong); - [data-slot="icon-svg"] { - color: var(--icon-base); - } + [data-slot="icon-svg"] { + color: var(--icon-base); + } - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - &:disabled { - color: var(--text-weak); - cursor: not-allowed; + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:focus-visible:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + &:disabled { + color: var(--text-weak); + cursor: not-allowed; - [data-slot="icon-svg"] { - color: var(--icon-disabled); - } - } - &[data-selected="true"]:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &[data-active="true"] { - background-color: var(--surface-raised-base-active); - } - } + [data-slot="icon-svg"] { + color: var(--icon-disabled); + } + } + &[data-selected="true"]:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &[data-active="true"] { + background-color: var(--surface-raised-base-active); + } + } - &[data-variant="secondary"] { - border: transparent; - background-color: var(--button-secondary-base); - color: var(--text-strong); - box-shadow: var(--shadow-xs-border); + &[data-variant="secondary"] { + border: transparent; + background-color: var(--button-secondary-base); + color: var(--text-strong); + box-shadow: var(--shadow-xs-border); - &:hover:not(:disabled) { - background-color: var(--button-secondary-hover); - } - &:focus:not(:disabled) { - background-color: var(--button-secondary-base); - } - &:focus-visible:not(:active) { - background-color: var(--button-secondary-base); - box-shadow: var(--shadow-xs-border-focus); - } - &:focus-visible:active { - box-shadow: none; - } - &:active:not(:disabled) { - background-color: var(--button-secondary-base); - scale: 0.99; - } - &:disabled { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - color: var(--text-weak); - cursor: not-allowed; - } + &:hover:not(:disabled) { + background-color: var(--button-secondary-hover); + } + &:focus:not(:disabled) { + background-color: var(--button-secondary-base); + } + &:focus-visible:not(:active) { + background-color: var(--button-secondary-base); + box-shadow: var(--shadow-xs-border-focus); + } + &:focus-visible:active { + box-shadow: none; + } + &:active:not(:disabled) { + background-color: var(--button-secondary-base); + scale: 0.99; + } + &:disabled { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + color: var(--text-weak); + cursor: not-allowed; + } - [data-slot="icon-svg"] { - color: var(--icon-strong-base); - } - } + [data-slot="icon-svg"] { + color: var(--icon-strong-base); + } + } - &[data-size="small"] { - padding: 2px 8px; - &[data-icon] { - padding: 2px 12px 2px 4px; - } + &[data-size="small"] { + padding: 2px 8px; + &[data-icon] { + padding: 2px 12px 2px 4px; + } - gap: 4px; + gap: 4px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } - &[data-size="normal"] { - padding: 4px 6px; - &[data-icon] { - padding: 4px 12px 4px 4px; - } + &[data-size="normal"] { + padding: 4px 6px; + &[data-icon] { + padding: 4px 12px 4px 4px; + } - gap: 6px; + gap: 6px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } - &[data-size="large"] { - padding: 6px 12px; + &[data-size="large"] { + padding: 6px 12px; - &[data-icon] { - padding: 6px 12px 6px 8px; - } + &[data-icon] { + padding: 6px 12px 6px 8px; + } - gap: 4px; + gap: 4px; - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } - &:focus { - outline: none; - } + &:focus { + outline: none; + } } diff --git a/packages/ui/src/components/card.css b/packages/ui/src/components/card.css index 8ac8390421..809fbdacde 100644 --- a/packages/ui/src/components/card.css +++ b/packages/ui/src/components/card.css @@ -1,31 +1,31 @@ [data-component="card"] { - width: 100%; - display: flex; - flex-direction: column; - background-color: var(--surface-inset-base); - border: 1px solid var(--border-weaker-base); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - border-radius: var(--radius-md); - padding: 6px 12px; - overflow: clip; + width: 100%; + display: flex; + flex-direction: column; + background-color: var(--surface-inset-base); + border: 1px solid var(--border-weaker-base); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + border-radius: var(--radius-md); + padding: 6px 12px; + overflow: clip; - &[data-variant="error"] { - background-color: var(--surface-critical-weak); - border: 1px solid var(--border-critical-base); - color: rgba(218, 51, 25, 0.6); + &[data-variant="error"] { + background-color: var(--surface-critical-weak); + border: 1px solid var(--border-critical-base); + color: rgba(218, 51, 25, 0.6); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &[data-component="icon"] { - color: var(--icon-critical-active); - } - } + &[data-component="icon"] { + color: var(--icon-critical-active); + } + } } diff --git a/packages/ui/src/components/checkbox.css b/packages/ui/src/components/checkbox.css index 44cb1d8ae6..cad0dd2dd6 100644 --- a/packages/ui/src/components/checkbox.css +++ b/packages/ui/src/components/checkbox.css @@ -1,136 +1,133 @@ [data-component="checkbox"] { - display: flex; - align-items: center; - gap: 12px; - cursor: default; + display: flex; + align-items: center; + gap: 12px; + cursor: default; - [data-slot="checkbox-checkbox-control"] { - transition-property: border-color, background-color, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + [data-slot="checkbox-checkbox-control"] { + transition-property: border-color, background-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="checkbox-checkbox-indicator"] { - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + [data-slot="checkbox-checkbox-indicator"] { + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="checkbox-checkbox-input"] { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } + [data-slot="checkbox-checkbox-input"] { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } - [data-slot="checkbox-checkbox-control"] { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - padding: 2px; - aspect-ratio: 1; - flex-shrink: 0; - border-radius: var(--radius-sm); - border: 1px solid var(--border-weak-base); - /* background-color: var(--surface-weak); */ - } + [data-slot="checkbox-checkbox-control"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + padding: 2px; + aspect-ratio: 1; + flex-shrink: 0; + border-radius: var(--radius-sm); + border: 1px solid var(--border-weak-base); + /* background-color: var(--surface-weak); */ + } - [data-slot="checkbox-checkbox-indicator"] { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - color: var(--icon-base); - opacity: 0; - } + [data-slot="checkbox-checkbox-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + color: var(--icon-base); + opacity: 0; + } - /* [data-slot="checkbox-checkbox-content"] { */ - /* } */ + /* [data-slot="checkbox-checkbox-content"] { */ + /* } */ - [data-slot="checkbox-checkbox-label"] { - user-select: none; - color: var(--text-base); + [data-slot="checkbox-checkbox-label"] { + user-select: none; + color: var(--text-base); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="checkbox-checkbox-description"] { - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="checkbox-checkbox-description"] { + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="checkbox-checkbox-error"] { - color: var(--text-error); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="checkbox-checkbox-error"] { + color: var(--text-error); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - &:hover:not([data-disabled], [data-readonly]) - [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &:hover:not([data-disabled], [data-readonly]) [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &:focus-within:not([data-readonly]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-focus); - box-shadow: 0 0 0 2px var(--surface-focus); - } + &:focus-within:not([data-readonly]) [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-focus); + box-shadow: 0 0 0 2px var(--surface-focus); + } - &[data-checked] [data-slot="checkbox-checkbox-control"], - &[data-indeterminate] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-base); - background-color: var(--surface-weak); - } + &[data-checked] [data-slot="checkbox-checkbox-control"], + &[data-indeterminate] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-base); + background-color: var(--surface-weak); + } - &[data-checked]:hover:not([data-disabled], [data-readonly]) - [data-slot="checkbox-checkbox-control"], - &[data-indeterminate]:hover:not([data-disabled]) - [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &[data-checked]:hover:not([data-disabled], [data-readonly]) [data-slot="checkbox-checkbox-control"], + &[data-indeterminate]:hover:not([data-disabled]) [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &[data-checked] [data-slot="checkbox-checkbox-indicator"], - &[data-indeterminate] [data-slot="checkbox-checkbox-indicator"] { - opacity: 1; - } + &[data-checked] [data-slot="checkbox-checkbox-indicator"], + &[data-indeterminate] [data-slot="checkbox-checkbox-indicator"] { + opacity: 1; + } - &[data-disabled] { - cursor: not-allowed; - } + &[data-disabled] { + cursor: not-allowed; + } - &[data-disabled] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - } + &[data-disabled] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + } - &[data-invalid] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-error); - } + &[data-invalid] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-error); + } - &[data-readonly] { - cursor: default; - pointer-events: none; - } + &[data-readonly] { + cursor: default; + pointer-events: none; + } } diff --git a/packages/ui/src/components/code.css b/packages/ui/src/components/code.css index 553219bb86..671b40512d 100644 --- a/packages/ui/src/components/code.css +++ b/packages/ui/src/components/code.css @@ -1,4 +1,4 @@ [data-component="code"] { - content-visibility: auto; - overflow: hidden; + content-visibility: auto; + overflow: hidden; } diff --git a/packages/ui/src/components/collapsible.css b/packages/ui/src/components/collapsible.css index 312eec84a8..cc62b2b87c 100644 --- a/packages/ui/src/components/collapsible.css +++ b/packages/ui/src/components/collapsible.css @@ -1,99 +1,99 @@ [data-component="collapsible"] { - width: 100%; - display: flex; - flex-direction: column; - background-color: var(--surface-inset-base); - border: 1px solid var(--border-weaker-base); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - border-radius: var(--radius-md); - overflow: clip; + width: 100%; + display: flex; + flex-direction: column; + background-color: var(--surface-inset-base); + border: 1px solid var(--border-weaker-base); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + border-radius: var(--radius-md); + overflow: clip; - [data-slot="collapsible-trigger"] { - width: 100%; - display: flex; - height: 32px; - padding: 6px 8px 6px 12px; - align-items: center; - align-self: stretch; - cursor: default; - user-select: none; - color: var(--text-base); + [data-slot="collapsible-trigger"] { + width: 100%; + display: flex; + height: 32px; + padding: 6px 8px 6px 12px; + align-items: center; + align-self: stretch; + cursor: default; + user-select: none; + color: var(--text-base); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - /* &:hover { */ - /* background-color: var(--surface-base); */ - /* } */ - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } + /* &:hover { */ + /* background-color: var(--surface-base); */ + /* } */ + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } - [data-slot="collapsible-arrow"] { - flex-shrink: 0; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - color: var(--text-weak); - } - } + [data-slot="collapsible-arrow"] { + flex-shrink: 0; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } + } - [data-slot="collapsible-content"] { - display: grid; - grid-template-rows: 0fr; - transition-property: grid-template-rows, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + [data-slot="collapsible-content"] { + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - > * { - overflow: hidden; - } + > * { + overflow: hidden; + } - &[data-expanded] { - grid-template-rows: 1fr; - } + &[data-expanded] { + grid-template-rows: 1fr; + } - &[data-closed] { - grid-template-rows: 0fr; - } - } + &[data-closed] { + grid-template-rows: 0fr; + } + } - &[data-variant="ghost"] { - background-color: transparent; - border: none; + &[data-variant="ghost"] { + background-color: transparent; + border: none; - > [data-slot="collapsible-trigger"] { - background-color: transparent; - border: none; - padding: 0; + > [data-slot="collapsible-trigger"] { + background-color: transparent; + border: none; + padding: 0; - /* &:hover { */ - /* color: var(--text-strong); */ - /* } */ - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } - } - } + /* &:hover { */ + /* color: var(--text-strong); */ + /* } */ + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } + } + } - &[data-variant="ghost"][data-scope="filetree"] { - > [data-slot="collapsible-trigger"] { - height: 24px; - } - } + &[data-variant="ghost"][data-scope="filetree"] { + > [data-slot="collapsible-trigger"] { + height: 24px; + } + } } diff --git a/packages/ui/src/components/cycle-label.css b/packages/ui/src/components/cycle-label.css index 46a6408f01..e3b5256d4f 100644 --- a/packages/ui/src/components/cycle-label.css +++ b/packages/ui/src/components/cycle-label.css @@ -1,52 +1,51 @@ .cycle-label { - --c-dur: 200ms; - --c-stag: 30ms; - --c-ease: cubic-bezier(0.25, 0, 0.5, 1); - --c-opacity-start: 0; - --c-opacity-end: 1; - --c-blur-start: 0px; - --c-blur-end: 0px; - --c-skew: 10deg; + --c-dur: 200ms; + --c-stag: 30ms; + --c-ease: cubic-bezier(0.25, 0, 0.5, 1); + --c-opacity-start: 0; + --c-opacity-end: 1; + --c-blur-start: 0px; + --c-blur-end: 0px; + --c-skew: 10deg; - display: inline-flex; - position: relative; + display: inline-flex; + position: relative; - transform-style: preserve-3d; - perspective: 500px; - transition: width 200ms var(--c-ease); - will-change: width; - overflow: hidden; + transform-style: preserve-3d; + perspective: 500px; + transition: width 200ms var(--c-ease); + will-change: width; + overflow: hidden; - .cycle-char { - display: inline-block; - transform-style: preserve-3d; - min-width: 0.25em; - backface-visibility: hidden; + .cycle-char { + display: inline-block; + transform-style: preserve-3d; + min-width: 0.25em; + backface-visibility: hidden; - transition: - transform var(--c-dur) var(--c-ease), - opacity var(--c-dur) var(--c-ease), - filter var(--c-dur) var(--c-ease); - transition-delay: calc(var(--i, 0) * var(--c-stag)); + transition: + transform var(--c-dur) var(--c-ease), + opacity var(--c-dur) var(--c-ease), + filter var(--c-dur) var(--c-ease); + transition-delay: calc(var(--i, 0) * var(--c-stag)); - &.enter { - opacity: var(--c-opacity-end); - filter: blur(var(--c-blur-end)); - transform: translateY(0) rotateX(0) skewX(0); - } + &.enter { + opacity: var(--c-opacity-end); + filter: blur(var(--c-blur-end)); + transform: translateY(0) rotateX(0) skewX(0); + } - &.exit { - opacity: var(--c-opacity-start); - filter: blur(var(--c-blur-start)); - transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); - } + &.exit { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); + } - &.pre { - opacity: var(--c-opacity-start); - filter: blur(var(--c-blur-start)); - transition: none; - transform: translateY(-50%) rotateX(-90deg) - skewX(calc(var(--c-skew) * -1)); - } - } + &.pre { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transition: none; + transform: translateY(-50%) rotateX(-90deg) skewX(calc(var(--c-skew) * -1)); + } + } } diff --git a/packages/ui/src/components/dialog.css b/packages/ui/src/components/dialog.css index 5ff9ec595b..b788945dce 100644 --- a/packages/ui/src/components/dialog.css +++ b/packages/ui/src/components/dialog.css @@ -1,196 +1,192 @@ /* [data-component="dialog-trigger"] { } */ [data-component="dialog-overlay"] { - position: fixed; - inset: 0; - z-index: 50; - background-color: hsl(from var(--background-base) h s l / 0.2); + position: fixed; + inset: 0; + z-index: 50; + background-color: hsl(from var(--background-base) h s l / 0.2); - animation: overlayHide var(--transition-duration) var(--transition-easing) - forwards; + animation: overlayHide var(--transition-duration) var(--transition-easing) forwards; - &[data-expanded] { - animation: overlayShow var(--transition-duration) var(--transition-easing) - forwards; - } + &[data-expanded] { + animation: overlayShow var(--transition-duration) var(--transition-easing) forwards; + } - @starting-style { - animation: none; - } + @starting-style { + animation: none; + } } [data-component="dialog"] { - position: fixed; - inset: 0; - z-index: 50; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; + position: fixed; + inset: 0; + z-index: 50; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; - [data-slot="dialog-container"] { - position: relative; - z-index: 50; - width: min(calc(100vw - 16px), 640px); - height: min(calc(100vh - 16px), 512px); - display: flex; - flex-direction: column; - align-items: center; - justify-items: start; + [data-slot="dialog-container"] { + position: relative; + z-index: 50; + width: min(calc(100vw - 16px), 640px); + height: min(calc(100vh - 16px), 512px); + display: flex; + flex-direction: column; + align-items: center; + justify-items: start; - [data-slot="dialog-content"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - width: 100%; - max-height: 100%; - min-height: 280px; - pointer-events: auto; + [data-slot="dialog-content"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + width: 100%; + max-height: 100%; + min-height: 280px; + pointer-events: auto; - /* padding: 8px; */ - /* padding: 8px 8px 0 8px; */ - border-radius: var(--radius-xl); - background: var(--surface-raised-stronger-non-alpha); - background-clip: padding-box; - box-shadow: var(--shadow-lg-border-base); + /* padding: 8px; */ + /* padding: 8px 8px 0 8px; */ + border-radius: var(--radius-xl); + background: var(--surface-raised-stronger-non-alpha); + background-clip: padding-box; + box-shadow: var(--shadow-lg-border-base); - animation: contentHide var(--transition-duration) var(--transition-easing) - forwards; + animation: contentHide var(--transition-duration) var(--transition-easing) forwards; - &[data-expanded] { - animation: contentShow var(--transition-duration) - var(--transition-easing) forwards; - } + &[data-expanded] { + animation: contentShow var(--transition-duration) var(--transition-easing) forwards; + } - @starting-style { - animation: none; - } + @starting-style { + animation: none; + } - [data-slot="dialog-header"] { - display: flex; - padding: 20px; - justify-content: space-between; - align-items: center; - flex-shrink: 0; - align-self: stretch; + [data-slot="dialog-header"] { + display: flex; + padding: 20px; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; - [data-slot="dialog-title"] { - color: var(--text-strong); + [data-slot="dialog-title"] { + color: var(--text-strong); - /* text-16-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 150% */ - letter-spacing: var(--letter-spacing-tight); - } - /* [data-slot="dialog-close-button"] {} */ - } + /* text-16-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 150% */ + letter-spacing: var(--letter-spacing-tight); + } + /* [data-slot="dialog-close-button"] {} */ + } - [data-slot="dialog-description"] { - display: flex; - padding: 16px; - padding-left: 24px; - padding-top: 0; - margin-top: -8px; - justify-content: space-between; - align-items: center; - flex-shrink: 0; - align-self: stretch; + [data-slot="dialog-description"] { + display: flex; + padding: 16px; + padding-left: 24px; + padding-top: 0; + margin-top: -8px; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; - color: var(--text-base); + color: var(--text-base); - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="dialog-body"] { - width: 100%; - position: relative; - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; + [data-slot="dialog-body"] { + width: 100%; + position: relative; + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; - &:focus-visible { - outline: none; - } - } - &:focus-visible { - outline: none; - } - } - } + &:focus-visible { + outline: none; + } + } + &:focus-visible { + outline: none; + } + } + } - &[data-fit] { - [data-slot="dialog-container"] { - height: auto; + &[data-fit] { + [data-slot="dialog-container"] { + height: auto; - [data-slot="dialog-content"] { - min-height: 0; - } - } - } + [data-slot="dialog-content"] { + min-height: 0; + } + } + } - &[data-size="large"] [data-slot="dialog-container"] { - width: min(calc(100vw - 32px), 800px); - height: min(calc(100vh - 32px), 600px); - } + &[data-size="large"] [data-slot="dialog-container"] { + width: min(calc(100vw - 32px), 800px); + height: min(calc(100vh - 32px), 600px); + } - &[data-size="x-large"] [data-slot="dialog-container"] { - width: min(calc(100vw - 32px), 960px); - height: min(calc(100vh - 32px), 600px); - } + &[data-size="x-large"] [data-slot="dialog-container"] { + width: min(calc(100vw - 32px), 960px); + height: min(calc(100vh - 32px), 600px); + } } [data-component="dialog"][data-transition] [data-slot="dialog-content"] { - animation: contentHide 100ms ease-in forwards; + animation: contentHide 100ms ease-in forwards; - &[data-expanded] { - animation: contentShow 150ms ease-out; - } + &[data-expanded] { + animation: contentShow 150ms ease-out; + } } @keyframes overlayShow { - from { - opacity: 0; - } - to { - opacity: 1; - } + from { + opacity: 0; + } + to { + opacity: 1; + } } @keyframes overlayHide { - from { - opacity: 1; - } - to { - opacity: 0; - } + from { + opacity: 1; + } + to { + opacity: 0; + } } @keyframes contentShow { - from { - opacity: 0; - transform: translateY(2.5%) scale(0.975); - } - to { - opacity: 1; - transform: scale(1); - } + from { + opacity: 0; + transform: translateY(2.5%) scale(0.975); + } + to { + opacity: 1; + transform: scale(1); + } } @keyframes contentHide { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: translateY(-2.5%) scale(0.975); - } + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: translateY(-2.5%) scale(0.975); + } } diff --git a/packages/ui/src/components/diff-changes.css b/packages/ui/src/components/diff-changes.css index 6e0c3d01ba..be3cca885d 100644 --- a/packages/ui/src/components/diff-changes.css +++ b/packages/ui/src/components/diff-changes.css @@ -1,41 +1,41 @@ [data-component="diff-changes"] { - display: flex; - gap: 8px; - justify-content: flex-end; - align-items: center; + display: flex; + gap: 8px; + justify-content: flex-end; + align-items: center; - [data-slot="diff-changes-additions"] { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - text-align: right; - color: var(--text-diff-add-base); - } + [data-slot="diff-changes-additions"] { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + text-align: right; + color: var(--text-diff-add-base); + } - [data-slot="diff-changes-deletions"] { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - text-align: right; - color: var(--text-diff-delete-base); - } + [data-slot="diff-changes-deletions"] { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + text-align: right; + color: var(--text-diff-delete-base); + } } [data-component="diff-changes"][data-variant="bars"] { - width: 18px; - flex-shrink: 0; + width: 18px; + flex-shrink: 0; - svg { - display: block; - width: 100%; - height: auto; - } + svg { + display: block; + width: 100%; + height: auto; + } } diff --git a/packages/ui/src/components/diff.css b/packages/ui/src/components/diff.css index 92c4450126..1d94e417ae 100644 --- a/packages/ui/src/components/diff.css +++ b/packages/ui/src/components/diff.css @@ -1,35 +1,35 @@ [data-component="diff"] { - content-visibility: auto; + content-visibility: auto; - [data-slot="diff-hunk-separator-line-number"] { - position: sticky; - left: 0; - background-color: var(--surface-diff-hidden-strong); - z-index: 2; - display: flex; - align-items: center; - justify-content: center; + [data-slot="diff-hunk-separator-line-number"] { + position: sticky; + left: 0; + background-color: var(--surface-diff-hidden-strong); + z-index: 2; + display: flex; + align-items: center; + justify-content: center; - [data-slot="diff-hunk-separator-line-number-icon"] { - aspect-ratio: 1; - width: 24px; - height: 24px; - color: var(--icon-strong-base); - } - } - [data-slot="diff-hunk-separator-content"] { - position: sticky; - background-color: var(--surface-diff-hidden-base); - color: var(--text-base); - width: var(--diffs-column-content-width); - left: var(--diffs-column-number-width); - padding-left: 8px; - user-select: none; - cursor: default; - text-align: left; + [data-slot="diff-hunk-separator-line-number-icon"] { + aspect-ratio: 1; + width: 24px; + height: 24px; + color: var(--icon-strong-base); + } + } + [data-slot="diff-hunk-separator-content"] { + position: sticky; + background-color: var(--surface-diff-hidden-base); + color: var(--text-base); + width: var(--diffs-column-content-width); + left: var(--diffs-column-number-width); + padding-left: 8px; + user-select: none; + cursor: default; + text-align: left; - [data-slot="diff-hunk-separator-content-span"] { - mix-blend-mode: var(--text-mix-blend-mode); - } - } + [data-slot="diff-hunk-separator-content-span"] { + mix-blend-mode: var(--text-mix-blend-mode); + } + } } diff --git a/packages/ui/src/components/dropdown-menu.css b/packages/ui/src/components/dropdown-menu.css index cfbfd1cf0e..18266ac1a1 100644 --- a/packages/ui/src/components/dropdown-menu.css +++ b/packages/ui/src/components/dropdown-menu.css @@ -1,136 +1,134 @@ [data-component="dropdown-menu-content"], [data-component="dropdown-menu-sub-content"] { - min-width: 8rem; - overflow: hidden; - border: none; - border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); - background-clip: padding-box; - background-color: var(--surface-raised-stronger-non-alpha); - padding: 4px; - z-index: 100; - transform-origin: var(--kb-menu-content-transform-origin); + min-width: 8rem; + overflow: hidden; + border: none; + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + background-clip: padding-box; + background-color: var(--surface-raised-stronger-non-alpha); + padding: 4px; + z-index: 100; + transform-origin: var(--kb-menu-content-transform-origin); - &:focus-within, - &:focus { - outline: none; - } + &:focus-within, + &:focus { + outline: none; + } - animation: dropdownMenuContentHide var(--transition-duration) - var(--transition-easing) forwards; + animation: dropdownMenuContentHide var(--transition-duration) var(--transition-easing) forwards; - @starting-style { - animation: none; - } + @starting-style { + animation: none; + } - &[data-expanded] { - pointer-events: auto; - animation: dropdownMenuContentShow var(--transition-duration) - var(--transition-easing) forwards; - } + &[data-expanded] { + pointer-events: auto; + animation: dropdownMenuContentShow var(--transition-duration) var(--transition-easing) forwards; + } } [data-component="dropdown-menu-content"], [data-component="dropdown-menu-sub-content"] { - [data-slot="dropdown-menu-item"], - [data-slot="dropdown-menu-checkbox-item"], - [data-slot="dropdown-menu-radio-item"], - [data-slot="dropdown-menu-sub-trigger"] { - position: relative; - display: flex; - align-items: center; - gap: 8px; - padding: 4px 8px; - border-radius: var(--radius-sm); - cursor: default; - outline: none; + [data-slot="dropdown-menu-item"], + [data-slot="dropdown-menu-checkbox-item"], + [data-slot="dropdown-menu-radio-item"], + [data-slot="dropdown-menu-sub-trigger"] { + position: relative; + display: flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + border-radius: var(--radius-sm); + cursor: default; + outline: none; - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-strong); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); - transition-property: background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - user-select: none; + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; - &:hover { - background-color: var(--surface-raised-base-hover); - } + &:hover { + background-color: var(--surface-raised-base-hover); + } - &[data-disabled] { - color: var(--text-weak); - pointer-events: none; - } - } + &[data-disabled] { + color: var(--text-weak); + pointer-events: none; + } + } - [data-slot="dropdown-menu-sub-trigger"] { - &[data-expanded] { - background: var(--surface-raised-base-hover); - outline: none; - border: none; - } - } + [data-slot="dropdown-menu-sub-trigger"] { + &[data-expanded] { + background: var(--surface-raised-base-hover); + outline: none; + border: none; + } + } - [data-slot="dropdown-menu-item-indicator"] { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - } + [data-slot="dropdown-menu-item-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + } - [data-slot="dropdown-menu-item-label"] { - flex: 1; - } + [data-slot="dropdown-menu-item-label"] { + flex: 1; + } - [data-slot="dropdown-menu-item-description"] { - font-size: var(--font-size-x-small); - color: var(--text-weak); - } + [data-slot="dropdown-menu-item-description"] { + font-size: var(--font-size-x-small); + color: var(--text-weak); + } - [data-slot="dropdown-menu-separator"] { - height: 1px; - margin: 4px -4px; - border-top-color: var(--border-weak-base); - } + [data-slot="dropdown-menu-separator"] { + height: 1px; + margin: 4px -4px; + border-top-color: var(--border-weak-base); + } - [data-slot="dropdown-menu-group-label"] { - padding: 4px 8px; - font-family: var(--font-family-sans); - font-size: var(--font-size-x-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - } + [data-slot="dropdown-menu-group-label"] { + padding: 4px 8px; + font-family: var(--font-family-sans); + font-size: var(--font-size-x-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } - [data-slot="dropdown-menu-arrow"] { - fill: var(--surface-raised-stronger-non-alpha); - } + [data-slot="dropdown-menu-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } } @keyframes dropdownMenuContentShow { - from { - opacity: 0; - transform: scaleY(0.95); - } - to { - opacity: 1; - transform: scaleY(1); - } + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } @keyframes dropdownMenuContentHide { - from { - opacity: 1; - transform: scaleY(1); - } - to { - opacity: 0; - transform: scaleY(0.95); - } + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } } diff --git a/packages/ui/src/components/file-icon.css b/packages/ui/src/components/file-icon.css index 379247f0c8..e650f6dc72 100644 --- a/packages/ui/src/components/file-icon.css +++ b/packages/ui/src/components/file-icon.css @@ -1,5 +1,5 @@ [data-component="file-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; + flex-shrink: 0; + width: 16px; + height: 16px; } diff --git a/packages/ui/src/components/hover-card.css b/packages/ui/src/components/hover-card.css index 2a588adc60..d23e43946d 100644 --- a/packages/ui/src/components/hover-card.css +++ b/packages/ui/src/components/hover-card.css @@ -1,63 +1,61 @@ [data-slot="hover-card-trigger"] { - display: flex; - width: 100%; - min-width: 0; + display: flex; + width: 100%; + min-width: 0; } [data-component="hover-card-content"] { - z-index: 50; - min-width: 200px; - max-width: 320px; - max-height: calc(100vh - 1rem); - border-radius: 8px; - background-color: var(--surface-raised-stronger-non-alpha); - pointer-events: auto; + z-index: 50; + min-width: 200px; + max-width: 320px; + max-height: calc(100vh - 1rem); + border-radius: 8px; + 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; - box-shadow: var(--shadow-md); + border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); + background-clip: padding-box; + box-shadow: var(--shadow-md); - transform-origin: var(--kb-hovercard-content-transform-origin); + transform-origin: var(--kb-hovercard-content-transform-origin); - &:focus-within { - outline: none; - } + &:focus-within { + outline: none; + } - &[data-closed] { - animation: hover-card-close var(--transition-duration) - var(--transition-easing); - } + &[data-closed] { + animation: hover-card-close var(--transition-duration) var(--transition-easing); + } - &[data-expanded] { - animation: hover-card-open var(--transition-duration) - var(--transition-easing); - } + &[data-expanded] { + animation: hover-card-open var(--transition-duration) var(--transition-easing); + } - [data-slot="hover-card-body"] { - padding: 4px; - max-height: inherit; - overflow: hidden; - } + [data-slot="hover-card-body"] { + padding: 4px; + max-height: inherit; + overflow: hidden; + } } @keyframes hover-card-open { - from { - opacity: 0; - transform: scale(0.96); - } - to { - opacity: 1; - transform: scale(1); - } + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } } @keyframes hover-card-close { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.96); - } + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } } diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index 94aa80f026..f1371bfa9a 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -1,143 +1,143 @@ [data-component="icon-button"] { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-sm); - text-decoration: none; - user-select: none; - aspect-ratio: 1; - flex-shrink: 0; - transition-property: background-color, color, opacity, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm); + text-decoration: none; + user-select: none; + aspect-ratio: 1; + flex-shrink: 0; + transition-property: background-color, color, opacity, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &[data-variant="primary"] { - background-color: var(--icon-strong-base); + &[data-variant="primary"] { + background-color: var(--icon-strong-base); - [data-slot="icon-svg"] { - /* color: var(--icon-weak-base); */ - color: var(--icon-invert-base); + [data-slot="icon-svg"] { + /* color: var(--icon-weak-base); */ + color: var(--icon-invert-base); - /* &:hover:not(:disabled) { */ - /* color: var(--icon-weak-hover); */ - /* } */ - /* &:active:not(:disabled) { */ - /* color: var(--icon-strong-active); */ - /* } */ - } + /* &:hover:not(:disabled) { */ + /* color: var(--icon-weak-hover); */ + /* } */ + /* &:active:not(:disabled) { */ + /* color: var(--icon-strong-active); */ + /* } */ + } - &:hover:not(:disabled) { - background-color: var(--icon-strong-hover); - } - &:focus:not(:disabled) { - background-color: var(--icon-strong-focus); - } - &:active:not(:disabled) { - background-color: var(--icon-strong-active); - } - &:disabled { - background-color: var(--icon-strong-disabled); + &:hover:not(:disabled) { + background-color: var(--icon-strong-hover); + } + &:focus:not(:disabled) { + background-color: var(--icon-strong-focus); + } + &:active:not(:disabled) { + background-color: var(--icon-strong-active); + } + &:disabled { + background-color: var(--icon-strong-disabled); - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - } - } + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + } + } - &[data-variant="secondary"] { - border: transparent; - background-color: var(--button-secondary-base); - color: var(--text-strong); - box-shadow: var(--shadow-xs-border); + &[data-variant="secondary"] { + border: transparent; + background-color: var(--button-secondary-base); + color: var(--text-strong); + box-shadow: var(--shadow-xs-border); - &:hover:not(:disabled) { - background-color: var(--button-secondary-hover); - } - &:focus:not(:disabled) { - background-color: var(--button-secondary-base); - } - &:focus-visible:not(:active) { - background-color: var(--button-secondary-base); - box-shadow: var(--shadow-xs-border-focus); - } - &:focus-visible:active { - box-shadow: none; - } - &:active:not(:disabled) { - background-color: var(--button-secondary-base); - } + &:hover:not(:disabled) { + background-color: var(--button-secondary-hover); + } + &:focus:not(:disabled) { + background-color: var(--button-secondary-base); + } + &:focus-visible:not(:active) { + background-color: var(--button-secondary-base); + box-shadow: var(--shadow-xs-border-focus); + } + &:focus-visible:active { + box-shadow: none; + } + &:active:not(:disabled) { + background-color: var(--button-secondary-base); + } - [data-slot="icon-svg"] { - color: var(--icon-strong-base); - } + [data-slot="icon-svg"] { + color: var(--icon-strong-base); + } - &:disabled { - background-color: var(--icon-strong-disabled); - color: var(--icon-invert-base); - cursor: not-allowed; - } - } + &:disabled { + background-color: var(--icon-strong-disabled); + color: var(--icon-invert-base); + cursor: not-allowed; + } + } - &[data-variant="ghost"] { - background-color: transparent; - /* color: var(--icon-base); */ + &[data-variant="ghost"] { + background-color: transparent; + /* color: var(--icon-base); */ - [data-slot="icon-svg"] { - color: var(--icon-base); - } + [data-slot="icon-svg"] { + color: var(--icon-base); + } - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-hover); */ - /* } */ - } - &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-active); */ - /* } */ - } - &[data-selected]:not(:disabled) { - background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-selected); */ - /* } */ - } - &:disabled { - color: var(--icon-invert-base); - cursor: not-allowed; - } - } + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-hover); */ + /* } */ + } + &:focus-visible:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-active); */ + /* } */ + } + &[data-selected]:not(:disabled) { + background-color: var(--surface-raised-base-active); + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-selected); */ + /* } */ + } + &:disabled { + color: var(--icon-invert-base); + cursor: not-allowed; + } + } - &[data-size="normal"] { - width: 24px; - height: 24px; + &[data-size="normal"] { + width: 24px; + height: 24px; - font-size: var(--font-size-small); - line-height: var(--line-height-large); - gap: calc(var(--spacing) * 0.5); - } + font-size: var(--font-size-small); + line-height: var(--line-height-large); + gap: calc(var(--spacing) * 0.5); + } - &[data-size="large"] { - height: 32px; - /* padding: 0 8px 0 6px; */ - gap: 8px; + &[data-size="large"] { + height: 32px; + /* padding: 0 8px 0 6px; */ + gap: 8px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } - &:focus { - outline: none; - } + &:focus { + outline: none; + } } diff --git a/packages/ui/src/components/icon.css b/packages/ui/src/components/icon.css index dd760ccbc2..467ff21bcc 100644 --- a/packages/ui/src/components/icon.css +++ b/packages/ui/src/components/icon.css @@ -1,34 +1,34 @@ [data-component="icon"] { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - /* resize: both; */ - aspect-ratio: 1 / 1; - color: var(--icon-base); + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + /* resize: both; */ + aspect-ratio: 1 / 1; + color: var(--icon-base); - &[data-size="small"] { - width: 16px; - height: 16px; - } + &[data-size="small"] { + width: 16px; + height: 16px; + } - &[data-size="normal"] { - width: 20px; - height: 20px; - } + &[data-size="normal"] { + width: 20px; + height: 20px; + } - &[data-size="medium"] { - width: 24px; - height: 24px; - } + &[data-size="medium"] { + width: 24px; + height: 24px; + } - &[data-size="large"] { - width: 24px; - height: 24px; - } + &[data-size="large"] { + width: 24px; + height: 24px; + } - [data-slot="icon-svg"] { - width: 100%; - height: auto; - } + [data-slot="icon-svg"] { + width: 100%; + height: auto; + } } diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index f23357293e..97488a42f0 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -86,7 +86,10 @@ export interface IconProps extends ComponentProps<"svg"> { export function Icon(props: IconProps) { const [local, others] = splitProps(props, ["name", "size", "class", "classList"]) return ( -
+
"; - inherits: false; - initial-value: 0px; + syntax: ""; + inherits: false; + initial-value: 0px; } @keyframes scroll { - 0% { - --bottom-fade: 20px; - } - 90% { - --bottom-fade: 20px; - } - 100% { - --bottom-fade: 0; - } + 0% { + --bottom-fade: 20px; + } + 90% { + --bottom-fade: 20px; + } + 100% { + --bottom-fade: 0; + } } [data-component="list"] { - display: flex; - flex-direction: column; - gap: 8px; - overflow: hidden; - padding: 0 12px; + display: flex; + flex-direction: column; + gap: 8px; + overflow: hidden; + padding: 0 12px; - [data-slot="list-search-wrapper"] { - display: flex; - flex-shrink: 0; - align-items: center; - gap: 8px; - align-self: stretch; - margin-bottom: 4px; + [data-slot="list-search-wrapper"] { + display: flex; + flex-shrink: 0; + align-items: center; + gap: 8px; + align-self: stretch; + margin-bottom: 4px; - > [data-component="icon-button"] { - width: 24px; - height: 24px; - flex-shrink: 0; - background-color: transparent; - opacity: 0.5; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + > [data-component="icon-button"] { + width: 24px; + height: 24px; + flex-shrink: 0; + background-color: transparent; + opacity: 0.5; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &:hover:not(:disabled), - &:focus-visible:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - opacity: 0.7; - } + &:hover:not(:disabled), + &:focus-visible:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + opacity: 0.7; + } - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - } + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + } - [data-slot="list-search"] { - display: flex; - flex: 1; - padding: 8px; - align-items: center; - gap: 12px; + [data-slot="list-search"] { + display: flex; + flex: 1; + padding: 8px; + align-items: center; + gap: 12px; - border-radius: var(--radius-md); - background: var(--surface-base); + border-radius: var(--radius-md); + background: var(--surface-base); - [data-slot="list-search-container"] { - display: flex; - align-items: center; - gap: 8px; - flex: 1 0 0; - max-height: 20px; + [data-slot="list-search-container"] { + display: flex; + align-items: center; + gap: 8px; + flex: 1 0 0; + max-height: 20px; - [data-slot="list-search-input"] { - width: 100%; + [data-slot="list-search-input"] { + width: 100%; - &[data-slot="input-input"] { - line-height: 20px; - max-height: 20px; - } - } - } + &[data-slot="input-input"] { + line-height: 20px; + max-height: 20px; + } + } + } - > [data-component="icon-button"] { - width: 20px; - height: 20px; - background-color: transparent; - opacity: 0.5; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + > [data-component="icon-button"] { + width: 20px; + height: 20px; + background-color: transparent; + opacity: 0.5; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &:hover:not(:disabled), - &:focus-visible:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - opacity: 0.7; - } + &:hover:not(:disabled), + &:focus-visible:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + opacity: 0.7; + } - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } - > [data-component="icon-button"] { - background-color: transparent; + > [data-component="icon-button"] { + background-color: transparent; - &:hover:not(:disabled), - &:focus:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - } + &:hover:not(:disabled), + &:focus:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + } - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - } + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + } - [data-slot="list-scroll"] { - display: flex; - flex-direction: column; - gap: 12px; - overflow-y: auto; - overscroll-behavior: contain; + [data-slot="list-scroll"] { + display: flex; + flex-direction: column; + gap: 12px; + overflow-y: auto; + overscroll-behavior: contain; - [data-slot="list-empty-state"] { - display: flex; - padding: 32px 48px; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 8px; - align-self: stretch; + [data-slot="list-empty-state"] { + display: flex; + padding: 32px 48px; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 8px; + align-self: stretch; - [data-slot="list-message"] { - display: flex; - justify-content: center; - align-items: center; - gap: 2px; - max-width: 100%; - color: var(--text-weak); - white-space: nowrap; + [data-slot="list-message"] { + display: flex; + justify-content: center; + align-items: center; + gap: 2px; + max-width: 100%; + color: var(--text-weak); + white-space: nowrap; - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="list-filter"] { - color: var(--text-strong); - overflow: hidden; - text-overflow: ellipsis; - } - } + [data-slot="list-filter"] { + color: var(--text-strong); + overflow: hidden; + text-overflow: ellipsis; + } + } - [data-slot="list-group"] { - position: relative; - display: flex; - flex-direction: column; + [data-slot="list-group"] { + position: relative; + display: flex; + flex-direction: column; - &:last-child { - padding-bottom: 12px; - } + &:last-child { + padding-bottom: 12px; + } - [data-slot="list-header"] { - display: flex; - z-index: 10; - padding: 8px 12px 8px 8px; - justify-content: space-between; - align-items: center; - align-self: stretch; - background: var(--surface-raised-stronger-non-alpha); - position: sticky; - top: 0; + [data-slot="list-header"] { + display: flex; + z-index: 10; + padding: 8px 12px 8px 8px; + justify-content: space-between; + align-items: center; + align-self: stretch; + background: var(--surface-raised-stronger-non-alpha); + position: sticky; + top: 0; - color: var(--text-weak); + color: var(--text-weak); - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - &::after { - content: ""; - position: absolute; - top: 100%; - left: 0; - right: 0; - height: 16px; - background: linear-gradient( - to bottom, - var(--surface-raised-stronger-non-alpha), - transparent - ); - pointer-events: none; - opacity: 0; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + &::after { + content: ""; + position: absolute; + top: 100%; + left: 0; + right: 0; + height: 16px; + background: linear-gradient(to bottom, var(--surface-raised-stronger-non-alpha), transparent); + pointer-events: none; + opacity: 0; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - &[data-stuck="true"]::after { - opacity: 1; - } - } + &[data-stuck="true"]::after { + opacity: 1; + } + } - [data-slot="list-items"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; + [data-slot="list-items"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; - [data-slot="list-item"] { - display: flex; - position: relative; - width: 100%; - padding: 6px 8px 6px 8px; - align-items: center; - color: var(--text-strong); - scroll-margin-top: 28px; + [data-slot="list-item"] { + display: flex; + position: relative; + width: 100%; + padding: 6px 8px 6px 8px; + align-items: center; + color: var(--text-strong); + scroll-margin-top: 28px; - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - [data-slot="list-item-selected-icon"] { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - aspect-ratio: 1 / 1; - [data-component="icon"] { - color: var(--icon-strong-base); - } - } + [data-slot="list-item-selected-icon"] { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + aspect-ratio: 1 / 1; + [data-component="icon"] { + color: var(--icon-strong-base); + } + } - [name="check"] { - color: var(--icon-strong-base); - } + [name="check"] { + color: var(--icon-strong-base); + } - [data-slot="list-item-active-icon"] { - display: none; - align-items: center; - justify-content: center; - flex-shrink: 0; - aspect-ratio: 1 / 1; - [data-component="icon"] { - color: var(--icon-strong-base); - } - } + [data-slot="list-item-active-icon"] { + display: none; + align-items: center; + justify-content: center; + flex-shrink: 0; + aspect-ratio: 1 / 1; + [data-component="icon"] { + color: var(--icon-strong-base); + } + } - [data-slot="list-item-extra-icon"] { - color: var(--icon-base); - margin-left: -4px; - } + [data-slot="list-item-extra-icon"] { + color: var(--icon-base); + margin-left: -4px; + } - [data-slot="list-item-divider"] { - position: absolute; - bottom: 0; - left: var(--list-divider-inset, 16px); - right: var(--list-divider-inset, 16px); - height: 1px; - background: var(--border-weak-base); - pointer-events: none; - } + [data-slot="list-item-divider"] { + position: absolute; + bottom: 0; + left: var(--list-divider-inset, 16px); + right: var(--list-divider-inset, 16px); + height: 1px; + background: var(--border-weak-base); + pointer-events: none; + } - [data-slot="list-item"]:last-child [data-slot="list-item-divider"] { - display: none; - } + [data-slot="list-item"]:last-child [data-slot="list-item-divider"] { + display: none; + } - &[data-active="true"] { - border-radius: var(--radius-md); - background: var(--surface-raised-base-hover); - [data-slot="list-item-active-icon"] { - display: inline-flex; - } - [data-slot="list-item-extra-icon"] { - display: block !important; - color: var(--icon-strong-base) !important; - } - } - &:active { - background: var(--surface-raised-base-active); - } - &:focus-visible { - outline: none; - } - } + &[data-active="true"] { + border-radius: var(--radius-md); + background: var(--surface-raised-base-hover); + [data-slot="list-item-active-icon"] { + display: inline-flex; + } + [data-slot="list-item-extra-icon"] { + display: block !important; + color: var(--icon-strong-base) !important; + } + } + &:active { + background: var(--surface-raised-base-active); + } + &:focus-visible { + outline: none; + } + } - [data-slot="list-item-add"] { - display: flex; - position: relative; - width: 100%; - padding: 6px 8px 6px 8px; - align-items: center; - color: var(--text-strong); + [data-slot="list-item-add"] { + display: flex; + position: relative; + width: 100%; + padding: 6px 8px 6px 8px; + align-items: center; + color: var(--text-strong); - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - [data-component="input"] { - width: 100%; - } - } - } - } - } + [data-component="input"] { + width: 100%; + } + } + } + } + } } diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index f612a231e0..15854180e4 100644 --- a/packages/ui/src/components/list.tsx +++ b/packages/ui/src/components/list.tsx @@ -268,13 +268,7 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void }) {searchAction()}
- + 0 || showAdd()} fallback={ diff --git a/packages/ui/src/components/logo.css b/packages/ui/src/components/logo.css index b16c441d2b..091649e8bb 100644 --- a/packages/ui/src/components/logo.css +++ b/packages/ui/src/components/logo.css @@ -1,4 +1,4 @@ [data-component="logo-mark"] { - width: 16px; - aspect-ratio: 4 / 5; + width: 16px; + aspect-ratio: 4 / 5; } diff --git a/packages/ui/src/components/markdown.css b/packages/ui/src/components/markdown.css index 5d7f26e3d3..ef43187336 100644 --- a/packages/ui/src/components/markdown.css +++ b/packages/ui/src/components/markdown.css @@ -1,211 +1,209 @@ [data-component="markdown"] { - /* Reset & Base Typography */ - min-width: 0; - max-width: 100%; - overflow-wrap: break-word; - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: var(--font-size-base); /* 14px */ - line-height: var(--line-height-x-large); + /* Reset & Base Typography */ + min-width: 0; + max-width: 100%; + overflow-wrap: break-word; + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); /* 14px */ + line-height: var(--line-height-x-large); - /* Spacing for flow */ - > *:first-child { - margin-top: 0; - } - > *:last-child { - margin-bottom: 0; - } + /* Spacing for flow */ + > *:first-child { + margin-top: 0; + } + > *:last-child { + margin-bottom: 0; + } - /* Headings: Same size, distinguished by color and spacing */ - h1, - h2, - h3, - h4, - h5, - h6 { - font-size: var(--font-size-base); - color: var(--text-strong); - font-weight: var(--font-weight-medium); - margin-top: 2rem; - margin-bottom: 0.75rem; - line-height: var(--line-height-large); - } + /* Headings: Same size, distinguished by color and spacing */ + h1, + h2, + h3, + h4, + h5, + h6 { + font-size: var(--font-size-base); + color: var(--text-strong); + font-weight: var(--font-weight-medium); + margin-top: 2rem; + margin-bottom: 0.75rem; + line-height: var(--line-height-large); + } - /* Emphasis & Strong: Neutral strong color */ - strong, - b { - color: var(--text-strong); - font-weight: var(--font-weight-medium); - } + /* Emphasis & Strong: Neutral strong color */ + strong, + b { + color: var(--text-strong); + font-weight: var(--font-weight-medium); + } - /* Paragraphs */ - p { - margin-bottom: 1rem; - } + /* Paragraphs */ + p { + margin-bottom: 1rem; + } - /* Links */ - a { - color: var(--text-interactive-base); - text-decoration: none; - font-weight: inherit; - } + /* Links */ + a { + color: var(--text-interactive-base); + text-decoration: none; + font-weight: inherit; + } - a:hover { - text-decoration: underline; - text-underline-offset: 2px; - } + a:hover { + text-decoration: underline; + text-underline-offset: 2px; + } - /* Lists */ - ul, - ol { - margin-top: 0.5rem; - margin-bottom: 1rem; - padding-left: 1.5rem; - list-style-position: outside; - } + /* Lists */ + ul, + ol { + margin-top: 0.5rem; + margin-bottom: 1rem; + padding-left: 1.5rem; + list-style-position: outside; + } - ul { - list-style-type: disc; - } + ul { + list-style-type: disc; + } - ol { - list-style-type: decimal; - } + ol { + list-style-type: decimal; + } - li { - margin-bottom: 0.5rem; - } + li { + margin-bottom: 0.5rem; + } - li > p:first-child { - display: inline; - margin: 0; - } + li > p:first-child { + display: inline; + margin: 0; + } - li > p + p { - display: block; - margin-top: 0.5rem; - } + li > p + p { + display: block; + margin-top: 0.5rem; + } - li::marker { - color: var(--text-weak); - } + li::marker { + color: var(--text-weak); + } - /* Nested lists spacing */ - li > ul, - li > ol { - margin-top: 0.25rem; - margin-bottom: 0.25rem; - padding-left: 1rem; /* Minimal indent for nesting only */ - } + /* Nested lists spacing */ + li > ul, + li > ol { + margin-top: 0.25rem; + margin-bottom: 0.25rem; + padding-left: 1rem; /* Minimal indent for nesting only */ + } - /* Blockquotes */ - blockquote { - border-left: 2px solid var(--border-weak-base); - margin: 1.5rem 0; - padding-left: 0.5rem; - color: var(--text-weak); - font-style: normal; - } + /* Blockquotes */ + blockquote { + border-left: 2px solid var(--border-weak-base); + margin: 1.5rem 0; + padding-left: 0.5rem; + color: var(--text-weak); + font-style: normal; + } - /* Horizontal Rule - Invisible spacing only */ - hr { - border: none; - height: 0; - margin: 2.5rem 0; - } + /* Horizontal Rule - Invisible spacing only */ + hr { + border: none; + height: 0; + margin: 2.5rem 0; + } - .shiki { - font-size: 13px; - padding: 8px 12px; - border-radius: 4px; - border: 0.5px solid var(--border-weak-base); - } + .shiki { + font-size: 13px; + padding: 8px 12px; + border-radius: 4px; + border: 0.5px solid var(--border-weak-base); + } - [data-component="markdown-code"] { - position: relative; - } + [data-component="markdown-code"] { + position: relative; + } - [data-slot="markdown-copy-button"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } + [data-slot="markdown-copy-button"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } - [data-component="markdown-code"]:hover [data-slot="markdown-copy-button"] { - opacity: 1; - } + [data-component="markdown-code"]:hover [data-slot="markdown-copy-button"] { + opacity: 1; + } - [data-slot="markdown-copy-button"] [data-slot="check-icon"] { - display: none; - } + [data-slot="markdown-copy-button"] [data-slot="check-icon"] { + display: none; + } - [data-slot="markdown-copy-button"][data-copied="true"] - [data-slot="copy-icon"] { - display: none; - } + [data-slot="markdown-copy-button"][data-copied="true"] [data-slot="copy-icon"] { + display: none; + } - [data-slot="markdown-copy-button"][data-copied="true"] - [data-slot="check-icon"] { - display: inline-flex; - } + [data-slot="markdown-copy-button"][data-copied="true"] [data-slot="check-icon"] { + display: inline-flex; + } - pre { - margin-top: 2rem; - margin-bottom: 2rem; - overflow: auto; + pre { + margin-top: 2rem; + margin-bottom: 2rem; + overflow: auto; - scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } - } + scrollbar-width: none; + &::-webkit-scrollbar { + display: none; + } + } - :not(pre) > code { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - color: var(--syntax-string); - font-weight: var(--font-weight-medium); - /* font-size: 13px; */ + :not(pre) > code { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + color: var(--syntax-string); + font-weight: var(--font-weight-medium); + /* font-size: 13px; */ - /* padding: 2px 2px; */ - /* margin: 0 1.5px; */ - /* border-radius: 2px; */ - /* background: var(--surface-base); */ - /* box-shadow: 0 0 0 0.5px var(--border-weak-base); */ - } + /* padding: 2px 2px; */ + /* margin: 0 1.5px; */ + /* border-radius: 2px; */ + /* background: var(--surface-base); */ + /* box-shadow: 0 0 0 0.5px var(--border-weak-base); */ + } - /* Tables */ - table { - width: 100%; - border-collapse: collapse; - margin: 1.5rem 0; - font-size: var(--font-size-base); - } + /* Tables */ + table { + width: 100%; + border-collapse: collapse; + margin: 1.5rem 0; + font-size: var(--font-size-base); + } - th, - td { - /* Minimal borders for structure, matching TUI "lines" roughly but keeping it web-clean */ - border-bottom: 1px solid var(--border-weaker-base); - padding: 0.75rem 0.5rem; - text-align: left; - vertical-align: top; - } + th, + td { + /* Minimal borders for structure, matching TUI "lines" roughly but keeping it web-clean */ + border-bottom: 1px solid var(--border-weaker-base); + padding: 0.75rem 0.5rem; + text-align: left; + vertical-align: top; + } - th { - color: var(--text-strong); - font-weight: var(--font-weight-medium); - border-bottom: 1px solid var(--border-weak-base); - } + th { + color: var(--text-strong); + font-weight: var(--font-weight-medium); + border-bottom: 1px solid var(--border-weak-base); + } - /* Images */ - img { - max-width: 100%; - height: auto; - border-radius: 4px; - margin: 1.5rem 0; - display: block; - } + /* Images */ + img { + max-width: 100%; + height: auto; + border-radius: 4px; + margin: 1.5rem 0; + display: block; + } } diff --git a/packages/ui/src/components/message-nav.css b/packages/ui/src/components/message-nav.css index 6b82dc91c2..b1454ad425 100644 --- a/packages/ui/src/components/message-nav.css +++ b/packages/ui/src/components/message-nav.css @@ -1,123 +1,122 @@ [data-component="message-nav"] { - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: flex-start; - padding-left: 0; - list-style: none; + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + padding-left: 0; + list-style: none; - &[data-size="normal"] { - width: 240px; - gap: 4px; - } + &[data-size="normal"] { + width: 240px; + gap: 4px; + } - &[data-size="compact"] { - width: 24px; - } + &[data-size="compact"] { + width: 24px; + } } [data-slot="message-nav-item"] { - display: flex; - align-items: center; - align-self: stretch; - justify-content: flex-end; + display: flex; + align-items: center; + align-self: stretch; + justify-content: flex-end; - [data-component="message-nav"][data-size="normal"] & { - justify-content: flex-start; - } + [data-component="message-nav"][data-size="normal"] & { + justify-content: flex-start; + } } [data-slot="message-nav-tick-button"] { - display: flex; - align-items: center; - justify-content: flex-start; - height: 12px; - width: 24px; - border: none; - background: none; - padding: 0; + display: flex; + align-items: center; + justify-content: flex-start; + height: 12px; + width: 24px; + border: none; + background: none; + padding: 0; - &[data-active] [data-slot="message-nav-tick-line"] { - background-color: var(--icon-strong-base); - width: 100%; - } + &[data-active] [data-slot="message-nav-tick-line"] { + background-color: var(--icon-strong-base); + width: 100%; + } } [data-slot="message-nav-tick-line"] { - height: 1px; - width: 16px; - background-color: var(--icon-base); - transition: - width 0.2s, - background-color 0.2s; + height: 1px; + width: 16px; + background-color: var(--icon-base); + transition: + width 0.2s, + background-color 0.2s; } -[data-slot="message-nav-tick-button"]:hover - [data-slot="message-nav-tick-line"] { - width: 100%; - background-color: var(--icon-strong-base); +[data-slot="message-nav-tick-button"]:hover [data-slot="message-nav-tick-line"] { + width: 100%; + background-color: var(--icon-strong-base); } [data-slot="message-nav-message-button"] { - display: flex; - align-items: center; - align-self: stretch; - width: 100%; - column-gap: 12px; - cursor: default; - border: none; - background: none; - padding: 4px 12px; - border-radius: var(--radius-sm); + display: flex; + align-items: center; + align-self: stretch; + width: 100%; + column-gap: 12px; + cursor: default; + border: none; + background: none; + padding: 4px 12px; + border-radius: var(--radius-sm); } [data-slot="message-nav-title-preview"] { - font-size: 14px; /* text-14-regular */ - color: var(--text-base); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - text-align: left; + font-size: 14px; /* text-14-regular */ + color: var(--text-base); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + text-align: left; - &[data-active] { - color: var(--text-strong); - } + &[data-active] { + color: var(--text-strong); + } } [data-slot="message-nav-item"]:hover [data-slot="message-nav-message-button"] { - background-color: var(--surface-base); + background-color: var(--surface-base); } [data-slot="message-nav-item"]:active [data-slot="message-nav-message-button"] { - background-color: var(--surface-base-active); + background-color: var(--surface-base-active); } [data-slot="message-nav-item"]:active [data-slot="message-nav-title-preview"] { - color: var(--text-base); + color: var(--text-base); } [data-slot="message-nav-tooltip"] { - z-index: 1000; + z-index: 1000; } [data-slot="message-nav-tooltip-content"] { - display: flex; - padding: 4px 4px 6px 4px; - justify-content: center; - align-items: center; - border-radius: var(--radius-md); - background: var(--surface-raised-stronger-non-alpha); - max-height: calc(100vh - 6rem); - overflow-y: auto; + display: flex; + padding: 4px 4px 6px 4px; + justify-content: center; + align-items: center; + border-radius: var(--radius-md); + background: var(--surface-raised-stronger-non-alpha); + max-height: calc(100vh - 6rem); + overflow-y: auto; - /* border/shadow-xs/base */ - box-shadow: - 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), - 0 1px 2px -1px rgba(19, 16, 16, 0.04), - 0 1px 2px 0 rgba(19, 16, 16, 0.06), - 0 1px 3px 0 rgba(19, 16, 16, 0.08); + /* border/shadow-xs/base */ + box-shadow: + 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), + 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), + 0 1px 3px 0 rgba(19, 16, 16, 0.08); - * { - margin: 0 !important; - } + * { + margin: 0 !important; + } } diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index dba0a59b72..2bef792a2c 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -1,439 +1,439 @@ [data-component="assistant-message"] { - content-visibility: auto; - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; + content-visibility: auto; + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; } [data-component="user-message"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); - display: flex; - flex-direction: column; - gap: 8px; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); + display: flex; + flex-direction: column; + gap: 8px; - [data-slot="user-message-attachments"] { - display: flex; - flex-wrap: wrap; - gap: 8px; - } + [data-slot="user-message-attachments"] { + display: flex; + flex-wrap: wrap; + gap: 8px; + } - [data-slot="user-message-attachment"] { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - border-radius: 6px; - overflow: hidden; - background: var(--surface-weak); - border: 1px solid var(--border-weak-base); - transition: border-color 0.15s ease; + [data-slot="user-message-attachment"] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 6px; + overflow: hidden; + background: var(--surface-weak); + border: 1px solid var(--border-weak-base); + transition: border-color 0.15s ease; - &:hover { - border-color: var(--border-strong-base); - } + &:hover { + border-color: var(--border-strong-base); + } - &[data-type="image"] { - width: 48px; - height: 48px; - } + &[data-type="image"] { + width: 48px; + height: 48px; + } - &[data-type="file"] { - width: 48px; - height: 48px; - } - } + &[data-type="file"] { + width: 48px; + height: 48px; + } + } - [data-slot="user-message-attachment-image"] { - width: 100%; - height: 100%; - object-fit: cover; - } + [data-slot="user-message-attachment-image"] { + width: 100%; + height: 100%; + object-fit: cover; + } - [data-slot="user-message-attachment-icon"] { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - color: var(--icon-weak); + [data-slot="user-message-attachment-icon"] { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: var(--icon-weak); - [data-component="icon"] { - width: 20px; - height: 20px; - } - } + [data-component="icon"] { + width: 20px; + height: 20px; + } + } - [data-slot="user-message-text"] { - position: relative; - white-space: pre-wrap; - word-break: break-word; - overflow: hidden; - background: var(--surface-weak); - border: 1px solid var(--border-weak-base); - padding: 8px 12px; - border-radius: 4px; + [data-slot="user-message-text"] { + position: relative; + white-space: pre-wrap; + word-break: break-word; + overflow: hidden; + background: var(--surface-weak); + border: 1px solid var(--border-weak-base); + padding: 8px 12px; + border-radius: 4px; - [data-highlight="file"] { - color: var(--syntax-property); - } + [data-highlight="file"] { + color: var(--syntax-property); + } - [data-highlight="agent"] { - color: var(--syntax-type); - } + [data-highlight="agent"] { + color: var(--syntax-type); + } - [data-slot="user-message-copy-wrapper"] { - position: absolute; - top: 7px; - right: 7px; - opacity: 0; - transition: opacity 0.15s ease; - } + [data-slot="user-message-copy-wrapper"] { + position: absolute; + top: 7px; + right: 7px; + opacity: 0; + transition: opacity 0.15s ease; + } - &:hover [data-slot="user-message-copy-wrapper"] { - opacity: 1; - } - } + &:hover [data-slot="user-message-copy-wrapper"] { + opacity: 1; + } + } - .text-text-strong { - color: var(--text-strong); - } + .text-text-strong { + color: var(--text-strong); + } - .font-medium { - font-weight: var(--font-weight-medium); - } + .font-medium { + font-weight: var(--font-weight-medium); + } } [data-component="text-part"] { - width: 100%; + width: 100%; - [data-slot="text-part-body"] { - position: relative; - margin-top: 32px; - } + [data-slot="text-part-body"] { + position: relative; + margin-top: 32px; + } - [data-slot="text-part-copy-wrapper"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } + [data-slot="text-part-copy-wrapper"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } - [data-slot="text-part-body"]:hover [data-slot="text-part-copy-wrapper"] { - opacity: 1; - } + [data-slot="text-part-body"]:hover [data-slot="text-part-copy-wrapper"] { + opacity: 1; + } - [data-component="markdown"] { - margin-top: 0; - font-size: var(--font-size-base); - } + [data-component="markdown"] { + margin-top: 0; + font-size: var(--font-size-base); + } } [data-component="reasoning-part"] { - width: 100%; - color: var(--text-base); - opacity: 0.8; - line-height: var(--line-height-large); + width: 100%; + color: var(--text-base); + opacity: 0.8; + line-height: var(--line-height-large); - [data-component="markdown"] { - margin-top: 24px; - font-style: italic !important; + [data-component="markdown"] { + margin-top: 24px; + font-style: italic !important; - p:has(strong) { - margin-top: 24px; - margin-bottom: 0; + p:has(strong) { + margin-top: 24px; + margin-bottom: 0; - &:first-child { - margin-top: 0; - } - } - } + &:first-child { + margin-top: 0; + } + } + } } [data-component="tool-error"] { - display: flex; - align-items: start; - gap: 8px; + display: flex; + align-items: start; + gap: 8px; - [data-slot="icon-svg"] { - color: var(--icon-critical-base); - margin-top: 4px; - } + [data-slot="icon-svg"] { + color: var(--icon-critical-base); + margin-top: 4px; + } - [data-slot="message-part-tool-error-content"] { - display: flex; - align-items: start; - gap: 8px; - } + [data-slot="message-part-tool-error-content"] { + display: flex; + align-items: start; + gap: 8px; + } - [data-slot="message-part-tool-error-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-on-critical-base); - white-space: nowrap; - } + [data-slot="message-part-tool-error-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-on-critical-base); + white-space: nowrap; + } - [data-slot="message-part-tool-error-message"] { - color: var(--text-on-critical-weak); - max-height: 240px; - overflow-y: auto; - word-break: break-word; - } + [data-slot="message-part-tool-error-message"] { + color: var(--text-on-critical-weak); + max-height: 240px; + overflow-y: auto; + word-break: break-word; + } } [data-component="tool-output"] { - white-space: pre; - padding: 8px 12px; - height: fit-content; - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; + white-space: pre; + padding: 8px 12px; + height: fit-content; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; - [data-component="markdown"] { - width: 100%; - min-width: 0; + [data-component="markdown"] { + width: 100%; + min-width: 0; - pre { - margin: 0; - padding: 0; - background-color: transparent !important; - border: none !important; - } - } + pre { + margin: 0; + padding: 0; + background-color: transparent !important; + border: none !important; + } + } - pre { - margin: 0; - padding: 0; - background: none; - } + pre { + margin: 0; + padding: 0; + background: none; + } - &[data-scrollable] { - height: auto; - max-height: 240px; - overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + &[data-scrollable] { + height: auto; + max-height: 240px; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } - [data-component="markdown"] { - overflow: visible; - } - } + [data-component="markdown"] { + overflow: visible; + } + } } [data-component="edit-trigger"], [data-component="write-trigger"] { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + width: 100%; - [data-slot="message-part-title-area"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - } + [data-slot="message-part-title-area"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + } - [data-slot="message-part-title"] { - flex-shrink: 0; - display: flex; - align-items: center; - gap: 4px; - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); - } + [data-slot="message-part-title"] { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 4px; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); + } - [data-slot="message-part-title-text"] { - text-transform: capitalize; - } + [data-slot="message-part-title-text"] { + text-transform: capitalize; + } - [data-slot="message-part-title-filename"] { - /* No text-transform - preserve original filename casing */ - } + [data-slot="message-part-title-filename"] { + /* No text-transform - preserve original filename casing */ + } - [data-slot="message-part-path"] { - display: flex; - flex-grow: 1; - min-width: 0; - } + [data-slot="message-part-path"] { + display: flex; + flex-grow: 1; + min-width: 0; + } - [data-slot="message-part-directory"] { - color: var(--text-weak); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } + [data-slot="message-part-directory"] { + color: var(--text-weak); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } - [data-slot="message-part-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } + [data-slot="message-part-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } - [data-slot="message-part-actions"] { - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - } + [data-slot="message-part-actions"] { + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + } } [data-component="edit-content"] { - border-top: 1px solid var(--border-weaker-base); - max-height: 420px; - overflow-y: auto; + border-top: 1px solid var(--border-weaker-base); + max-height: 420px; + overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="write-content"] { - border-top: 1px solid var(--border-weaker-base); - max-height: 240px; - overflow-y: auto; + border-top: 1px solid var(--border-weaker-base); + max-height: 240px; + overflow-y: auto; - [data-component="code"] { - padding-bottom: 0px !important; - } + [data-component="code"] { + padding-bottom: 0px !important; + } - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="tool-action"] { - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; } [data-component="todos"] { - padding: 10px 12px 24px 48px; - display: flex; - flex-direction: column; - gap: 8px; + padding: 10px 12px 24px 48px; + display: flex; + flex-direction: column; + gap: 8px; - [data-slot="message-part-todo-content"] { - &[data-completed="completed"] { - text-decoration: line-through; - color: var(--text-weaker); - } - } + [data-slot="message-part-todo-content"] { + &[data-completed="completed"] { + text-decoration: line-through; + color: var(--text-weaker); + } + } } [data-component="task-tools"] { - padding: 8px 12px; - display: flex; - flex-direction: column; - gap: 6px; + padding: 8px 12px; + display: flex; + flex-direction: column; + gap: 6px; - [data-slot="task-tool-item"] { - display: flex; - align-items: center; - gap: 8px; - color: var(--text-weak); + [data-slot="task-tool-item"] { + display: flex; + align-items: center; + gap: 8px; + color: var(--text-weak); - [data-slot="icon-svg"] { - flex-shrink: 0; - color: var(--icon-weak); - } - } + [data-slot="icon-svg"] { + flex-shrink: 0; + color: var(--icon-weak); + } + } - [data-slot="task-tool-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-weak); - } + [data-slot="task-tool-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-weak); + } - [data-slot="task-tool-subtitle"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - color: var(--text-weaker); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + [data-slot="task-tool-subtitle"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + color: var(--text-weaker); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } } [data-component="diagnostics"] { - display: flex; - flex-direction: column; - gap: 4px; - padding: 8px 12px; - background-color: var(--surface-critical-weak); - border-top: 1px solid var(--border-critical-base); + display: flex; + flex-direction: column; + gap: 4px; + padding: 8px 12px; + background-color: var(--surface-critical-weak); + border-top: 1px solid var(--border-critical-base); - [data-slot="diagnostic"] { - display: flex; - align-items: baseline; - gap: 6px; - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - line-height: var(--line-height-large); - } + [data-slot="diagnostic"] { + display: flex; + align-items: baseline; + gap: 6px; + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + line-height: var(--line-height-large); + } - [data-slot="diagnostic-label"] { - color: var(--text-on-critical-base); - font-weight: var(--font-weight-medium); - text-transform: uppercase; - letter-spacing: -0.5px; - flex-shrink: 0; - } + [data-slot="diagnostic-label"] { + color: var(--text-on-critical-base); + font-weight: var(--font-weight-medium); + text-transform: uppercase; + letter-spacing: -0.5px; + flex-shrink: 0; + } - [data-slot="diagnostic-location"] { - color: var(--text-on-critical-weak); - flex-shrink: 0; - } + [data-slot="diagnostic-location"] { + color: var(--text-on-critical-weak); + flex-shrink: 0; + } - [data-slot="diagnostic-message"] { - color: var(--text-on-critical-base); - word-break: break-word; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - } + [data-slot="diagnostic-message"] { + color: var(--text-on-critical-base); + word-break: break-word; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; + line-clamp: 3; + overflow: hidden; + } } [data-component="user-message"] [data-slot="user-message-text"], @@ -446,383 +446,383 @@ [data-component="todos"], [data-component="diagnostics"], .error-card { - -webkit-user-select: text; - user-select: text; + -webkit-user-select: text; + user-select: text; } [data-component="tool-part-wrapper"] { - width: 100%; + width: 100%; - &[data-permission="true"], - &[data-question="true"] { - position: sticky; - top: calc(2px + var(--sticky-header-height, 40px)); - bottom: 0px; - z-index: 20; - border-radius: 6px; - border: none; - box-shadow: var(--shadow-xs-border-base); - background-color: var(--surface-raised-base); - overflow: visible; - overflow-anchor: none; + &[data-permission="true"], + &[data-question="true"] { + position: sticky; + top: calc(2px + var(--sticky-header-height, 40px)); + bottom: 0px; + z-index: 20; + border-radius: 6px; + border: none; + box-shadow: var(--shadow-xs-border-base); + background-color: var(--surface-raised-base); + overflow: visible; + overflow-anchor: none; - & > *:first-child { - border-top-left-radius: 6px; - border-top-right-radius: 6px; - overflow: hidden; - } + & > *:first-child { + border-top-left-radius: 6px; + border-top-right-radius: 6px; + overflow: hidden; + } - & > *:last-child { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - overflow: hidden; - } + & > *:last-child { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + overflow: hidden; + } - [data-component="collapsible"] { - border: none; - } + [data-component="collapsible"] { + border: none; + } - [data-component="card"] { - border: none; - } - } + [data-component="card"] { + border: none; + } + } - &[data-permission="true"] { - &::before { - content: ""; - position: absolute; - inset: -1.5px; - top: -5px; - border-radius: 7.5px; - border: 1.5px solid transparent; - background: - linear-gradient(var(--background-base) 0 0) padding-box, - conic-gradient( - from var(--border-angle), - transparent 0deg, - transparent 0deg, - var(--border-warning-strong, var(--border-warning-selected)) 300deg, - var(--border-warning-base) 360deg - ) - border-box; - animation: chase-border 2.5s linear infinite; - pointer-events: none; - z-index: -1; - } - } + &[data-permission="true"] { + &::before { + content: ""; + position: absolute; + inset: -1.5px; + top: -5px; + border-radius: 7.5px; + border: 1.5px solid transparent; + background: + linear-gradient(var(--background-base) 0 0) padding-box, + conic-gradient( + from var(--border-angle), + transparent 0deg, + transparent 0deg, + var(--border-warning-strong, var(--border-warning-selected)) 300deg, + var(--border-warning-base) 360deg + ) + border-box; + animation: chase-border 2.5s linear infinite; + pointer-events: none; + z-index: -1; + } + } - &[data-question="true"] { - background: var(--background-base); - border: 1px solid var(--border-weak-base); - } + &[data-question="true"] { + background: var(--background-base); + border: 1px solid var(--border-weak-base); + } } @property --border-angle { - syntax: ""; - initial-value: 0deg; - inherits: false; + syntax: ""; + initial-value: 0deg; + inherits: false; } @keyframes chase-border { - from { - --border-angle: 0deg; - } + from { + --border-angle: 0deg; + } - to { - --border-angle: 360deg; - } + to { + --border-angle: 360deg; + } } [data-component="permission-prompt"] { - display: flex; - flex-direction: column; - padding: 8px 12px; - background-color: var(--surface-raised-strong); - border-radius: 0 0 6px 6px; + display: flex; + flex-direction: column; + padding: 8px 12px; + background-color: var(--surface-raised-strong); + border-radius: 0 0 6px 6px; - [data-slot="permission-actions"] { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; - } + [data-slot="permission-actions"] { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; + } } [data-component="question-prompt"] { - display: flex; - flex-direction: column; - padding: 12px; - background-color: var(--surface-inset-base); - border-radius: 0 0 6px 6px; - gap: 12px; + display: flex; + flex-direction: column; + padding: 12px; + background-color: var(--surface-inset-base); + border-radius: 0 0 6px 6px; + gap: 12px; - [data-slot="question-tabs"] { - display: flex; - gap: 4px; - flex-wrap: wrap; + [data-slot="question-tabs"] { + display: flex; + gap: 4px; + flex-wrap: wrap; - [data-slot="question-tab"] { - padding: 4px 12px; - font-size: 13px; - border-radius: 4px; - background-color: var(--surface-base); - color: var(--text-base); - border: none; - cursor: pointer; - transition: - color 0.15s, - background-color 0.15s; + [data-slot="question-tab"] { + padding: 4px 12px; + font-size: 13px; + border-radius: 4px; + background-color: var(--surface-base); + color: var(--text-base); + border: none; + cursor: pointer; + transition: + color 0.15s, + background-color 0.15s; - &:hover { - background-color: var(--surface-base-hover); - } + &:hover { + background-color: var(--surface-base-hover); + } - &[data-active="true"] { - background-color: var(--surface-raised-base); - } + &[data-active="true"] { + background-color: var(--surface-raised-base); + } - &[data-answered="true"] { - color: var(--text-strong); - } - } - } + &[data-answered="true"] { + color: var(--text-strong); + } + } + } - [data-slot="question-content"] { - display: flex; - flex-direction: column; - gap: 8px; + [data-slot="question-content"] { + display: flex; + flex-direction: column; + gap: 8px; - [data-slot="question-text"] { - font-size: 14px; - color: var(--text-base); - line-height: 1.5; - } - } + [data-slot="question-text"] { + font-size: 14px; + color: var(--text-base); + line-height: 1.5; + } + } - [data-slot="question-options"] { - display: flex; - flex-direction: column; - gap: 4px; + [data-slot="question-options"] { + display: flex; + flex-direction: column; + gap: 4px; - [data-slot="question-option"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 2px; - padding: 8px 12px; - background-color: var(--surface-base); - border: 1px solid var(--border-weaker-base); - border-radius: 6px; - cursor: pointer; - text-align: left; - width: 100%; - transition: - background-color 0.15s, - border-color 0.15s; - position: relative; + [data-slot="question-option"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + padding: 8px 12px; + background-color: var(--surface-base); + border: 1px solid var(--border-weaker-base); + border-radius: 6px; + cursor: pointer; + text-align: left; + width: 100%; + transition: + background-color 0.15s, + border-color 0.15s; + position: relative; - &:hover { - background-color: var(--surface-base-hover); - border-color: var(--border-default); - } + &:hover { + background-color: var(--surface-base-hover); + border-color: var(--border-default); + } - &[data-picked="true"] { - [data-component="icon"] { - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); - color: var(--text-strong); - } - } + &[data-picked="true"] { + [data-component="icon"] { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--text-strong); + } + } - [data-slot="option-label"] { - font-size: 14px; - color: var(--text-base); - font-weight: 500; - } + [data-slot="option-label"] { + font-size: 14px; + color: var(--text-base); + font-weight: 500; + } - [data-slot="option-description"] { - font-size: 12px; - color: var(--text-weak); - } - } + [data-slot="option-description"] { + font-size: 12px; + color: var(--text-weak); + } + } - [data-slot="custom-input-form"] { - display: flex; - gap: 8px; - padding: 8px 0; - align-items: stretch; + [data-slot="custom-input-form"] { + display: flex; + gap: 8px; + padding: 8px 0; + align-items: stretch; - [data-slot="custom-input"] { - flex: 1; - padding: 8px 12px; - font-size: 14px; - border: 1px solid var(--border-default); - border-radius: 6px; - background-color: var(--surface-base); - color: var(--text-base); - outline: none; + [data-slot="custom-input"] { + flex: 1; + padding: 8px 12px; + font-size: 14px; + border: 1px solid var(--border-default); + border-radius: 6px; + background-color: var(--surface-base); + color: var(--text-base); + outline: none; - &:focus { - border-color: var(--border-focus); - } + &:focus { + border-color: var(--border-focus); + } - &::placeholder { - color: var(--text-weak); - } - } + &::placeholder { + color: var(--text-weak); + } + } - [data-component="button"] { - height: auto; - } - } - } + [data-component="button"] { + height: auto; + } + } + } - [data-slot="question-review"] { - display: flex; - flex-direction: column; - gap: 12px; + [data-slot="question-review"] { + display: flex; + flex-direction: column; + gap: 12px; - [data-slot="review-title"] { - display: none; - } + [data-slot="review-title"] { + display: none; + } - [data-slot="review-item"] { - display: flex; - flex-direction: column; - gap: 2px; - font-size: 13px; + [data-slot="review-item"] { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 13px; - [data-slot="review-label"] { - color: var(--text-weak); - } + [data-slot="review-label"] { + color: var(--text-weak); + } - [data-slot="review-value"] { - color: var(--text-strong); + [data-slot="review-value"] { + color: var(--text-strong); - &[data-answered="false"] { - color: var(--text-weak); - } - } - } - } + &[data-answered="false"] { + color: var(--text-weak); + } + } + } + } - [data-slot="question-actions"] { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; - } + [data-slot="question-actions"] { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; + } } [data-component="question-answers"] { - display: flex; - flex-direction: column; - gap: 12px; - padding: 8px 12px; + display: flex; + flex-direction: column; + gap: 12px; + padding: 8px 12px; - [data-slot="question-answer-item"] { - display: flex; - flex-direction: column; - gap: 2px; - font-size: 13px; + [data-slot="question-answer-item"] { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 13px; - [data-slot="question-text"] { - color: var(--text-weak); - } + [data-slot="question-text"] { + color: var(--text-weak); + } - [data-slot="answer-text"] { - color: var(--text-strong); - } - } + [data-slot="answer-text"] { + color: var(--text-strong); + } + } } [data-component="apply-patch-files"] { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } [data-component="apply-patch-file"] { - display: flex; - flex-direction: column; - border-top: 1px solid var(--border-weaker-base); + display: flex; + flex-direction: column; + border-top: 1px solid var(--border-weaker-base); - &:first-child { - border-top: 1px solid var(--border-weaker-base); - } + &:first-child { + border-top: 1px solid var(--border-weaker-base); + } - [data-slot="apply-patch-file-header"] { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - background-color: var(--surface-inset-base); - } + [data-slot="apply-patch-file-header"] { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background-color: var(--surface-inset-base); + } - [data-slot="apply-patch-file-action"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-base); - flex-shrink: 0; + [data-slot="apply-patch-file-action"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-base); + flex-shrink: 0; - &[data-type="delete"] { - color: var(--text-critical-base); - } + &[data-type="delete"] { + color: var(--text-critical-base); + } - &[data-type="add"] { - color: var(--text-success-base); - } + &[data-type="add"] { + color: var(--text-success-base); + } - &[data-type="move"] { - color: var(--text-warning-base); - } - } + &[data-type="move"] { + color: var(--text-warning-base); + } + } - [data-slot="apply-patch-file-path"] { - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - color: var(--text-weak); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex-grow: 1; - } + [data-slot="apply-patch-file-path"] { + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + color: var(--text-weak); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-grow: 1; + } - [data-slot="apply-patch-deletion-count"] { - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - color: var(--text-critical-base); - flex-shrink: 0; - } + [data-slot="apply-patch-deletion-count"] { + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + color: var(--text-critical-base); + flex-shrink: 0; + } } [data-component="apply-patch-file-diff"] { - max-height: 420px; - overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + max-height: 420px; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="tool-loaded-file"] { - display: flex; - align-items: center; - gap: 8px; - padding: 4px 0 4px 28px; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - color: var(--text-weak); + display: flex; + align-items: center; + gap: 8px; + padding: 4px 0 4px 28px; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + color: var(--text-weak); - [data-component="icon"] { - flex-shrink: 0; - color: var(--icon-weak); - } + [data-component="icon"] { + flex-shrink: 0; + color: var(--icon-weak); + } } diff --git a/packages/ui/src/components/morph-chevron.css b/packages/ui/src/components/morph-chevron.css index c7bab9081f..f6edb3f649 100644 --- a/packages/ui/src/components/morph-chevron.css +++ b/packages/ui/src/components/morph-chevron.css @@ -1,10 +1,10 @@ [data-slot="morph-chevron-svg"] { - width: 16px; - height: 16px; - display: block; - fill: none; - stroke-width: 1.5; - stroke: currentcolor; - stroke-linecap: round; - stroke-linejoin: round; + width: 16px; + height: 16px; + display: block; + fill: none; + stroke-width: 1.5; + stroke: currentcolor; + stroke-linecap: round; + stroke-linejoin: round; } diff --git a/packages/ui/src/components/popover.css b/packages/ui/src/components/popover.css index 5a8ad10a0d..d200fe8b24 100644 --- a/packages/ui/src/components/popover.css +++ b/packages/ui/src/components/popover.css @@ -1,136 +1,132 @@ [data-slot="popover-trigger"] { - display: inline-flex; + display: inline-flex; } [data-component="popover-content"] { - z-index: 50; - min-width: 200px; - max-width: 320px; - border-radius: var(--radius-md); - background-color: var(--surface-raised-stronger-non-alpha); + z-index: 50; + min-width: 200px; + max-width: 320px; + border-radius: var(--radius-md); + background-color: var(--surface-raised-stronger-non-alpha); - border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); - background-clip: padding-box; - box-shadow: var(--shadow-md); + border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); + background-clip: padding-box; + box-shadow: var(--shadow-md); - transform-origin: var(--kb-popover-content-transform-origin); + transform-origin: var(--kb-popover-content-transform-origin); - animation: popoverContentHide var(--transition-duration) - var(--transition-easing) forwards; + animation: popoverContentHide var(--transition-duration) var(--transition-easing) forwards; - @starting-style { - animation: none; - } + @starting-style { + animation: none; + } - &[data-expanded] { - pointer-events: auto; - animation: popoverContentShow var(--transition-duration) - var(--transition-easing) forwards; - } + &[data-expanded] { + pointer-events: auto; + animation: popoverContentShow var(--transition-duration) var(--transition-easing) forwards; + } - [data-origin-top-right] { - transform-origin: top right; - } + [data-origin-top-right] { + transform-origin: top right; + } - [data-origin-top-left] { - transform-origin: top left; - } + [data-origin-top-left] { + transform-origin: top left; + } - [data-origin-bottom-right] { - transform-origin: bottom right; - } + [data-origin-bottom-right] { + transform-origin: bottom right; + } - [data-origin-bottom-left] { - transform-origin: bottom left; - } + [data-origin-bottom-left] { + transform-origin: bottom left; + } - &:focus-within { - outline: none; - } + &:focus-within { + outline: none; + } - [data-slot="popover-header"] { - display: flex; - padding: 12px; - padding-bottom: 0; - justify-content: space-between; - align-items: center; - gap: 8px; + [data-slot="popover-header"] { + display: flex; + padding: 12px; + padding-bottom: 0; + justify-content: space-between; + align-items: center; + gap: 8px; - [data-slot="popover-title"] { - flex: 1; - color: var(--text-strong); - margin: 0; + [data-slot="popover-title"] { + flex: 1; + color: var(--text-strong); + margin: 0; - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="popover-close-button"] { - flex-shrink: 0; - } - } + [data-slot="popover-close-button"] { + flex-shrink: 0; + } + } - [data-slot="popover-description"] { - padding: 0 12px; - margin: 0; - color: var(--text-base); + [data-slot="popover-description"] { + padding: 0 12px; + margin: 0; + color: var(--text-base); - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="popover-body"] { - padding: 12px; - } + [data-slot="popover-body"] { + padding: 12px; + } - [data-slot="popover-arrow"] { - fill: var(--surface-raised-stronger-non-alpha); - } + [data-slot="popover-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } } @keyframes popoverContentShow { - from { - opacity: 0; - transform: scaleY(0.95); - } - to { - opacity: 1; - transform: scaleY(1); - } + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } @keyframes popoverContentHide { - from { - opacity: 1; - transform: scaleY(1); - } - to { - opacity: 0; - transform: scaleY(0.95); - } + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } } [data-component="model-popover-content"] { - transform-origin: var(--kb-popper-content-transform-origin); - pointer-events: none; - animation: popoverContentHide var(--transition-duration) - var(--transition-easing) forwards; + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; + animation: popoverContentHide var(--transition-duration) var(--transition-easing) forwards; - @starting-style { - animation: none; - } + @starting-style { + animation: none; + } - &[data-expanded] { - pointer-events: auto; - animation: popoverContentShow var(--transition-duration) - var(--transition-easing) forwards; - } + &[data-expanded] { + pointer-events: auto; + animation: popoverContentShow var(--transition-duration) var(--transition-easing) forwards; + } } diff --git a/packages/ui/src/components/progress-circle.css b/packages/ui/src/components/progress-circle.css index e06cc3070c..d8dc4e1d05 100644 --- a/packages/ui/src/components/progress-circle.css +++ b/packages/ui/src/components/progress-circle.css @@ -1,10 +1,10 @@ [data-component="progress-circle"] { - color: inherit; + color: inherit; - [data-slot="progress-circle-background"] { - transform-origin: 50% 50%; - transform: rotate(270deg); - stroke-opacity: 0.5; - transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); - } + [data-slot="progress-circle-background"] { + transform-origin: 50% 50%; + transform: rotate(270deg); + stroke-opacity: 0.5; + transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); + } } diff --git a/packages/ui/src/components/provider-icon.css b/packages/ui/src/components/provider-icon.css index a125315b34..142c5ca7cd 100644 --- a/packages/ui/src/components/provider-icon.css +++ b/packages/ui/src/components/provider-icon.css @@ -1,5 +1,5 @@ [data-component="provider-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; + flex-shrink: 0; + width: 16px; + height: 16px; } diff --git a/packages/ui/src/components/radio-group.css b/packages/ui/src/components/radio-group.css index a6af7ca0f7..df51fc8e86 100644 --- a/packages/ui/src/components/radio-group.css +++ b/packages/ui/src/components/radio-group.css @@ -1,169 +1,156 @@ [data-component="radio-group"] { - display: flex; - flex-direction: column; - gap: calc(var(--spacing) * 2); + display: flex; + flex-direction: column; + gap: calc(var(--spacing) * 2); - [data-slot="radio-group-wrapper"] { - all: unset; - background-color: var(--surface-base); - border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); - margin: 0; - padding: 0; - position: relative; - width: fit-content; - } + [data-slot="radio-group-wrapper"] { + all: unset; + background-color: var(--surface-base); + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + margin: 0; + padding: 0; + position: relative; + width: fit-content; + } - [data-slot="radio-group-items"] { - display: inline-flex; - list-style: none; - flex-direction: row; - } + [data-slot="radio-group-items"] { + display: inline-flex; + list-style: none; + flex-direction: row; + } - [data-slot="radio-group-indicator"] { - background: var(--button-secondary-base); - border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); - content: ""; - opacity: var(--indicator-opacity, 1); - position: absolute; - transition-property: opacity, box-shadow, width, height, transform; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + [data-slot="radio-group-indicator"] { + background: var(--button-secondary-base); + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + content: ""; + opacity: var(--indicator-opacity, 1); + position: absolute; + transition-property: opacity, box-shadow, width, height, transform; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="radio-group-item"] { - position: relative; - } + [data-slot="radio-group-item"] { + position: relative; + } - /* Separator between items */ - [data-slot="radio-group-item"]:not(:first-of-type)::before { - background: var(--border-weak-base); - border-radius: var(--radius-xs); - content: ""; - inset: 6px 0; - position: absolute; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - width: 1px; - transform: translateX(-0.5px); - } + /* Separator between items */ + [data-slot="radio-group-item"]:not(:first-of-type)::before { + background: var(--border-weak-base); + border-radius: var(--radius-xs); + content: ""; + inset: 6px 0; + position: absolute; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + width: 1px; + transform: translateX(-0.5px); + } - /* Hide separator when item or previous item is checked */ - [data-slot="radio-group-item"]:has( - [data-slot="radio-group-item-input"][data-checked] - )::before, - [data-slot="radio-group-item"]:has( - [data-slot="radio-group-item-input"][data-checked] - ) - + [data-slot="radio-group-item"]::before { - opacity: 0; - } + /* Hide separator when item or previous item is checked */ + [data-slot="radio-group-item"]:has([data-slot="radio-group-item-input"][data-checked])::before, + [data-slot="radio-group-item"]:has([data-slot="radio-group-item-input"][data-checked]) + + [data-slot="radio-group-item"]::before { + opacity: 0; + } - [data-slot="radio-group-item-label"] { - color: var(--text-weak); - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - border-radius: var(--radius-md); - cursor: pointer; - display: flex; - flex-wrap: nowrap; - gap: calc(var(--spacing) * 1); - line-height: 1; - padding: 6px 12px; - place-content: center; - position: relative; - transition-property: color, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - user-select: none; - } + [data-slot="radio-group-item-label"] { + color: var(--text-weak); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + border-radius: var(--radius-md); + cursor: pointer; + display: flex; + flex-wrap: nowrap; + gap: calc(var(--spacing) * 1); + line-height: 1; + padding: 6px 12px; + place-content: center; + position: relative; + transition-property: color, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; + } - [data-slot="radio-group-item-input"] { - all: unset; - } + [data-slot="radio-group-item-input"] { + all: unset; + } - /* Checked state */ - [data-slot="radio-group-item-input"][data-checked] - + [data-slot="radio-group-item-label"] { - color: var(--text-strong); - } + /* Checked state */ + [data-slot="radio-group-item-input"][data-checked] + [data-slot="radio-group-item-label"] { + color: var(--text-strong); + } - /* Disabled state */ - [data-slot="radio-group-item-input"][data-disabled] - + [data-slot="radio-group-item-label"] { - cursor: not-allowed; - opacity: 0.5; - } + /* Disabled state */ + [data-slot="radio-group-item-input"][data-disabled] + [data-slot="radio-group-item-label"] { + cursor: not-allowed; + opacity: 0.5; + } - /* Hover state for unchecked, enabled items */ - [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) - + [data-slot="radio-group-item-label"] { - cursor: pointer; - user-select: none; - } + /* Hover state for unchecked, enabled items */ + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + [data-slot="radio-group-item-label"] { + cursor: pointer; + user-select: none; + } - [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) - + [data-slot="radio-group-item-label"]:hover { - color: var(--text-base); - } + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + + [data-slot="radio-group-item-label"]:hover { + color: var(--text-base); + } - [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) - + [data-slot="radio-group-item-label"]:active { - opacity: 0.7; - } + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + + [data-slot="radio-group-item-label"]:active { + opacity: 0.7; + } - /* Focus state */ - [data-slot="radio-group-wrapper"]:has( - [data-slot="radio-group-item-input"]:focus-visible - ) - [data-slot="radio-group-indicator"] { - box-shadow: var(--shadow-xs-border-focus); - } + /* Focus state */ + [data-slot="radio-group-wrapper"]:has([data-slot="radio-group-item-input"]:focus-visible) + [data-slot="radio-group-indicator"] { + box-shadow: var(--shadow-xs-border-focus); + } - /* Hide indicator when nothing is checked */ - [data-slot="radio-group-wrapper"]:not( - :has([data-slot="radio-group-item-input"][data-checked]) - ) - [data-slot="radio-group-indicator"] { - --indicator-opacity: 0; - } + /* Hide indicator when nothing is checked */ + [data-slot="radio-group-wrapper"]:not(:has([data-slot="radio-group-item-input"][data-checked])) + [data-slot="radio-group-indicator"] { + --indicator-opacity: 0; + } - /* Vertical orientation */ - &[aria-orientation="vertical"] [data-slot="radio-group-items"] { - flex-direction: column; - } + /* Vertical orientation */ + &[aria-orientation="vertical"] [data-slot="radio-group-items"] { + flex-direction: column; + } - &[aria-orientation="vertical"] - [data-slot="radio-group-item"]:not(:first-of-type)::before { - height: 1px; - width: auto; - inset: 0 6px; - transform: translateY(-0.5px); - } + &[aria-orientation="vertical"] [data-slot="radio-group-item"]:not(:first-of-type)::before { + height: 1px; + width: auto; + inset: 0 6px; + transform: translateY(-0.5px); + } - /* Small size variant */ - &[data-size="small"] { - [data-slot="radio-group-item-label"] { - font-size: 12px; - padding: 4px 8px; - } + /* Small size variant */ + &[data-size="small"] { + [data-slot="radio-group-item-label"] { + font-size: 12px; + padding: 4px 8px; + } - [data-slot="radio-group-item"]:not(:first-of-type)::before { - inset: 4px 0; - } + [data-slot="radio-group-item"]:not(:first-of-type)::before { + inset: 4px 0; + } - &[aria-orientation="vertical"] - [data-slot="radio-group-item"]:not(:first-of-type)::before { - inset: 0 4px; - } - } + &[aria-orientation="vertical"] [data-slot="radio-group-item"]:not(:first-of-type)::before { + inset: 0 4px; + } + } - /* Disabled root state */ - &[data-disabled] { - opacity: 0.5; - cursor: not-allowed; - } + /* Disabled root state */ + &[data-disabled] { + opacity: 0.5; + cursor: not-allowed; + } } diff --git a/packages/ui/src/components/reasoning-icon.css b/packages/ui/src/components/reasoning-icon.css index 81545cdf4f..b03f69a931 100644 --- a/packages/ui/src/components/reasoning-icon.css +++ b/packages/ui/src/components/reasoning-icon.css @@ -1,10 +1,8 @@ [data-component="reasoning-icon"] { - color: var(--icon-strong-base); + color: var(--icon-strong-base); - [data-slot="reasoning-icon-percentage"] { - transition: clip-path 200ms cubic-bezier(0.25, 0, 0.5, 1); - clip-path: inset( - calc(100% - var(--reasoning-icon-percentage) * 100%) 0 0 0 - ); - } + [data-slot="reasoning-icon-percentage"] { + transition: clip-path 200ms cubic-bezier(0.25, 0, 0.5, 1); + clip-path: inset(calc(100% - var(--reasoning-icon-percentage) * 100%) 0 0 0); + } } diff --git a/packages/ui/src/components/reasoning-icon.tsx b/packages/ui/src/components/reasoning-icon.tsx index 0ad60e9640..7bac49ffd2 100644 --- a/packages/ui/src/components/reasoning-icon.tsx +++ b/packages/ui/src/components/reasoning-icon.tsx @@ -25,8 +25,22 @@ export function ReasoningIcon(props: ReasoningIconProps) { [split.class ?? ""]: !!split.class, }} > - - + + ) } diff --git a/packages/ui/src/components/resize-handle.css b/packages/ui/src/components/resize-handle.css index 5c26b490f7..0aad9b9678 100644 --- a/packages/ui/src/components/resize-handle.css +++ b/packages/ui/src/components/resize-handle.css @@ -1,60 +1,60 @@ [data-component="resize-handle"] { - position: absolute; - z-index: 10; + position: absolute; + z-index: 10; - &::after { - content: ""; - position: absolute; - opacity: 0; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + &::after { + content: ""; + position: absolute; + opacity: 0; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - &:hover::after, - &:active::after { - opacity: 1; - } + &:hover::after, + &:active::after { + opacity: 1; + } - &[data-direction="horizontal"] { - inset-block: 0; - inset-inline-end: 0; - width: 8px; - transform: translateX(50%); - cursor: col-resize; + &[data-direction="horizontal"] { + inset-block: 0; + inset-inline-end: 0; + width: 8px; + transform: translateX(50%); + cursor: col-resize; - &[data-edge="start"] { - inset-inline-start: 0; - inset-inline-end: auto; - transform: translateX(-50%); - } + &[data-edge="start"] { + inset-inline-start: 0; + inset-inline-end: auto; + transform: translateX(-50%); + } - &::after { - width: 3px; - inset-block: 0; - inset-inline-start: 50%; - transform: translateX(-50%); - } - } + &::after { + width: 3px; + inset-block: 0; + inset-inline-start: 50%; + transform: translateX(-50%); + } + } - &[data-direction="vertical"] { - inset-inline: 0; - inset-block-start: 0; - height: 8px; - transform: translateY(-50%); - cursor: row-resize; + &[data-direction="vertical"] { + inset-inline: 0; + inset-block-start: 0; + height: 8px; + transform: translateY(-50%); + cursor: row-resize; - &[data-edge="end"] { - inset-block-start: auto; - inset-block-end: 0; - transform: translateY(50%); - } + &[data-edge="end"] { + inset-block-start: auto; + inset-block-end: 0; + transform: translateY(50%); + } - &::after { - height: 3px; - inset-inline: 0; - inset-block-start: 50%; - transform: translateY(-50%); - } - } + &::after { + height: 3px; + inset-inline: 0; + inset-block-start: 50%; + transform: translateY(-50%); + } + } } diff --git a/packages/ui/src/components/scroll-fade.css b/packages/ui/src/components/scroll-fade.css index 1e6b30d27a..ede5fabec4 100644 --- a/packages/ui/src/components/scroll-fade.css +++ b/packages/ui/src/components/scroll-fade.css @@ -1,122 +1,82 @@ [data-component="scroll-fade"] { - overflow: auto; - overscroll-behavior: contain; - scrollbar-width: none; - box-sizing: border-box; - color: inherit; - font: inherit; - -ms-overflow-style: none; + overflow: auto; + overscroll-behavior: contain; + scrollbar-width: none; + box-sizing: border-box; + color: inherit; + font: inherit; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } - &[data-direction="horizontal"] { - overflow-x: auto; - overflow-y: hidden; + &[data-direction="horizontal"] { + overflow-x: auto; + overflow-y: hidden; - /* Both fades */ - &[data-fade-start][data-fade-end] { - mask-image: linear-gradient( - to right, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - -webkit-mask-image: linear-gradient( - to right, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - } + /* Both fades */ + &[data-fade-start][data-fade-end] { + mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } - /* Only start fade */ - &[data-fade-start]:not([data-fade-end]) { - mask-image: linear-gradient( - to right, - transparent, - black var(--scroll-fade-start), - black 100% - ); - -webkit-mask-image: linear-gradient( - to right, - transparent, - black var(--scroll-fade-start), - black 100% - ); - } + /* Only start fade */ + &[data-fade-start]:not([data-fade-end]) { + mask-image: linear-gradient(to right, transparent, black var(--scroll-fade-start), black 100%); + -webkit-mask-image: linear-gradient(to right, transparent, black var(--scroll-fade-start), black 100%); + } - /* Only end fade */ - &:not([data-fade-start])[data-fade-end] { - mask-image: linear-gradient( - to right, - black 0%, - black calc(100% - var(--scroll-fade-end)), - transparent - ); - -webkit-mask-image: linear-gradient( - to right, - black 0%, - black calc(100% - var(--scroll-fade-end)), - transparent - ); - } - } + /* Only end fade */ + &:not([data-fade-start])[data-fade-end] { + mask-image: linear-gradient(to right, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); + -webkit-mask-image: linear-gradient(to right, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); + } + } - &[data-direction="vertical"] { - overflow-y: auto; - overflow-x: hidden; + &[data-direction="vertical"] { + overflow-y: auto; + overflow-x: hidden; - &[data-fade-start][data-fade-end] { - mask-image: linear-gradient( - to bottom, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - -webkit-mask-image: linear-gradient( - to bottom, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - } + &[data-fade-start][data-fade-end] { + mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } - /* Only start fade */ - &[data-fade-start]:not([data-fade-end]) { - mask-image: linear-gradient( - to bottom, - transparent, - black var(--scroll-fade-start), - black 100% - ); - -webkit-mask-image: linear-gradient( - to bottom, - transparent, - black var(--scroll-fade-start), - black 100% - ); - } + /* Only start fade */ + &[data-fade-start]:not([data-fade-end]) { + mask-image: linear-gradient(to bottom, transparent, black var(--scroll-fade-start), black 100%); + -webkit-mask-image: linear-gradient(to bottom, transparent, black var(--scroll-fade-start), black 100%); + } - /* Only end fade */ - &:not([data-fade-start])[data-fade-end] { - mask-image: linear-gradient( - to bottom, - black 0%, - black calc(100% - var(--scroll-fade-end)), - transparent - ); - -webkit-mask-image: linear-gradient( - to bottom, - black 0%, - black calc(100% - var(--scroll-fade-end)), - transparent - ); - } - } + /* Only end fade */ + &:not([data-fade-start])[data-fade-end] { + mask-image: linear-gradient(to bottom, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); + -webkit-mask-image: linear-gradient(to bottom, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); + } + } } diff --git a/packages/ui/src/components/scroll-reveal.tsx b/packages/ui/src/components/scroll-reveal.tsx index 3e9c8b362b..6e5072dc81 100644 --- a/packages/ui/src/components/scroll-reveal.tsx +++ b/packages/ui/src/components/scroll-reveal.tsx @@ -1,5 +1,5 @@ import { type JSX, onCleanup, splitProps } from "solid-js" -import { ScrollFade, type ScrollFadeProps } from './scroll-fade' +import { ScrollFade, type ScrollFadeProps } from "./scroll-fade" const SCROLL_SPEED = 60 const PAUSE_DURATION = 800 diff --git a/packages/ui/src/components/select.css b/packages/ui/src/components/select.css index aafe421aa1..5c79698835 100644 --- a/packages/ui/src/components/select.css +++ b/packages/ui/src/components/select.css @@ -1,165 +1,163 @@ [data-component="select"] { - [data-slot="select-select-trigger"] { - display: flex; - padding: 4px 8px !important; - align-items: center; - justify-content: space-between; - box-shadow: none; - transition-property: background-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + [data-slot="select-select-trigger"] { + display: flex; + padding: 4px 8px !important; + align-items: center; + justify-content: space-between; + box-shadow: none; + transition-property: background-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - [data-slot="select-select-trigger-value"] { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - [data-slot="select-select-trigger-icon"] { - width: 16px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - color: var(--icon-base); - } + [data-slot="select-select-trigger-value"] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + [data-slot="select-select-trigger-icon"] { + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: var(--icon-base); + } - &:hover, - &[data-expanded] { - &[data-variant="secondary"] { - background-color: var(--button-secondary-hover); - } - &[data-variant="ghost"] { - background-color: var(--surface-raised-base-active); - } - &[data-variant="primary"] { - background-color: var(--icon-strong-active); - } - } - &:not([data-expanded]):focus, - &:not([data-expanded]):focus-visible { - &[data-variant="secondary"] { - background-color: var(--button-secondary-base); - } - &[data-variant="ghost"] { - background-color: transparent; - } - &[data-variant="primary"] { - background-color: var(--icon-strong-base); - } - } - } + &:hover, + &[data-expanded] { + &[data-variant="secondary"] { + background-color: var(--button-secondary-hover); + } + &[data-variant="ghost"] { + background-color: var(--surface-raised-base-active); + } + &[data-variant="primary"] { + background-color: var(--icon-strong-active); + } + } + &:not([data-expanded]):focus, + &:not([data-expanded]):focus-visible { + &[data-variant="secondary"] { + background-color: var(--button-secondary-base); + } + &[data-variant="ghost"] { + background-color: transparent; + } + &[data-variant="primary"] { + background-color: var(--icon-strong-base); + } + } + } } [data-component="select-content"] { - min-width: 8rem; - max-width: 23rem; - overflow: hidden; - border-radius: var(--radius-md); - background-color: var(--surface-raised-stronger-non-alpha); - padding: 4px; - box-shadow: var(--shadow-xs-border); - z-index: 50; - transform-origin: var(--kb-popper-content-transform-origin); - pointer-events: none; + min-width: 8rem; + max-width: 23rem; + overflow: hidden; + border-radius: var(--radius-md); + background-color: var(--surface-raised-stronger-non-alpha); + padding: 4px; + box-shadow: var(--shadow-xs-border); + z-index: 50; + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; - animation: selectContentHide var(--transition-duration) - var(--transition-easing) forwards; + animation: selectContentHide var(--transition-duration) var(--transition-easing) forwards; - @starting-style { - animation: none; - } + @starting-style { + animation: none; + } - &[data-expanded] { - pointer-events: auto; - animation: selectContentShow var(--transition-duration) - var(--transition-easing) forwards; - } + &[data-expanded] { + pointer-events: auto; + animation: selectContentShow var(--transition-duration) var(--transition-easing) forwards; + } - [data-slot="select-select-content-list"] { - overflow-y: auto; - max-height: 12rem; - white-space: nowrap; - overflow-x: hidden; - display: flex; - flex-direction: column; - &:focus { - outline: none; - } - > *:not([role="presentation"]) + *:not([role="presentation"]) { - margin-top: 2px; - } - } - [data-slot="select-select-item"] { - position: relative; - display: flex; - align-items: center; - padding: 4px 8px; - gap: 12px; - border-radius: var(--radius-sm); + [data-slot="select-select-content-list"] { + overflow-y: auto; + max-height: 12rem; + white-space: nowrap; + overflow-x: hidden; + display: flex; + flex-direction: column; + &:focus { + outline: none; + } + > *:not([role="presentation"]) + *:not([role="presentation"]) { + margin-top: 2px; + } + } + [data-slot="select-select-item"] { + position: relative; + display: flex; + align-items: center; + padding: 4px 8px; + gap: 12px; + border-radius: var(--radius-sm); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - color: var(--text-strong); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); - transition-property: background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - outline: none; - user-select: none; + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + outline: none; + user-select: none; - &:hover { - background-color: var(--surface-raised-base-hover); - } - &[data-disabled] { - background-color: var(--surface-raised-base); - pointer-events: none; - } - [data-slot="select-select-item-indicator"] { - display: flex; - align-items: center; - justify-content: center; - margin-left: auto; - width: 16px; - height: 16px; - color: var(--icon-strong-base); + &:hover { + background-color: var(--surface-raised-base-hover); + } + &[data-disabled] { + background-color: var(--surface-raised-base); + pointer-events: none; + } + [data-slot="select-select-item-indicator"] { + display: flex; + align-items: center; + justify-content: center; + margin-left: auto; + width: 16px; + height: 16px; + color: var(--icon-strong-base); - svg { - color: var(--icon-strong-base); - } - } - &:focus { - outline: none; - } - &:hover { - background: var(--surface-raised-base-hover); - } - } + svg { + color: var(--icon-strong-base); + } + } + &:focus { + outline: none; + } + &:hover { + background: var(--surface-raised-base-hover); + } + } } @keyframes selectContentShow { - from { - opacity: 0; - transform: scaleY(0.95); - } - to { - opacity: 1; - transform: scaleY(1); - } + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } @keyframes selectContentHide { - from { - opacity: 1; - transform: scaleY(1); - } - to { - opacity: 0; - transform: scaleY(0.95); - } + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } } diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index d2ec356f4e..4fc88b1994 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -1,216 +1,215 @@ [data-component="session-review"] { - display: flex; - flex-direction: column; - gap: 8px; - height: 100%; - overflow-y: auto; - scrollbar-width: none; - contain: strict; - &::-webkit-scrollbar { - display: none; - } + display: flex; + flex-direction: column; + gap: 8px; + height: 100%; + overflow-y: auto; + scrollbar-width: none; + contain: strict; + &::-webkit-scrollbar { + display: none; + } - /* [data-slot="session-review-container"] { */ - /* height: 100%; */ - /* } */ + /* [data-slot="session-review-container"] { */ + /* height: 100%; */ + /* } */ - [data-slot="session-review-header"] { - position: sticky; - top: 0; - z-index: 20; - background-color: var(--background-stronger); - height: 32px; - flex-shrink: 0; - display: flex; - justify-content: space-between; - align-items: center; - align-self: stretch; - } + [data-slot="session-review-header"] { + position: sticky; + top: 0; + z-index: 20; + background-color: var(--background-stronger); + height: 32px; + flex-shrink: 0; + display: flex; + justify-content: space-between; + align-items: center; + align-self: stretch; + } - [data-slot="session-review-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-strong); - } + [data-slot="session-review-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-strong); + } - [data-slot="session-review-actions"] { - display: flex; - align-items: center; - column-gap: 16px; - padding-right: 1px; - } + [data-slot="session-review-actions"] { + display: flex; + align-items: center; + column-gap: 16px; + padding-right: 1px; + } - [data-component="sticky-accordion-header"] { - top: 40px; + [data-component="sticky-accordion-header"] { + top: 40px; - &[data-expanded]::before { - top: -40px; - } - } + &[data-expanded]::before { + top: -40px; + } + } - [data-slot="accordion-trigger"] { - background-color: var(--background-stronger) !important; - } + [data-slot="accordion-trigger"] { + background-color: var(--background-stronger) !important; + } - [data-slot="session-review-accordion-item"][data-selected] { - [data-slot="session-review-accordion-content"] { - box-shadow: var(--shadow-xs-border-select); - border-radius: var(--radius-lg); - } - } + [data-slot="session-review-accordion-item"][data-selected] { + [data-slot="session-review-accordion-content"] { + box-shadow: var(--shadow-xs-border-select); + border-radius: var(--radius-lg); + } + } - [data-slot="accordion-item"] { - [data-slot="accordion-content"] { - /* Use grid-template-rows for smooth height transition */ - display: grid; - } - } + [data-slot="accordion-item"] { + [data-slot="accordion-content"] { + /* Use grid-template-rows for smooth height transition */ + display: grid; + } + } - [data-slot="accordion-content"] { - -webkit-user-select: text; - user-select: text; - } + [data-slot="accordion-content"] { + -webkit-user-select: text; + user-select: text; + } - [data-slot="session-review-accordion-content"] { - position: relative; - overflow: hidden; - } + [data-slot="session-review-accordion-content"] { + position: relative; + overflow: hidden; + } - [data-slot="session-review-trigger-content"] { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - gap: 20px; - } + [data-slot="session-review-trigger-content"] { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + gap: 20px; + } - [data-slot="session-review-file-info"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 20px; - min-width: 0; - } + [data-slot="session-review-file-info"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 20px; + min-width: 0; + } - [data-slot="session-review-file-name-container"] { - display: flex; - flex-grow: 1; - min-width: 0; - } + [data-slot="session-review-file-name-container"] { + display: flex; + flex-grow: 1; + min-width: 0; + } - [data-slot="session-review-directory"] { - color: var(--text-base); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } + [data-slot="session-review-directory"] { + color: var(--text-base); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } - [data-slot="session-review-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } + [data-slot="session-review-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } - [data-slot="session-review-view-button"] { - display: flex; - align-items: center; - justify-content: center; - padding: 2px; - margin-left: 8px; - border: none; - background: transparent; - color: var(--text-base); - cursor: pointer; - border-radius: 4px; - opacity: 0; - transition-property: opacity, background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + [data-slot="session-review-view-button"] { + display: flex; + align-items: center; + justify-content: center; + padding: 2px; + margin-left: 8px; + border: none; + background: transparent; + color: var(--text-base); + cursor: pointer; + border-radius: 4px; + opacity: 0; + transition-property: opacity, background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &:hover { - color: var(--text-strong); - background: var(--surface-base); - } - } + &:hover { + color: var(--text-strong); + background: var(--surface-base); + } + } - [data-slot="accordion-trigger"]:hover - [data-slot="session-review-view-button"] { - opacity: 1; - } + [data-slot="accordion-trigger"]:hover [data-slot="session-review-view-button"] { + opacity: 1; + } - [data-slot="session-review-trigger-actions"] { - flex-shrink: 0; - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - } + [data-slot="session-review-trigger-actions"] { + flex-shrink: 0; + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + } - [data-slot="session-review-change"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - } + [data-slot="session-review-change"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + } - [data-slot="session-review-change"][data-type="added"] { - color: var(--icon-diff-add-base); - } + [data-slot="session-review-change"][data-type="added"] { + color: var(--icon-diff-add-base); + } - [data-slot="session-review-change"][data-type="removed"] { - color: var(--icon-diff-delete-base); - } + [data-slot="session-review-change"][data-type="removed"] { + color: var(--icon-diff-delete-base); + } - [data-slot="session-review-file-container"] { - padding: 0; - } + [data-slot="session-review-file-container"] { + padding: 0; + } - [data-slot="session-review-image-container"] { - padding: 12px; - display: flex; - justify-content: center; - background: var(--background-stronger); - } + [data-slot="session-review-image-container"] { + padding: 12px; + display: flex; + justify-content: center; + background: var(--background-stronger); + } - [data-slot="session-review-image"] { - max-width: 100%; - max-height: 60vh; - object-fit: contain; - border-radius: 8px; - border: 1px solid var(--border-weak-base); - background: var(--background-base); - } + [data-slot="session-review-image"] { + max-width: 100%; + max-height: 60vh; + object-fit: contain; + border-radius: 8px; + border: 1px solid var(--border-weak-base); + background: var(--background-base); + } - [data-slot="session-review-image-placeholder"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - color: var(--text-weak); - } + [data-slot="session-review-image-placeholder"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + color: var(--text-weak); + } - [data-slot="session-review-audio-container"] { - padding: 12px; - display: flex; - justify-content: center; - background: var(--background-stronger); - } + [data-slot="session-review-audio-container"] { + padding: 12px; + display: flex; + justify-content: center; + background: var(--background-stronger); + } - [data-slot="session-review-audio"] { - width: 100%; - max-width: 560px; - } + [data-slot="session-review-audio"] { + width: 100%; + max-width: 560px; + } - [data-slot="session-review-audio-placeholder"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - color: var(--text-weak); - } + [data-slot="session-review-audio-placeholder"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + color: var(--text-weak); + } - [data-slot="session-review-diff-wrapper"] { - position: relative; - overflow: hidden; - --line-comment-z: 5; - --line-comment-popover-z: 30; - } + [data-slot="session-review-diff-wrapper"] { + position: relative; + overflow: hidden; + --line-comment-z: 5; + --line-comment-popover-z: 30; + } } diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index db73e801e1..088b377cb7 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -1,580 +1,563 @@ [data-component="session-turn"] { - --session-turn-sticky-height: 0px; - --sticky-header-height: calc( - var(--session-title-height, 0px) + - var(--session-turn-sticky-height, 0px) + - 24px - ); - /* flex: 1; */ - height: 100%; - min-height: 0; - min-width: 0; - display: flex; - align-items: flex-start; - justify-content: flex-start; - - [data-slot="session-turn-content"] { - flex-grow: 1; - width: 100%; - height: 100%; - min-width: 0; - overflow-y: auto; - scrollbar-width: none; - } - - [data-slot="session-turn-content"]::-webkit-scrollbar { - display: none; - } - - [data-slot="session-turn-message-container"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - min-width: 0; - gap: 18px; - overflow-anchor: none; - - [data-slot="session-turn-badge"] { - display: inline-flex; - align-items: center; - padding: 2px 6px; - border-radius: 4px; - font-family: var(--font-family-mono); - font-size: var(--font-size-x-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-normal); - white-space: nowrap; - color: var(--text-base); - background: var(--surface-raised-base); - } - } - - [data-slot="session-turn-attachments"] { - width: 100%; - min-width: 0; - align-self: stretch; - } - - [data-slot="session-turn-sticky"] { - width: calc(100% + 9px); - position: sticky; - top: var(--session-title-height, 0px); - z-index: 20; - background-color: var(--background-stronger); - margin-left: -9px; - padding-left: 9px; - /* padding-bottom: 12px; */ - display: flex; - flex-direction: column; - gap: 12px; - - &::before { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - background-color: var(--background-stronger); - z-index: -1; - } - - &::after { - content: ""; - position: absolute; - top: 100%; - left: 0; - right: 0; - height: 32px; - background: linear-gradient( - to bottom, - var(--background-stronger), - transparent - ); - pointer-events: none; - } - } - - [data-slot="session-turn-message-header"] { - display: flex; - align-items: center; - align-self: stretch; - height: 32px; - } - - [data-slot="session-turn-message-content"] { - margin-top: 0; - max-width: 100%; - } - - [data-component="user-message"] [data-slot="user-message-text"] { - max-height: var(--user-message-collapsed-height, 64px); - transition: max-height 200ms cubic-bezier(0.25, 0, 0.5, 1); - } - - [data-component="user-message"][data-expanded="true"] - [data-slot="user-message-text"] { - max-height: 2000px; - } - - [data-component="user-message"][data-can-expand="true"] - [data-slot="user-message-text"] { - padding-right: 36px; - padding-bottom: 28px; - } - - [data-component="user-message"][data-can-expand="true"]:not( - [data-expanded="true"] - ) - [data-slot="user-message-text"]::after { - content: ""; - position: absolute; - left: 0; - right: 0; - height: 8px; - bottom: 0px; - background: - linear-gradient(to bottom, transparent, var(--surface-weak)), - linear-gradient(to bottom, transparent, var(--surface-weak)); - pointer-events: none; - } - - [data-component="user-message"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"] { - display: none; - position: absolute; - bottom: 6px; - right: 6px; - padding: 0; - } - - [data-component="user-message"][data-can-expand="true"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"], - [data-component="user-message"][data-expanded="true"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"] { - display: inline-flex; - align-items: center; - justify-content: center; - height: 22px; - width: 22px; - border: none; - border-radius: 6px; - background: transparent; - cursor: pointer; - color: var(--text-weak); - } - - [data-component="user-message"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"]:hover { - background: var(--surface-raised-base); - color: var(--text-base); - } - - [data-slot="session-turn-user-badges"] { - display: flex; - align-items: center; - gap: 6px; - padding-left: 16px; - } - - [data-slot="session-turn-message-title"] { - width: 100%; - font-size: var(--font-size-large); - font-weight: 500; - color: var(--text-strong); - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - white-space: nowrap; - } - - [data-slot="session-turn-message-title"] h1 { - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - white-space: nowrap; - font-size: inherit; - font-weight: inherit; - } - - [data-slot="session-turn-typewriter"] { - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - white-space: nowrap; - } - - [data-slot="session-turn-summary-section"] { - width: 100%; - display: flex; - flex-direction: column; - gap: 24px; - align-items: flex-start; - align-self: stretch; - } - - [data-slot="session-turn-summary-header"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 4px; - align-self: stretch; - - [data-slot="session-turn-response"] { - position: relative; - width: 100%; - } - - [data-slot="session-turn-response-copy-wrapper"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } - - [data-slot="session-turn-response"]:hover - [data-slot="session-turn-response-copy-wrapper"] { - opacity: 1; - } - - p { - font-size: var(--font-size-base); - line-height: var(--line-height-x-large); - } - } - - [data-slot="session-turn-summary-title"] { - font-size: 13px; - /* text-12-medium */ - font-weight: 500; - color: var(--text-weak); - } - - [data-slot="session-turn-markdown"], - [data-slot="session-turn-accordion"] [data-slot="accordion-content"] { - -webkit-user-select: text; - user-select: text; - } - - [data-slot="session-turn-markdown"] { - &[data-diffs="true"] { - font-size: 15px; - } - - &[data-fade="true"] > * { - animation: fadeUp 0.4s ease-out forwards; - opacity: 0; - - &:nth-child(1) { - animation-delay: 0.1s; - } - - &:nth-child(2) { - animation-delay: 0.2s; - } - - &:nth-child(3) { - animation-delay: 0.3s; - } - - &:nth-child(4) { - animation-delay: 0.4s; - } - - &:nth-child(5) { - animation-delay: 0.5s; - } - - &:nth-child(6) { - animation-delay: 0.6s; - } - - &:nth-child(7) { - animation-delay: 0.7s; - } - - &:nth-child(8) { - animation-delay: 0.8s; - } - - &:nth-child(9) { - animation-delay: 0.9s; - } - - &:nth-child(10) { - animation-delay: 1s; - } - - &:nth-child(11) { - animation-delay: 1.1s; - } - - &:nth-child(12) { - animation-delay: 1.2s; - } - - &:nth-child(13) { - animation-delay: 1.3s; - } - - &:nth-child(14) { - animation-delay: 1.4s; - } - - &:nth-child(15) { - animation-delay: 1.5s; - } - - &:nth-child(16) { - animation-delay: 1.6s; - } - - &:nth-child(17) { - animation-delay: 1.7s; - } - - &:nth-child(18) { - animation-delay: 1.8s; - } - - &:nth-child(19) { - animation-delay: 1.9s; - } - - &:nth-child(20) { - animation-delay: 2s; - } - - &:nth-child(21) { - animation-delay: 2.1s; - } - - &:nth-child(22) { - animation-delay: 2.2s; - } - - &:nth-child(23) { - animation-delay: 2.3s; - } - - &:nth-child(24) { - animation-delay: 2.4s; - } - - &:nth-child(25) { - animation-delay: 2.5s; - } - - &:nth-child(26) { - animation-delay: 2.6s; - } - - &:nth-child(27) { - animation-delay: 2.7s; - } - - &:nth-child(28) { - animation-delay: 2.8s; - } - - &:nth-child(29) { - animation-delay: 2.9s; - } - - &:nth-child(30) { - animation-delay: 3s; - } - } - } - - [data-slot="session-turn-summary-section"] { - position: relative; - - [data-slot="session-turn-summary-copy"] { - position: absolute; - top: 0; - right: 0; - opacity: 0; - transition: opacity 0.15s ease; - } - - &:hover [data-slot="session-turn-summary-copy"] { - opacity: 1; - } - } - - [data-slot="session-turn-accordion"] { - width: 100%; - } - - [data-component="sticky-accordion-header"] { - top: var(--sticky-header-height, 0px); - - &[data-expanded]::before { - top: calc(-1 * var(--sticky-header-height, 0px)); - } - } - - [data-slot="session-turn-accordion-trigger-content"] { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - gap: 20px; - - [data-expandable="false"] { - pointer-events: none; - } - } - - [data-slot="session-turn-file-info"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 20px; - min-width: 0; - } - - [data-slot="session-turn-file-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; - } - - [data-slot="session-turn-file-path"] { - display: flex; - flex-grow: 1; - min-width: 0; - } - - [data-slot="session-turn-directory"] { - color: var(--text-base); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } - - [data-slot="session-turn-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } - - [data-slot="session-turn-accordion-actions"] { - flex-shrink: 0; - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - color: var(--icon-base); - } - - [data-slot="session-turn-accordion-content"] { - max-height: 240px; - /* max-h-60 */ - overflow-y: auto; - scrollbar-width: none; - } - - [data-slot="session-turn-accordion-content"]::-webkit-scrollbar { - display: none; - } - - [data-slot="session-turn-response-section"] { - width: calc(100% + 9px); - min-width: 0; - margin-left: -9px; - padding-left: 9px; - } - - [data-slot="session-turn-collapsible"] { - gap: 32px; - overflow: visible; - } - - [data-slot="session-turn-collapsible-trigger-content"] { - max-width: 100%; - display: flex; - align-items: center; - gap: 8px; - color: var(--text-weak); - - [data-slot="session-turn-trigger-icon"] { - color: var(--icon-base); - } - - [data-component="spinner"] { - width: 12px; - height: 12px; - margin-right: 4px; - } - - [data-component="icon"] { - width: 14px; - height: 14px; - } - } - - [data-slot="session-turn-retry-message"] { - font-weight: 500; - color: var(--syntax-critical); - } - - [data-slot="session-turn-retry-seconds"] { - color: var(--text-weak); - } - - [data-slot="session-turn-retry-attempt"] { - color: var(--text-weak); - } - - [data-slot="session-turn-status-text"] { - overflow: hidden; - text-overflow: ellipsis; - } - - [data-slot="session-turn-details-text"] { - font-size: 13px; - /* text-12-medium */ - font-weight: 500; - } - - .error-card { - color: var(--text-on-critical-base); - max-height: 240px; - overflow-y: auto; - } - - [data-slot="session-turn-collapsible-content-inner"] { - width: 100%; - min-width: 0; - display: flex; - flex-direction: column; - align-self: stretch; - gap: 12px; - margin-left: 12px; - padding-left: 12px; - padding-right: 12px; - border-left: 1px solid var(--border-base); - - > :first-child > [data-component="markdown"]:first-child { - margin-top: 0; - } - } - - [data-slot="session-turn-permission-parts"] { - width: 100%; - min-width: 0; - display: flex; - flex-direction: column; - gap: 12px; - } + --session-turn-sticky-height: 0px; + --sticky-header-height: calc(var(--session-title-height, 0px) + var(--session-turn-sticky-height, 0px) + 24px); + /* flex: 1; */ + height: 100%; + min-height: 0; + min-width: 0; + display: flex; + align-items: flex-start; + justify-content: flex-start; + + [data-slot="session-turn-content"] { + flex-grow: 1; + width: 100%; + height: 100%; + min-width: 0; + overflow-y: auto; + scrollbar-width: none; + } + + [data-slot="session-turn-content"]::-webkit-scrollbar { + display: none; + } + + [data-slot="session-turn-message-container"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + min-width: 0; + gap: 18px; + overflow-anchor: none; + + [data-slot="session-turn-badge"] { + display: inline-flex; + align-items: center; + padding: 2px 6px; + border-radius: 4px; + font-family: var(--font-family-mono); + font-size: var(--font-size-x-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-normal); + white-space: nowrap; + color: var(--text-base); + background: var(--surface-raised-base); + } + } + + [data-slot="session-turn-attachments"] { + width: 100%; + min-width: 0; + align-self: stretch; + } + + [data-slot="session-turn-sticky"] { + width: calc(100% + 9px); + position: sticky; + top: var(--session-title-height, 0px); + z-index: 20; + background-color: var(--background-stronger); + margin-left: -9px; + padding-left: 9px; + /* padding-bottom: 12px; */ + display: flex; + flex-direction: column; + gap: 12px; + + &::before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: var(--background-stronger); + z-index: -1; + } + + &::after { + content: ""; + position: absolute; + top: 100%; + left: 0; + right: 0; + height: 32px; + background: linear-gradient(to bottom, var(--background-stronger), transparent); + pointer-events: none; + } + } + + [data-slot="session-turn-message-header"] { + display: flex; + align-items: center; + align-self: stretch; + height: 32px; + } + + [data-slot="session-turn-message-content"] { + margin-top: 0; + max-width: 100%; + } + + [data-component="user-message"] [data-slot="user-message-text"] { + max-height: var(--user-message-collapsed-height, 64px); + transition: max-height 200ms cubic-bezier(0.25, 0, 0.5, 1); + } + + [data-component="user-message"][data-expanded="true"] [data-slot="user-message-text"] { + max-height: 2000px; + } + + [data-component="user-message"][data-can-expand="true"] [data-slot="user-message-text"] { + padding-right: 36px; + padding-bottom: 28px; + } + + [data-component="user-message"][data-can-expand="true"]:not([data-expanded="true"]) + [data-slot="user-message-text"]::after { + content: ""; + position: absolute; + left: 0; + right: 0; + height: 8px; + bottom: 0px; + background: + linear-gradient(to bottom, transparent, var(--surface-weak)), + linear-gradient(to bottom, transparent, var(--surface-weak)); + pointer-events: none; + } + + [data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"] { + display: none; + position: absolute; + bottom: 6px; + right: 6px; + padding: 0; + } + + [data-component="user-message"][data-can-expand="true"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"], + [data-component="user-message"][data-expanded="true"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"] { + display: inline-flex; + align-items: center; + justify-content: center; + height: 22px; + width: 22px; + border: none; + border-radius: 6px; + background: transparent; + cursor: pointer; + color: var(--text-weak); + } + + [data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"]:hover { + background: var(--surface-raised-base); + color: var(--text-base); + } + + [data-slot="session-turn-user-badges"] { + display: flex; + align-items: center; + gap: 6px; + padding-left: 16px; + } + + [data-slot="session-turn-message-title"] { + width: 100%; + font-size: var(--font-size-large); + font-weight: 500; + color: var(--text-strong); + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + white-space: nowrap; + } + + [data-slot="session-turn-message-title"] h1 { + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + white-space: nowrap; + font-size: inherit; + font-weight: inherit; + } + + [data-slot="session-turn-typewriter"] { + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + white-space: nowrap; + } + + [data-slot="session-turn-summary-section"] { + width: 100%; + display: flex; + flex-direction: column; + gap: 24px; + align-items: flex-start; + align-self: stretch; + } + + [data-slot="session-turn-summary-header"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; + align-self: stretch; + + [data-slot="session-turn-response"] { + position: relative; + width: 100%; + } + + [data-slot="session-turn-response-copy-wrapper"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } + + [data-slot="session-turn-response"]:hover [data-slot="session-turn-response-copy-wrapper"] { + opacity: 1; + } + + p { + font-size: var(--font-size-base); + line-height: var(--line-height-x-large); + } + } + + [data-slot="session-turn-summary-title"] { + font-size: 13px; + /* text-12-medium */ + font-weight: 500; + color: var(--text-weak); + } + + [data-slot="session-turn-markdown"], + [data-slot="session-turn-accordion"] [data-slot="accordion-content"] { + -webkit-user-select: text; + user-select: text; + } + + [data-slot="session-turn-markdown"] { + &[data-diffs="true"] { + font-size: 15px; + } + + &[data-fade="true"] > * { + animation: fadeUp 0.4s ease-out forwards; + opacity: 0; + + &:nth-child(1) { + animation-delay: 0.1s; + } + + &:nth-child(2) { + animation-delay: 0.2s; + } + + &:nth-child(3) { + animation-delay: 0.3s; + } + + &:nth-child(4) { + animation-delay: 0.4s; + } + + &:nth-child(5) { + animation-delay: 0.5s; + } + + &:nth-child(6) { + animation-delay: 0.6s; + } + + &:nth-child(7) { + animation-delay: 0.7s; + } + + &:nth-child(8) { + animation-delay: 0.8s; + } + + &:nth-child(9) { + animation-delay: 0.9s; + } + + &:nth-child(10) { + animation-delay: 1s; + } + + &:nth-child(11) { + animation-delay: 1.1s; + } + + &:nth-child(12) { + animation-delay: 1.2s; + } + + &:nth-child(13) { + animation-delay: 1.3s; + } + + &:nth-child(14) { + animation-delay: 1.4s; + } + + &:nth-child(15) { + animation-delay: 1.5s; + } + + &:nth-child(16) { + animation-delay: 1.6s; + } + + &:nth-child(17) { + animation-delay: 1.7s; + } + + &:nth-child(18) { + animation-delay: 1.8s; + } + + &:nth-child(19) { + animation-delay: 1.9s; + } + + &:nth-child(20) { + animation-delay: 2s; + } + + &:nth-child(21) { + animation-delay: 2.1s; + } + + &:nth-child(22) { + animation-delay: 2.2s; + } + + &:nth-child(23) { + animation-delay: 2.3s; + } + + &:nth-child(24) { + animation-delay: 2.4s; + } + + &:nth-child(25) { + animation-delay: 2.5s; + } + + &:nth-child(26) { + animation-delay: 2.6s; + } + + &:nth-child(27) { + animation-delay: 2.7s; + } + + &:nth-child(28) { + animation-delay: 2.8s; + } + + &:nth-child(29) { + animation-delay: 2.9s; + } + + &:nth-child(30) { + animation-delay: 3s; + } + } + } + + [data-slot="session-turn-summary-section"] { + position: relative; + + [data-slot="session-turn-summary-copy"] { + position: absolute; + top: 0; + right: 0; + opacity: 0; + transition: opacity 0.15s ease; + } + + &:hover [data-slot="session-turn-summary-copy"] { + opacity: 1; + } + } + + [data-slot="session-turn-accordion"] { + width: 100%; + } + + [data-component="sticky-accordion-header"] { + top: var(--sticky-header-height, 0px); + + &[data-expanded]::before { + top: calc(-1 * var(--sticky-header-height, 0px)); + } + } + + [data-slot="session-turn-accordion-trigger-content"] { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + gap: 20px; + + [data-expandable="false"] { + pointer-events: none; + } + } + + [data-slot="session-turn-file-info"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 20px; + min-width: 0; + } + + [data-slot="session-turn-file-icon"] { + flex-shrink: 0; + width: 16px; + height: 16px; + } + + [data-slot="session-turn-file-path"] { + display: flex; + flex-grow: 1; + min-width: 0; + } + + [data-slot="session-turn-directory"] { + color: var(--text-base); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } + + [data-slot="session-turn-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } + + [data-slot="session-turn-accordion-actions"] { + flex-shrink: 0; + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + color: var(--icon-base); + } + + [data-slot="session-turn-accordion-content"] { + max-height: 240px; + /* max-h-60 */ + overflow-y: auto; + scrollbar-width: none; + } + + [data-slot="session-turn-accordion-content"]::-webkit-scrollbar { + display: none; + } + + [data-slot="session-turn-response-section"] { + width: calc(100% + 9px); + min-width: 0; + margin-left: -9px; + padding-left: 9px; + } + + [data-slot="session-turn-collapsible"] { + gap: 32px; + overflow: visible; + } + + [data-slot="session-turn-collapsible-trigger-content"] { + max-width: 100%; + display: flex; + align-items: center; + gap: 8px; + color: var(--text-weak); + + [data-slot="session-turn-trigger-icon"] { + color: var(--icon-base); + } + + [data-component="spinner"] { + width: 12px; + height: 12px; + margin-right: 4px; + } + + [data-component="icon"] { + width: 14px; + height: 14px; + } + } + + [data-slot="session-turn-retry-message"] { + font-weight: 500; + color: var(--syntax-critical); + } + + [data-slot="session-turn-retry-seconds"] { + color: var(--text-weak); + } + + [data-slot="session-turn-retry-attempt"] { + color: var(--text-weak); + } + + [data-slot="session-turn-status-text"] { + overflow: hidden; + text-overflow: ellipsis; + } + + [data-slot="session-turn-details-text"] { + font-size: 13px; + /* text-12-medium */ + font-weight: 500; + } + + .error-card { + color: var(--text-on-critical-base); + max-height: 240px; + overflow-y: auto; + } + + [data-slot="session-turn-collapsible-content-inner"] { + width: 100%; + min-width: 0; + display: flex; + flex-direction: column; + align-self: stretch; + gap: 12px; + margin-left: 12px; + padding-left: 12px; + padding-right: 12px; + border-left: 1px solid var(--border-base); + + > :first-child > [data-component="markdown"]:first-child { + margin-top: 0; + } + } + + [data-slot="session-turn-permission-parts"] { + width: 100%; + min-width: 0; + display: flex; + flex-direction: column; + gap: 12px; + } } diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index af06757f2f..3f176db702 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -553,7 +553,7 @@ export function SessionTurn( data-slot="session-turn-collapsible-trigger-content" variant="ghost" size="small" - onClick={props.onStepsExpandedToggle ?? (() => { })} + onClick={props.onStepsExpandedToggle ?? (() => {})} aria-expanded={props.stepsExpanded} > diff --git a/packages/ui/src/components/spinner.css b/packages/ui/src/components/spinner.css index 928a21c5ef..2ca474dc3c 100644 --- a/packages/ui/src/components/spinner.css +++ b/packages/ui/src/components/spinner.css @@ -1,6 +1,6 @@ [data-component="spinner"] { - color: inherit; - flex-shrink: 0; - width: 18px; - aspect-ratio: 1; + color: inherit; + flex-shrink: 0; + width: 18px; + aspect-ratio: 1; } diff --git a/packages/ui/src/components/sticky-accordion-header.css b/packages/ui/src/components/sticky-accordion-header.css index acf9eb703b..0fbc354fbe 100644 --- a/packages/ui/src/components/sticky-accordion-header.css +++ b/packages/ui/src/components/sticky-accordion-header.css @@ -1,16 +1,16 @@ [data-component="sticky-accordion-header"] { - position: sticky; - top: 0px; + position: sticky; + top: 0px; - &[data-expanded] { - z-index: 10; + &[data-expanded] { + z-index: 10; - &::before { - content: ""; - z-index: -10; - position: absolute; - inset: 0; - background-color: var(--background-stronger); - } - } + &::before { + content: ""; + z-index: -10; + position: absolute; + inset: 0; + background-color: var(--background-stronger); + } + } } diff --git a/packages/ui/src/components/switch.css b/packages/ui/src/components/switch.css index 4951e59989..9ea722760a 100644 --- a/packages/ui/src/components/switch.css +++ b/packages/ui/src/components/switch.css @@ -1,133 +1,132 @@ [data-component="switch"] { - position: relative; - display: flex; - align-items: center; - gap: 8px; - cursor: default; + position: relative; + display: flex; + align-items: center; + gap: 8px; + cursor: default; - [data-slot="switch-input"] { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } + [data-slot="switch-input"] { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } - [data-slot="switch-control"] { - display: inline-flex; - align-items: center; - width: 28px; - height: 16px; - flex-shrink: 0; - border-radius: 3px; - border: 1px solid var(--border-weak-base); - background: var(--surface-base); - transition-property: background-color, border-color, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + [data-slot="switch-control"] { + display: inline-flex; + align-items: center; + width: 28px; + height: 16px; + flex-shrink: 0; + border-radius: 3px; + border: 1px solid var(--border-weak-base); + background: var(--surface-base); + transition-property: background-color, border-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="switch-thumb"] { - width: 14px; - height: 14px; - box-sizing: content-box; + [data-slot="switch-thumb"] { + width: 14px; + height: 14px; + box-sizing: content-box; - border-radius: 2px; - border: 1px solid var(--border-base); - background: var(--icon-invert-base); + border-radius: 2px; + border: 1px solid var(--border-base); + background: var(--icon-invert-base); - /* shadows/shadow-xs */ - box-shadow: - 0 1px 2px -1px rgba(19, 16, 16, 0.04), - 0 1px 2px 0 rgba(19, 16, 16, 0.06), - 0 1px 3px 0 rgba(19, 16, 16, 0.08); + /* shadows/shadow-xs */ + box-shadow: + 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), + 0 1px 3px 0 rgba(19, 16, 16, 0.08); - transform: translateX(-1px); - transition-property: transform, background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } + transform: translateX(-1px); + transition-property: transform, background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } - [data-slot="switch-label"] { - user-select: none; - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="switch-label"] { + user-select: none; + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="switch-description"] { - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="switch-description"] { + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="switch-error"] { - color: var(--text-error); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } + [data-slot="switch-error"] { + color: var(--text-error); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } - &:hover:not([data-disabled], [data-readonly]) [data-slot="switch-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &:hover:not([data-disabled], [data-readonly]) [data-slot="switch-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &:focus-within:not([data-readonly]) [data-slot="switch-control"] { - border-color: var(--border-focus); - box-shadow: 0 0 0 2px var(--surface-focus); - } + &:focus-within:not([data-readonly]) [data-slot="switch-control"] { + border-color: var(--border-focus); + box-shadow: 0 0 0 2px var(--surface-focus); + } - &[data-checked] [data-slot="switch-control"] { - box-sizing: border-box; - border-color: var(--icon-strong-base); - background-color: var(--icon-strong-base); - } + &[data-checked] [data-slot="switch-control"] { + box-sizing: border-box; + border-color: var(--icon-strong-base); + background-color: var(--icon-strong-base); + } - &[data-checked] [data-slot="switch-thumb"] { - border: none; - transform: translateX(12px); - background-color: var(--icon-invert-base); - } + &[data-checked] [data-slot="switch-thumb"] { + border: none; + transform: translateX(12px); + background-color: var(--icon-invert-base); + } - &[data-checked]:hover:not([data-disabled], [data-readonly]) - [data-slot="switch-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } + &[data-checked]:hover:not([data-disabled], [data-readonly]) [data-slot="switch-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } - &[data-disabled] { - cursor: not-allowed; - } + &[data-disabled] { + cursor: not-allowed; + } - &[data-disabled] [data-slot="switch-control"] { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - } + &[data-disabled] [data-slot="switch-control"] { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + } - &[data-disabled] [data-slot="switch-thumb"] { - background-color: var(--icon-disabled); - } + &[data-disabled] [data-slot="switch-thumb"] { + background-color: var(--icon-disabled); + } - &[data-invalid] [data-slot="switch-control"] { - border-color: var(--border-error); - } + &[data-invalid] [data-slot="switch-control"] { + border-color: var(--border-error); + } - &[data-readonly] { - cursor: default; - pointer-events: none; - } + &[data-readonly] { + cursor: default; + pointer-events: none; + } } diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css index c7829f7224..dab07dab91 100644 --- a/packages/ui/src/components/tabs.css +++ b/packages/ui/src/components/tabs.css @@ -1,454 +1,454 @@ [data-component="tabs"] { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - background-color: var(--background-stronger); - overflow: clip; - - [data-slot="tabs-list"] { - height: 48px; - width: 100%; - position: relative; - display: flex; - align-items: center; - overflow-x: auto; - - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } - - /* After element to fill remaining space */ - &::after { - content: ""; - display: block; - flex-grow: 1; - height: 100%; - border-bottom: 1px solid var(--border-weak-base); - background-color: var(--background-base); - } - - &:empty::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - position: relative; - height: 100%; - display: flex; - align-items: center; - gap: 12px; - color: var(--text-base); - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - - white-space: nowrap; - flex-shrink: 0; - max-width: 280px; - border-bottom: 1px solid var(--border-weak-base); - border-right: 1px solid var(--border-weak-base); - background-color: var(--background-base); - transition-property: background-color, border-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - - [data-slot="tabs-trigger"] { - display: flex; - align-items: center; - justify-content: center; - padding: 14px 24px 14px 12px; - outline: none; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - - &:focus-visible { - outline: none; - box-shadow: none; - } - } - - [data-slot="tabs-trigger-close-button"] { - display: flex; - align-items: center; - justify-content: center; - } - - [data-component="icon-button"] { - margin: -0.25rem; - } - - &:disabled { - pointer-events: none; - color: var(--text-weaker); - } - &:focus-visible { - outline: none; - box-shadow: none; - } - &:has([data-hidden]) { - [data-slot="tabs-trigger-close-button"] { - opacity: 0; - } - - &:hover { - [data-slot="tabs-trigger-close-button"] { - opacity: 1; - } - } - } - &:has([data-selected]) { - color: var(--text-strong); - background-color: transparent; - border-bottom-color: transparent; - [data-slot="tabs-trigger-close-button"] { - opacity: 1; - } - } - &:hover:not(:disabled):not([data-selected]) { - color: var(--text-strong); - } - &:has([data-slot="tabs-trigger-close-button"]) { - padding-right: 12px; - - [data-slot="tabs-trigger"] { - padding-right: 0; - } - } - } - - [data-slot="tabs-content"] { - overflow-y: auto; - flex: 1; - - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } - - &:focus-visible { - outline: none; - } - } - - &[data-variant="alt"] { - [data-slot="tabs-list"] { - padding-left: 24px; - padding-right: 24px; - gap: 12px; - border-bottom: 1px solid var(--border-weak-base); - background-color: transparent; - - &::after { - border: none; - background-color: transparent; - } - &:empty::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - border: none; - color: var(--text-base); - background-color: transparent; - border-bottom-width: 2px; - border-bottom-style: solid; - border-bottom-color: transparent; - gap: 4px; - - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); - - [data-slot="tabs-trigger"] { - height: 100%; - padding: 4px; - background-color: transparent; - border-bottom-width: 2px; - border-bottom-color: transparent; - } - - [data-slot="tabs-trigger-close-button"] { - display: flex; - align-items: center; - justify-content: center; - } - - [data-component="icon-button"] { - width: 16px; - height: 16px; - margin: 0; - } - - &:has([data-selected]) { - color: var(--text-strong); - background-color: transparent; - border-bottom-color: var(--icon-strong-base); - } - - &:hover:not(:disabled):not([data-selected]) { - color: var(--text-strong); - } - - &:has([data-slot="tabs-trigger-close-button"]) { - padding-right: 0; - [data-slot="tabs-trigger"] { - padding-right: 0; - } - } - } - - /* [data-slot="tabs-content"] { */ - /* } */ - } - - &[data-variant="pill"][data-orientation="horizontal"] { - background-color: transparent; - - [data-slot="tabs-list"] { - height: auto; - padding: 6px 0; - gap: 4px; - background-color: var(--background-base); - - &::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - height: 32px; - border: none; - border-radius: var(--radius-sm); - background-color: transparent; - gap: 0; - - /* text-13-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - - [data-slot="tabs-trigger"] { - height: 100%; - width: 100%; - padding: 0 12px; - background-color: transparent; - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - color: var(--text-strong); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-active); - color: var(--text-strong); - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - } - } - } - - &[data-variant="pill"][data-orientation="horizontal"][data-scope="filetree"] { - [data-slot="tabs-list"] { - height: 48px; - padding-inline: 12px; - gap: 8px; - align-items: center; - } - - [data-slot="tabs-trigger-wrapper"] { - height: 26px; - border-radius: 6px; - color: var(--text-weak); - - &:not(:has([data-selected])):hover:not(:disabled) { - color: var(--text-base); - } - - &:has([data-selected]) { - color: var(--text-strong); - } - } - } - - &[data-orientation="vertical"] { - flex-direction: row; - - [data-slot="tabs-list"] { - flex-direction: column; - width: auto; - height: 100%; - overflow-x: hidden; - overflow-y: auto; - padding: 8px; - gap: 4px; - background-color: var(--background-base); - border-right: 1px solid var(--border-weak-base); - - &::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - width: 100%; - height: 32px; - border: none; - border-radius: 8px; - background-color: transparent; - - [data-slot="tabs-trigger"] { - height: 100%; - padding: 0 8px; - gap: 8px; - justify-content: flex-start; - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-active); - color: var(--text-strong); - } - } - - [data-slot="tabs-content"] { - overflow-x: auto; - overflow-y: auto; - } - - &[data-variant="alt"] { - [data-slot="tabs-list"] { - padding: 8px; - gap: 4px; - border: none; - - &::after { - display: none; - } - } - - [data-slot="tabs-trigger-wrapper"] { - height: 32px; - border: none; - border-radius: 8px; - - [data-slot="tabs-trigger"] { - border: none; - padding: 0 8px; - gap: 8px; - justify-content: flex-start; - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-hover); - color: var(--text-strong); - } - } - } - - &[data-variant="settings"] { - [data-slot="tabs-list"] { - width: 150px; - min-width: 150px; - - @media (min-width: 640px) { - width: 200px; - min-width: 200px; - } - padding: 12px; - gap: 0; - background-color: var(--background-base); - border-right: 1px solid var(--border-weak-base); - - &::after { - display: none; - } - } - - [data-slot="tabs-section-title"] { - width: 100%; - padding: 0 0 0 4px; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - color: var(--text-weak); - } - - [data-slot="tabs-trigger-wrapper"] { - height: 32px; - border: none; - border-radius: var(--radius-md); - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - - [data-slot="tabs-trigger"] { - border: none; - padding: 0 8px; - gap: 12px; - justify-content: flex-start; - width: 100%; - height: 100%; - } - - [data-component="icon"] { - color: var(--icon-base); - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - - &:has([data-selected]) { - background-color: var(--surface-raised-base-active); - color: var(--text-strong); - - [data-component="icon"] { - color: var(--icon-strong-base); - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - } - } - - [data-slot="tabs-content"] { - background-color: var(--surface-raised-stronger-non-alpha); - } - } - } + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background-color: var(--background-stronger); + overflow: clip; + + [data-slot="tabs-list"] { + height: 48px; + width: 100%; + position: relative; + display: flex; + align-items: center; + overflow-x: auto; + + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + + /* After element to fill remaining space */ + &::after { + content: ""; + display: block; + flex-grow: 1; + height: 100%; + border-bottom: 1px solid var(--border-weak-base); + background-color: var(--background-base); + } + + &:empty::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + position: relative; + height: 100%; + display: flex; + align-items: center; + gap: 12px; + color: var(--text-base); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + + white-space: nowrap; + flex-shrink: 0; + max-width: 280px; + border-bottom: 1px solid var(--border-weak-base); + border-right: 1px solid var(--border-weak-base); + background-color: var(--background-base); + transition-property: background-color, border-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + + [data-slot="tabs-trigger"] { + display: flex; + align-items: center; + justify-content: center; + padding: 14px 24px 14px 12px; + outline: none; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + + &:focus-visible { + outline: none; + box-shadow: none; + } + } + + [data-slot="tabs-trigger-close-button"] { + display: flex; + align-items: center; + justify-content: center; + } + + [data-component="icon-button"] { + margin: -0.25rem; + } + + &:disabled { + pointer-events: none; + color: var(--text-weaker); + } + &:focus-visible { + outline: none; + box-shadow: none; + } + &:has([data-hidden]) { + [data-slot="tabs-trigger-close-button"] { + opacity: 0; + } + + &:hover { + [data-slot="tabs-trigger-close-button"] { + opacity: 1; + } + } + } + &:has([data-selected]) { + color: var(--text-strong); + background-color: transparent; + border-bottom-color: transparent; + [data-slot="tabs-trigger-close-button"] { + opacity: 1; + } + } + &:hover:not(:disabled):not([data-selected]) { + color: var(--text-strong); + } + &:has([data-slot="tabs-trigger-close-button"]) { + padding-right: 12px; + + [data-slot="tabs-trigger"] { + padding-right: 0; + } + } + } + + [data-slot="tabs-content"] { + overflow-y: auto; + flex: 1; + + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + + &:focus-visible { + outline: none; + } + } + + &[data-variant="alt"] { + [data-slot="tabs-list"] { + padding-left: 24px; + padding-right: 24px; + gap: 12px; + border-bottom: 1px solid var(--border-weak-base); + background-color: transparent; + + &::after { + border: none; + background-color: transparent; + } + &:empty::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + border: none; + color: var(--text-base); + background-color: transparent; + border-bottom-width: 2px; + border-bottom-style: solid; + border-bottom-color: transparent; + gap: 4px; + + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); + + [data-slot="tabs-trigger"] { + height: 100%; + padding: 4px; + background-color: transparent; + border-bottom-width: 2px; + border-bottom-color: transparent; + } + + [data-slot="tabs-trigger-close-button"] { + display: flex; + align-items: center; + justify-content: center; + } + + [data-component="icon-button"] { + width: 16px; + height: 16px; + margin: 0; + } + + &:has([data-selected]) { + color: var(--text-strong); + background-color: transparent; + border-bottom-color: var(--icon-strong-base); + } + + &:hover:not(:disabled):not([data-selected]) { + color: var(--text-strong); + } + + &:has([data-slot="tabs-trigger-close-button"]) { + padding-right: 0; + [data-slot="tabs-trigger"] { + padding-right: 0; + } + } + } + + /* [data-slot="tabs-content"] { */ + /* } */ + } + + &[data-variant="pill"][data-orientation="horizontal"] { + background-color: transparent; + + [data-slot="tabs-list"] { + height: auto; + padding: 6px 0; + gap: 4px; + background-color: var(--background-base); + + &::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + height: 32px; + border: none; + border-radius: var(--radius-sm); + background-color: transparent; + gap: 0; + + /* text-13-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + + [data-slot="tabs-trigger"] { + height: 100%; + width: 100%; + padding: 0 12px; + background-color: transparent; + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + color: var(--text-strong); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-active); + color: var(--text-strong); + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + } + } + } + + &[data-variant="pill"][data-orientation="horizontal"][data-scope="filetree"] { + [data-slot="tabs-list"] { + height: 48px; + padding-inline: 12px; + gap: 8px; + align-items: center; + } + + [data-slot="tabs-trigger-wrapper"] { + height: 26px; + border-radius: 6px; + color: var(--text-weak); + + &:not(:has([data-selected])):hover:not(:disabled) { + color: var(--text-base); + } + + &:has([data-selected]) { + color: var(--text-strong); + } + } + } + + &[data-orientation="vertical"] { + flex-direction: row; + + [data-slot="tabs-list"] { + flex-direction: column; + width: auto; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + padding: 8px; + gap: 4px; + background-color: var(--background-base); + border-right: 1px solid var(--border-weak-base); + + &::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + width: 100%; + height: 32px; + border: none; + border-radius: 8px; + background-color: transparent; + + [data-slot="tabs-trigger"] { + height: 100%; + padding: 0 8px; + gap: 8px; + justify-content: flex-start; + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-active); + color: var(--text-strong); + } + } + + [data-slot="tabs-content"] { + overflow-x: auto; + overflow-y: auto; + } + + &[data-variant="alt"] { + [data-slot="tabs-list"] { + padding: 8px; + gap: 4px; + border: none; + + &::after { + display: none; + } + } + + [data-slot="tabs-trigger-wrapper"] { + height: 32px; + border: none; + border-radius: 8px; + + [data-slot="tabs-trigger"] { + border: none; + padding: 0 8px; + gap: 8px; + justify-content: flex-start; + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-hover); + color: var(--text-strong); + } + } + } + + &[data-variant="settings"] { + [data-slot="tabs-list"] { + width: 150px; + min-width: 150px; + + @media (min-width: 640px) { + width: 200px; + min-width: 200px; + } + padding: 12px; + gap: 0; + background-color: var(--background-base); + border-right: 1px solid var(--border-weak-base); + + &::after { + display: none; + } + } + + [data-slot="tabs-section-title"] { + width: 100%; + padding: 0 0 0 4px; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + color: var(--text-weak); + } + + [data-slot="tabs-trigger-wrapper"] { + height: 32px; + border: none; + border-radius: var(--radius-md); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + + [data-slot="tabs-trigger"] { + border: none; + padding: 0 8px; + gap: 12px; + justify-content: flex-start; + width: 100%; + height: 100%; + } + + [data-component="icon"] { + color: var(--icon-base); + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + + &:has([data-selected]) { + background-color: var(--surface-raised-base-active); + color: var(--text-strong); + + [data-component="icon"] { + color: var(--icon-strong-base); + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + } + } + + [data-slot="tabs-content"] { + background-color: var(--surface-raised-stronger-non-alpha); + } + } + } } diff --git a/packages/ui/src/components/tag.css b/packages/ui/src/components/tag.css index fef2c9ff20..5ffd2b9115 100644 --- a/packages/ui/src/components/tag.css +++ b/packages/ui/src/components/tag.css @@ -1,40 +1,40 @@ [data-component="tag"] { - display: inline-flex; - align-items: center; - justify-content: center; - user-select: none; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; - border-radius: var(--radius-xs); - border: 0.5px solid var(--border-weak-base); - background: var(--surface-raised-base); - color: var(--text-base); - transition-property: background-color, border-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + border-radius: var(--radius-xs); + border: 0.5px solid var(--border-weak-base); + background: var(--surface-raised-base); + color: var(--text-base); + transition-property: background-color, border-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - &[data-size="normal"] { - height: 18px; - padding: 0 6px; + &[data-size="normal"] { + height: 18px; + padding: 0 6px; - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } - &[data-size="large"] { - height: 22px; - padding: 0 8px; + &[data-size="large"] { + height: 22px; + padding: 0 8px; - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } } diff --git a/packages/ui/src/components/text-field.css b/packages/ui/src/components/text-field.css index 5568ac2dda..c94376be74 100644 --- a/packages/ui/src/components/text-field.css +++ b/packages/ui/src/components/text-field.css @@ -1,134 +1,134 @@ [data-component="input"] { - width: 100%; + width: 100%; - [data-slot="input-input"] { - width: 100%; - color: var(--text-strong); + [data-slot="input-input"] { + width: 100%; + color: var(--text-strong); - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - &:focus { - outline: none; - } + &:focus { + outline: none; + } - &::placeholder { - color: var(--text-weak); - } - } + &::placeholder { + color: var(--text-weak); + } + } - &[data-variant="normal"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; + &[data-variant="normal"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; - [data-slot="input-label"] { - color: var(--text-weak); + [data-slot="input-label"] { + color: var(--text-weak); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: 18px; /* 150% */ - letter-spacing: var(--letter-spacing-normal); - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: 18px; /* 150% */ + letter-spacing: var(--letter-spacing-normal); + } - [data-slot="input-wrapper"] { - display: flex; - align-items: start; - justify-content: space-between; - width: 100%; - padding-right: 4px; + [data-slot="input-wrapper"] { + display: flex; + align-items: start; + justify-content: space-between; + width: 100%; + padding-right: 4px; - border-radius: var(--radius-md); - border: 1px solid var(--border-weak-base); - background: var(--input-base); + border-radius: var(--radius-md); + border: 1px solid var(--border-weak-base); + background: var(--input-base); - &:focus-within:not(:has([data-readonly])) { - border-color: transparent; - /* border/shadow-xs/select */ - box-shadow: - 0 0 0 3px var(--border-weak-selected), - 0 0 0 1px var(--border-selected), - 0 1px 2px -1px rgba(19, 16, 16, 0.25), - 0 1px 2px 0 rgba(19, 16, 16, 0.08), - 0 1px 3px 0 rgba(19, 16, 16, 0.12); - } + &:focus-within:not(:has([data-readonly])) { + border-color: transparent; + /* border/shadow-xs/select */ + box-shadow: + 0 0 0 3px var(--border-weak-selected), + 0 0 0 1px var(--border-selected), + 0 1px 2px -1px rgba(19, 16, 16, 0.25), + 0 1px 2px 0 rgba(19, 16, 16, 0.08), + 0 1px 3px 0 rgba(19, 16, 16, 0.12); + } - &:has([data-invalid]) { - background: var(--surface-critical-weak); - border: 1px solid var(--border-critical-selected); - } + &:has([data-invalid]) { + background: var(--surface-critical-weak); + border: 1px solid var(--border-critical-selected); + } - &:not(:has([data-slot="input-copy-button"])) { - padding-right: 0; - } - } + &:not(:has([data-slot="input-copy-button"])) { + padding-right: 0; + } + } - [data-slot="input-input"] { - color: var(--text-strong); + [data-slot="input-input"] { + color: var(--text-strong); - display: flex; - height: 32px; - padding: 2px 12px; - align-items: center; - flex: 1; - min-width: 0; + display: flex; + height: 32px; + padding: 2px 12px; + align-items: center; + flex: 1; + min-width: 0; - background: transparent; - border: none; + background: transparent; + border: none; - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - &:focus { - outline: none; - } + &:focus { + outline: none; + } - &::placeholder { - color: var(--text-weak); - } - } + &::placeholder { + color: var(--text-weak); + } + } - textarea[data-slot="input-input"] { - height: auto; - min-height: 32px; - padding: 6px 12px; - resize: none; - } + textarea[data-slot="input-input"] { + height: auto; + min-height: 32px; + padding: 6px 12px; + resize: none; + } - [data-slot="input-copy-button"] { - flex-shrink: 0; - margin-top: 4px; - color: var(--icon-base); + [data-slot="input-copy-button"] { + flex-shrink: 0; + margin-top: 4px; + color: var(--icon-base); - &:hover { - color: var(--icon-strong-base); - } - } + &:hover { + color: var(--icon-strong-base); + } + } - [data-slot="input-error"] { - color: var(--text-on-critical-base); + [data-slot="input-error"] { + color: var(--text-on-critical-base); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: 18px; /* 150% */ - letter-spacing: var(--letter-spacing-normal); - } - } + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: 18px; /* 150% */ + letter-spacing: var(--letter-spacing-normal); + } + } } diff --git a/packages/ui/src/components/toast.css b/packages/ui/src/components/toast.css index d02896e783..1459bb1890 100644 --- a/packages/ui/src/components/toast.css +++ b/packages/ui/src/components/toast.css @@ -1,205 +1,205 @@ [data-component="toast-region"] { - position: fixed; - bottom: 48px; - right: 32px; - z-index: 1000; - display: flex; - flex-direction: column; - gap: 8px; - max-width: 400px; - width: 100%; - pointer-events: none; + position: fixed; + bottom: 48px; + right: 32px; + z-index: 1000; + display: flex; + flex-direction: column; + gap: 8px; + max-width: 400px; + width: 100%; + pointer-events: none; - [data-slot="toast-list"] { - display: flex; - flex-direction: column; - gap: 8px; - list-style: none; - margin: 0; - padding: 0; - } + [data-slot="toast-list"] { + display: flex; + flex-direction: column; + gap: 8px; + list-style: none; + margin: 0; + padding: 0; + } } [data-component="toast"] { - display: flex; - align-items: flex-start; - gap: 20px; - padding: 16px 20px; - pointer-events: auto; - transition: all 150ms ease-out; + display: flex; + align-items: flex-start; + gap: 20px; + padding: 16px 20px; + pointer-events: auto; + transition: all 150ms ease-out; - border-radius: var(--radius-lg); - border: 1px solid var(--border-weak-base); - background: var(--surface-float-base); - color: var(--text-invert-base); - box-shadow: var(--shadow-md); + border-radius: var(--radius-lg); + border: 1px solid var(--border-weak-base); + background: var(--surface-float-base); + color: var(--text-invert-base); + box-shadow: var(--shadow-md); - [data-slot="toast-inner"] { - display: flex; - align-items: flex-start; - gap: 10px; - } + [data-slot="toast-inner"] { + display: flex; + align-items: flex-start; + gap: 10px; + } - &[data-opened] { - animation: toastPopIn 150ms ease-out; - } + &[data-opened] { + animation: toastPopIn 150ms ease-out; + } - &[data-closed] { - animation: toastPopOut 100ms ease-in forwards; - } + &[data-closed] { + animation: toastPopOut 100ms ease-in forwards; + } - &[data-swipe="move"] { - transform: translateX(var(--kb-toast-swipe-move-x)); - } + &[data-swipe="move"] { + transform: translateX(var(--kb-toast-swipe-move-x)); + } - &[data-swipe="cancel"] { - transform: translateX(0); - transition: transform 200ms ease-out; - } + &[data-swipe="cancel"] { + transform: translateX(0); + transition: transform 200ms ease-out; + } - &[data-swipe="end"] { - animation: toastSwipeOut 100ms ease-out forwards; - } + &[data-swipe="end"] { + animation: toastSwipeOut 100ms ease-out forwards; + } - /* &[data-variant="success"] { */ - /* border-color: var(--color-semantic-positive); */ - /* } */ - /**/ - /* &[data-variant="error"] { */ - /* border-color: var(--color-semantic-danger); */ - /* } */ - /**/ - /* &[data-variant="loading"] { */ - /* border-color: var(--color-semantic-info); */ - /* } */ + /* &[data-variant="success"] { */ + /* border-color: var(--color-semantic-positive); */ + /* } */ + /**/ + /* &[data-variant="error"] { */ + /* border-color: var(--color-semantic-danger); */ + /* } */ + /**/ + /* &[data-variant="loading"] { */ + /* border-color: var(--color-semantic-info); */ + /* } */ - [data-slot="toast-icon"] { - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; + [data-slot="toast-icon"] { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; - [data-component="icon"] { - color: var(--text-invert-stronger); - /* color: var(--icon-invert-base); */ - } - } + [data-component="icon"] { + color: var(--text-invert-stronger); + /* color: var(--icon-invert-base); */ + } + } - [data-slot="toast-content"] { - flex: 1; - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; - } + [data-slot="toast-content"] { + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; + } - [data-slot="toast-title"] { - color: var(--text-invert-strong); + [data-slot="toast-title"] { + color: var(--text-invert-strong); - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); - margin: 0; - } + margin: 0; + } - [data-slot="toast-description"] { - color: var(--text-invert-base); - text-wrap-style: pretty; + [data-slot="toast-description"] { + color: var(--text-invert-base); + text-wrap-style: pretty; - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); - margin: 0; - } + margin: 0; + } - [data-slot="toast-actions"] { - display: flex; - gap: 16px; - margin-top: 8px; - } + [data-slot="toast-actions"] { + display: flex; + gap: 16px; + margin-top: 8px; + } - [data-slot="toast-action"] { - background: none; - border: none; - padding: 0; - cursor: pointer; + [data-slot="toast-action"] { + background: none; + border: none; + padding: 0; + cursor: pointer; - color: var(--text-invert-weak); - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); + color: var(--text-invert-weak); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); - &:hover { - text-decoration: underline; - } + &:hover { + text-decoration: underline; + } - &:first-child { - color: var(--text-invert-strong); - } - } + &:first-child { + color: var(--text-invert-strong); + } + } - [data-slot="toast-close-button"] { - flex-shrink: 0; - } + [data-slot="toast-close-button"] { + flex-shrink: 0; + } - [data-slot="toast-progress-track"] { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 3px; - background-color: var(--surface-base); - border-radius: 0 0 var(--radius-lg) var(--radius-lg); - overflow: hidden; - } + [data-slot="toast-progress-track"] { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 3px; + background-color: var(--surface-base); + border-radius: 0 0 var(--radius-lg) var(--radius-lg); + overflow: hidden; + } - [data-slot="toast-progress-fill"] { - height: 100%; - width: var(--kb-toast-progress-fill-width); - background-color: var(--color-primary); - transition: width 250ms linear; - } + [data-slot="toast-progress-fill"] { + height: 100%; + width: var(--kb-toast-progress-fill-width); + background-color: var(--color-primary); + transition: width 250ms linear; + } } @keyframes toastPopIn { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } } @keyframes toastPopOut { - from { - opacity: 1; - transform: translateY(0); - } - to { - opacity: 0; - transform: translateY(20px); - } + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(20px); + } } @keyframes toastSwipeOut { - from { - transform: translateX(var(--kb-toast-swipe-end-x)); - } - to { - transform: translateX(100%); - } + from { + transform: translateX(var(--kb-toast-swipe-end-x)); + } + to { + transform: translateX(100%); + } } diff --git a/packages/ui/src/components/tooltip.css b/packages/ui/src/components/tooltip.css index 4abeb81aa6..f02c2ca639 100644 --- a/packages/ui/src/components/tooltip.css +++ b/packages/ui/src/components/tooltip.css @@ -1,74 +1,74 @@ [data-component="tooltip-trigger"] { - display: flex; + display: flex; } [data-slot="tooltip-keybind"] { - display: flex; - align-items: center; - gap: 12px; + display: flex; + align-items: center; + gap: 12px; } [data-slot="tooltip-keybind-key"] { - color: var(--text-invert-base); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); + color: var(--text-invert-base); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); } [data-component="tooltip"] { - z-index: 1000; - max-width: 320px; - border-radius: var(--radius-sm); - background-color: var(--surface-float-base); - color: var(--text-invert-strong); - background: var(--surface-float-base); - padding: 2px 8px; - border: 1px solid var(--border-weak-base, rgba(0, 0, 0, 0.07)); + z-index: 1000; + max-width: 320px; + border-radius: var(--radius-sm); + background-color: var(--surface-float-base); + color: var(--text-invert-strong); + background: var(--surface-float-base); + padding: 2px 8px; + border: 1px solid var(--border-weak-base, rgba(0, 0, 0, 0.07)); - box-shadow: var(--shadow-md); - pointer-events: none !important; - /* transition: all 150ms ease-out; */ - /* transform: translate3d(0, 0, 0); */ - /* transform-origin: var(--kb-tooltip-content-transform-origin); */ + box-shadow: var(--shadow-md); + pointer-events: none !important; + /* transition: all 150ms ease-out; */ + /* transform: translate3d(0, 0, 0); */ + /* transform-origin: var(--kb-tooltip-content-transform-origin); */ - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &[data-expanded] { - opacity: 1; - /* transform: translate3d(0, 0, 0); */ - } + &[data-expanded] { + opacity: 1; + /* transform: translate3d(0, 0, 0); */ + } - &[data-closed]:not([data-force-open="true"]) { - opacity: 0; - } + &[data-closed]:not([data-force-open="true"]) { + opacity: 0; + } - /* &[data-placement="top"] { */ - /* &[data-closed] { */ - /* transform: translate3d(0, 4px, 0); */ - /* } */ - /* } */ - /**/ - /* &[data-placement="bottom"] { */ - /* &[data-closed] { */ - /* transform: translate3d(0, -4px, 0); */ - /* } */ - /* } */ - /**/ - /* &[data-placement="left"] { */ - /* &[data-closed] { */ - /* transform: translate3d(4px, 0, 0); */ - /* } */ - /* } */ - /**/ - /* &[data-placement="right"] { */ - /* &[data-closed] { */ - /* transform: translate3d(-4px, 0, 0); */ - /* } */ - /* } */ + /* &[data-placement="top"] { */ + /* &[data-closed] { */ + /* transform: translate3d(0, 4px, 0); */ + /* } */ + /* } */ + /**/ + /* &[data-placement="bottom"] { */ + /* &[data-closed] { */ + /* transform: translate3d(0, -4px, 0); */ + /* } */ + /* } */ + /**/ + /* &[data-placement="left"] { */ + /* &[data-closed] { */ + /* transform: translate3d(4px, 0, 0); */ + /* } */ + /* } */ + /**/ + /* &[data-placement="right"] { */ + /* &[data-closed] { */ + /* transform: translate3d(-4px, 0, 0); */ + /* } */ + /* } */ } diff --git a/packages/ui/src/components/typewriter.css b/packages/ui/src/components/typewriter.css index f99f2d8dac..e978312a9f 100644 --- a/packages/ui/src/components/typewriter.css +++ b/packages/ui/src/components/typewriter.css @@ -1,14 +1,14 @@ @keyframes blink { - 0%, - 50% { - opacity: 1; - } - 51%, - 100% { - opacity: 0; - } + 0%, + 50% { + opacity: 1; + } + 51%, + 100% { + opacity: 0; + } } .blinking-cursor { - animation: blink 1s step-end infinite; + animation: blink 1s step-end infinite; } diff --git a/packages/ui/src/context/dialog.tsx b/packages/ui/src/context/dialog.tsx index bd47b86d3f..4132125122 100644 --- a/packages/ui/src/context/dialog.tsx +++ b/packages/ui/src/context/dialog.tsx @@ -121,12 +121,16 @@ function init() { const render = (element: JSX.Element, id: string, owner: Owner) => { setRenders((renders) => ({ ...renders, [id]: element })) - show(() => element, owner, () => { - setRenders((renders) => { - const { [id]: _, ...rest } = renders - return rest - }) - }) + show( + () => element, + owner, + () => { + setRenders((renders) => { + const { [id]: _, ...rest } = renders + return rest + }) + }, + ) } const isActive = (id: string) => { diff --git a/packages/ui/src/styles/utilities.css b/packages/ui/src/styles/utilities.css index 990259acc2..82a913c883 100644 --- a/packages/ui/src/styles/utilities.css +++ b/packages/ui/src/styles/utilities.css @@ -1,174 +1,173 @@ :root { - interpolate-size: allow-keywords; + interpolate-size: allow-keywords; - /* Transition tokens */ - --transition-duration: 200ms; - --transition-easing: cubic-bezier(0.25, 0, 0.5, 1); - --transition-fast: 150ms; - --transition-slow: 300ms; + /* Transition tokens */ + --transition-duration: 200ms; + --transition-easing: cubic-bezier(0.25, 0, 0.5, 1); + --transition-fast: 150ms; + --transition-slow: 300ms; - /* Allow height transitions from 0 to auto */ - @supports (interpolate-size: allow-keywords) { - interpolate-size: allow-keywords; - } + /* Allow height transitions from 0 to auto */ + @supports (interpolate-size: allow-keywords) { + interpolate-size: allow-keywords; + } - [data-popper-positioner] { - pointer-events: none; - } + [data-popper-positioner] { + pointer-events: none; + } - /* ::selection { */ - /* background-color: color-mix(in srgb, var(--color-primary) 33%, transparent); */ - /* background-color: var(--color-primary); */ - /* color: var(--color-background); */ - /* } */ + /* ::selection { */ + /* background-color: color-mix(in srgb, var(--color-primary) 33%, transparent); */ + /* background-color: var(--color-primary); */ + /* color: var(--color-background); */ + /* } */ - ::-webkit-scrollbar-track { - background: transparent; - } + ::-webkit-scrollbar-track { + background: transparent; + } - ::-webkit-scrollbar-thumb { - background-color: var(--surface-float-base); - border-radius: var(--radius-md); - } + ::-webkit-scrollbar-thumb { + background-color: var(--surface-float-base); + border-radius: var(--radius-md); + } - * { - scrollbar-color: var(--surface-float-base) transparent; - } + * { + scrollbar-color: var(--surface-float-base) transparent; + } } .no-scrollbar { - &::-webkit-scrollbar { - display: none; - } - /* Hide scrollbar for IE, Edge and Firefox */ - & { - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; /* Firefox */ - } + &::-webkit-scrollbar { + display: none; + } + /* Hide scrollbar for IE, Edge and Firefox */ + & { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } } .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } .truncate-start { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; } .text-12-regular { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); } .text-12-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); } .text-12-mono { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-feature-settings-mono); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-mono); + font-feature-settings: var(--font-feature-settings-mono); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); } .text-14-regular { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); } .text-14-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); } .text-14-mono { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-feature-settings-mono); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 171.429% */ - letter-spacing: var(--letter-spacing-normal); + font-family: var(--font-family-mono); + font-feature-settings: var(--font-feature-settings-mono); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 171.429% */ + letter-spacing: var(--letter-spacing-normal); } .text-16-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 150% */ - letter-spacing: var(--letter-spacing-tight); + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 150% */ + letter-spacing: var(--letter-spacing-tight); } .text-20-medium { - font-family: var(--font-family-sans); - font-size: var(--font-size-x-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 120% */ - letter-spacing: var(--letter-spacing-tightest); + font-family: var(--font-family-sans); + font-size: var(--font-size-x-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 120% */ + letter-spacing: var(--letter-spacing-tightest); } /* Transition utility classes */ .transition-colors { - transition-property: background-color, border-color, color, fill, stroke; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition-property: background-color, border-color, color, fill, stroke; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } .transition-opacity { - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } .transition-transform { - transition-property: transform; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition-property: transform; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } .transition-shadow { - transition-property: box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition-property: box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } .transition-interactive { - transition-property: - background-color, border-color, color, box-shadow, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition-property: background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } From f48e2e56c95a7b96648176f1f783929dc4f33b37 Mon Sep 17 00:00:00 2001 From: Filip <34747899+neriousy@users.noreply.github.com> Date: Fri, 30 Jan 2026 19:04:02 +0100 Subject: [PATCH 07/58] test(app): change language test (#11295) --- packages/app/e2e/{ => app}/home.spec.ts | 4 +- packages/app/e2e/{ => app}/navigation.spec.ts | 4 +- packages/app/e2e/{ => app}/palette.spec.ts | 4 +- .../app/e2e/{ => app}/server-default.spec.ts | 4 +- packages/app/e2e/{ => app}/session.spec.ts | 4 +- .../e2e/{ => app}/titlebar-history.spec.ts | 4 +- .../app/e2e/{ => files}/file-open.spec.ts | 4 +- .../app/e2e/{ => files}/file-tree.spec.ts | 2 +- .../app/e2e/{ => files}/file-viewer.spec.ts | 4 +- .../app/e2e/{ => models}/model-picker.spec.ts | 4 +- .../{ => models}/models-visibility.spec.ts | 4 +- packages/app/e2e/{ => prompt}/context.spec.ts | 4 +- .../e2e/{ => prompt}/prompt-mention.spec.ts | 4 +- .../{ => prompt}/prompt-slash-open.spec.ts | 4 +- packages/app/e2e/{ => prompt}/prompt.spec.ts | 4 +- .../e2e/settings/settings-language.spec.ts | 39 +++++++++++++++++++ .../{ => settings}/settings-providers.spec.ts | 4 +- .../app/e2e/{ => settings}/settings.spec.ts | 4 +- .../sidebar-session-links.spec.ts | 32 ++------------- .../app/e2e/{ => sidebar}/sidebar.spec.ts | 4 +- .../e2e/{ => terminal}/terminal-init.spec.ts | 4 +- .../app/e2e/{ => terminal}/terminal.spec.ts | 4 +- packages/app/e2e/utils.ts | 2 + .../app/src/components/settings-general.tsx | 1 + 24 files changed, 84 insertions(+), 68 deletions(-) rename packages/app/e2e/{ => app}/home.spec.ts (88%) rename packages/app/e2e/{ => app}/navigation.spec.ts (72%) rename packages/app/e2e/{ => app}/palette.spec.ts (82%) rename packages/app/e2e/{ => app}/server-default.spec.ts (95%) rename packages/app/e2e/{ => app}/session.spec.ts (88%) rename packages/app/e2e/{ => app}/titlebar-history.spec.ts (95%) rename packages/app/e2e/{ => files}/file-open.spec.ts (89%) rename packages/app/e2e/{ => files}/file-tree.spec.ts (96%) rename packages/app/e2e/{ => files}/file-viewer.spec.ts (92%) rename packages/app/e2e/{ => models}/model-picker.spec.ts (94%) rename packages/app/e2e/{ => models}/models-visibility.spec.ts (96%) rename packages/app/e2e/{ => prompt}/context.spec.ts (93%) rename packages/app/e2e/{ => prompt}/prompt-mention.spec.ts (90%) rename packages/app/e2e/{ => prompt}/prompt-slash-open.spec.ts (87%) rename packages/app/e2e/{ => prompt}/prompt.spec.ts (95%) create mode 100644 packages/app/e2e/settings/settings-language.spec.ts rename packages/app/e2e/{ => settings}/settings-providers.spec.ts (95%) rename packages/app/e2e/{ => settings}/settings.spec.ts (94%) rename packages/app/e2e/{ => sidebar}/sidebar-session-links.spec.ts (64%) rename packages/app/e2e/{ => sidebar}/sidebar.spec.ts (88%) rename packages/app/e2e/{ => terminal}/terminal-init.spec.ts (93%) rename packages/app/e2e/{ => terminal}/terminal.spec.ts (79%) diff --git a/packages/app/e2e/home.spec.ts b/packages/app/e2e/app/home.spec.ts similarity index 88% rename from packages/app/e2e/home.spec.ts rename to packages/app/e2e/app/home.spec.ts index c6fb0e3b07..f21dc40ec2 100644 --- a/packages/app/e2e/home.spec.ts +++ b/packages/app/e2e/app/home.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { serverName } from "./utils" +import { test, expect } from "../fixtures" +import { serverName } from "../utils" test("home renders and shows core entrypoints", async ({ page }) => { await page.goto("/") diff --git a/packages/app/e2e/navigation.spec.ts b/packages/app/e2e/app/navigation.spec.ts similarity index 72% rename from packages/app/e2e/navigation.spec.ts rename to packages/app/e2e/app/navigation.spec.ts index 76923af6ed..0812ea0187 100644 --- a/packages/app/e2e/navigation.spec.ts +++ b/packages/app/e2e/app/navigation.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { dirPath, promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { dirPath, promptSelector } from "../utils" test("project route redirects to /session", async ({ page, directory, slug }) => { await page.goto(dirPath(directory)) diff --git a/packages/app/e2e/palette.spec.ts b/packages/app/e2e/app/palette.spec.ts similarity index 82% rename from packages/app/e2e/palette.spec.ts rename to packages/app/e2e/app/palette.spec.ts index 617c55ac16..264b463bb4 100644 --- a/packages/app/e2e/palette.spec.ts +++ b/packages/app/e2e/app/palette.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey } from "./utils" +import { test, expect } from "../fixtures" +import { modKey } from "../utils" test("search palette opens and closes", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/server-default.spec.ts b/packages/app/e2e/app/server-default.spec.ts similarity index 95% rename from packages/app/e2e/server-default.spec.ts rename to packages/app/e2e/app/server-default.spec.ts index b6b16f0bcc..6f44ded1a2 100644 --- a/packages/app/e2e/server-default.spec.ts +++ b/packages/app/e2e/app/server-default.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { serverName, serverUrl } from "./utils" +import { test, expect } from "../fixtures" +import { serverName, serverUrl } from "../utils" const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl" diff --git a/packages/app/e2e/session.spec.ts b/packages/app/e2e/app/session.spec.ts similarity index 88% rename from packages/app/e2e/session.spec.ts rename to packages/app/e2e/app/session.spec.ts index 19e25a4213..8d605f0c3a 100644 --- a/packages/app/e2e/session.spec.ts +++ b/packages/app/e2e/app/session.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector } from "../utils" test("can open an existing session and type into the prompt", async ({ page, sdk, gotoSession }) => { const title = `e2e smoke ${Date.now()}` diff --git a/packages/app/e2e/titlebar-history.spec.ts b/packages/app/e2e/app/titlebar-history.spec.ts similarity index 95% rename from packages/app/e2e/titlebar-history.spec.ts rename to packages/app/e2e/app/titlebar-history.spec.ts index d4aa605e6d..649e5e0dc1 100644 --- a/packages/app/e2e/titlebar-history.spec.ts +++ b/packages/app/e2e/app/titlebar-history.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey, promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { modKey, promptSelector } from "../utils" test("titlebar back/forward navigates between sessions", async ({ page, slug, sdk, gotoSession }) => { await page.setViewportSize({ width: 1400, height: 800 }) diff --git a/packages/app/e2e/file-open.spec.ts b/packages/app/e2e/files/file-open.spec.ts similarity index 89% rename from packages/app/e2e/file-open.spec.ts rename to packages/app/e2e/files/file-open.spec.ts index fb7104b6b0..e384f0b0da 100644 --- a/packages/app/e2e/file-open.spec.ts +++ b/packages/app/e2e/files/file-open.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey } from "./utils" +import { test, expect } from "../fixtures" +import { modKey } from "../utils" test("can open a file tab from the search palette", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/file-tree.spec.ts b/packages/app/e2e/files/file-tree.spec.ts similarity index 96% rename from packages/app/e2e/file-tree.spec.ts rename to packages/app/e2e/files/file-tree.spec.ts index 0b04eb2468..844da1b329 100644 --- a/packages/app/e2e/file-tree.spec.ts +++ b/packages/app/e2e/files/file-tree.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from "./fixtures" +import { test, expect } from "../fixtures" test.skip("file tree can expand folders and open a file", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/file-viewer.spec.ts b/packages/app/e2e/files/file-viewer.spec.ts similarity index 92% rename from packages/app/e2e/file-viewer.spec.ts rename to packages/app/e2e/files/file-viewer.spec.ts index 1e0f8a6f23..bed6d1d369 100644 --- a/packages/app/e2e/file-viewer.spec.ts +++ b/packages/app/e2e/files/file-viewer.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey } from "./utils" +import { test, expect } from "../fixtures" +import { modKey } from "../utils" test("smoke file viewer renders real file content", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/model-picker.spec.ts b/packages/app/e2e/models/model-picker.spec.ts similarity index 94% rename from packages/app/e2e/model-picker.spec.ts rename to packages/app/e2e/models/model-picker.spec.ts index 9e64b3dfb0..a0c70aabef 100644 --- a/packages/app/e2e/model-picker.spec.ts +++ b/packages/app/e2e/models/model-picker.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector } from "../utils" test("smoke model selection updates prompt footer", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/models-visibility.spec.ts b/packages/app/e2e/models/models-visibility.spec.ts similarity index 96% rename from packages/app/e2e/models-visibility.spec.ts rename to packages/app/e2e/models/models-visibility.spec.ts index 680ba96a31..0db7580c20 100644 --- a/packages/app/e2e/models-visibility.spec.ts +++ b/packages/app/e2e/models/models-visibility.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey, promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { modKey, promptSelector } from "../utils" test("hiding a model removes it from the model picker", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/context.spec.ts b/packages/app/e2e/prompt/context.spec.ts similarity index 93% rename from packages/app/e2e/context.spec.ts rename to packages/app/e2e/prompt/context.spec.ts index beabd2eb7d..f0f3f073ae 100644 --- a/packages/app/e2e/context.spec.ts +++ b/packages/app/e2e/prompt/context.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector } from "../utils" test("context panel can be opened from the prompt", async ({ page, sdk, gotoSession }) => { const title = `e2e smoke context ${Date.now()}` diff --git a/packages/app/e2e/prompt-mention.spec.ts b/packages/app/e2e/prompt/prompt-mention.spec.ts similarity index 90% rename from packages/app/e2e/prompt-mention.spec.ts rename to packages/app/e2e/prompt/prompt-mention.spec.ts index 113b8465f7..85acb4c28f 100644 --- a/packages/app/e2e/prompt-mention.spec.ts +++ b/packages/app/e2e/prompt/prompt-mention.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector } from "../utils" test("smoke @mention inserts file pill token", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/prompt-slash-open.spec.ts b/packages/app/e2e/prompt/prompt-slash-open.spec.ts similarity index 87% rename from packages/app/e2e/prompt-slash-open.spec.ts rename to packages/app/e2e/prompt/prompt-slash-open.spec.ts index 3c29d405c1..3e769e3305 100644 --- a/packages/app/e2e/prompt-slash-open.spec.ts +++ b/packages/app/e2e/prompt/prompt-slash-open.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector } from "../utils" test("smoke /open opens file picker dialog", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/prompt.spec.ts b/packages/app/e2e/prompt/prompt.spec.ts similarity index 95% rename from packages/app/e2e/prompt.spec.ts rename to packages/app/e2e/prompt/prompt.spec.ts index 3e5892ce8d..b58e5e296c 100644 --- a/packages/app/e2e/prompt.spec.ts +++ b/packages/app/e2e/prompt/prompt.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector } from "../utils" function sessionIDFromUrl(url: string) { const match = /\/session\/([^/?#]+)/.exec(url) diff --git a/packages/app/e2e/settings/settings-language.spec.ts b/packages/app/e2e/settings/settings-language.spec.ts new file mode 100644 index 0000000000..b2ef70bf88 --- /dev/null +++ b/packages/app/e2e/settings/settings-language.spec.ts @@ -0,0 +1,39 @@ +import { test, expect } from "../fixtures" +import { modKey, settingsLanguageSelectSelector } from "../utils" + +test("smoke changing language updates settings labels", async ({ page, gotoSession }) => { + await page.addInitScript(() => { + localStorage.setItem("opencode.global.dat:language", JSON.stringify({ locale: "en" })) + }) + + await gotoSession() + + const dialog = page.getByRole("dialog") + + await page.keyboard.press(`${modKey}+Comma`).catch(() => undefined) + + const opened = await dialog + .waitFor({ state: "visible", timeout: 3000 }) + .then(() => true) + .catch(() => false) + + if (!opened) { + await page.getByRole("button", { name: "Settings" }).first().click() + await expect(dialog).toBeVisible() + } + + const heading = dialog.getByRole("heading", { level: 2 }) + await expect(heading).toHaveText("General") + + const select = dialog.locator(settingsLanguageSelectSelector) + await expect(select).toBeVisible() + await select.locator('[data-slot="select-select-trigger"]').click() + + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Deutsch" }).click() + + await expect(heading).toHaveText("Allgemein") + + await select.locator('[data-slot="select-select-trigger"]').click() + await page.locator('[data-slot="select-select-item"]').filter({ hasText: "English" }).click() + await expect(heading).toHaveText("General") +}) diff --git a/packages/app/e2e/settings-providers.spec.ts b/packages/app/e2e/settings/settings-providers.spec.ts similarity index 95% rename from packages/app/e2e/settings-providers.spec.ts rename to packages/app/e2e/settings/settings-providers.spec.ts index 326a9fad1d..5b9325c2ab 100644 --- a/packages/app/e2e/settings-providers.spec.ts +++ b/packages/app/e2e/settings/settings-providers.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey, promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { modKey, promptSelector } from "../utils" test("smoke providers settings opens provider selector", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/settings.spec.ts b/packages/app/e2e/settings/settings.spec.ts similarity index 94% rename from packages/app/e2e/settings.spec.ts rename to packages/app/e2e/settings/settings.spec.ts index 09dc942cc9..293a4ba9aa 100644 --- a/packages/app/e2e/settings.spec.ts +++ b/packages/app/e2e/settings/settings.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey } from "./utils" +import { test, expect } from "../fixtures" +import { modKey } from "../utils" test("smoke settings dialog opens, switches tabs, closes", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/sidebar-session-links.spec.ts b/packages/app/e2e/sidebar/sidebar-session-links.spec.ts similarity index 64% rename from packages/app/e2e/sidebar-session-links.spec.ts rename to packages/app/e2e/sidebar/sidebar-session-links.spec.ts index fab64736e2..8c3f695475 100644 --- a/packages/app/e2e/sidebar-session-links.spec.ts +++ b/packages/app/e2e/sidebar/sidebar-session-links.spec.ts @@ -1,33 +1,7 @@ -import { test, expect } from "./fixtures" -import { modKey, promptSelector } from "./utils" +import { test, expect } from "../fixtures" +import { modKey, promptSelector } from "../utils" -type Locator = { - first: () => Locator - getAttribute: (name: string) => Promise - scrollIntoViewIfNeeded: () => Promise - click: () => Promise -} - -type Page = { - locator: (selector: string) => Locator - keyboard: { - press: (key: string) => Promise - } -} - -type Fixtures = { - page: Page - slug: string - sdk: { - session: { - create: (input: { title: string }) => Promise<{ data?: { id?: string } }> - delete: (input: { sessionID: string }) => Promise - } - } - gotoSession: (sessionID?: string) => Promise -} - -test("sidebar session links navigate to the selected session", async ({ page, slug, sdk, gotoSession }: Fixtures) => { +test("sidebar session links navigate to the selected session", async ({ page, slug, sdk, gotoSession }) => { const stamp = Date.now() const one = await sdk.session.create({ title: `e2e sidebar nav 1 ${stamp}` }).then((r) => r.data) diff --git a/packages/app/e2e/sidebar.spec.ts b/packages/app/e2e/sidebar/sidebar.spec.ts similarity index 88% rename from packages/app/e2e/sidebar.spec.ts rename to packages/app/e2e/sidebar/sidebar.spec.ts index 925590f510..ba58b1008f 100644 --- a/packages/app/e2e/sidebar.spec.ts +++ b/packages/app/e2e/sidebar/sidebar.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { modKey } from "./utils" +import { test, expect } from "../fixtures" +import { modKey } from "../utils" test("sidebar can be collapsed and expanded", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/terminal-init.spec.ts b/packages/app/e2e/terminal/terminal-init.spec.ts similarity index 93% rename from packages/app/e2e/terminal-init.spec.ts rename to packages/app/e2e/terminal/terminal-init.spec.ts index cfde2d0193..6faa73a751 100644 --- a/packages/app/e2e/terminal-init.spec.ts +++ b/packages/app/e2e/terminal/terminal-init.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { promptSelector, terminalSelector, terminalToggleKey } from "./utils" +import { test, expect } from "../fixtures" +import { promptSelector, terminalSelector, terminalToggleKey } from "../utils" test("smoke terminal mounts and can create a second tab", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/terminal.spec.ts b/packages/app/e2e/terminal/terminal.spec.ts similarity index 79% rename from packages/app/e2e/terminal.spec.ts rename to packages/app/e2e/terminal/terminal.spec.ts index fc558b6325..aaf5c2d75d 100644 --- a/packages/app/e2e/terminal.spec.ts +++ b/packages/app/e2e/terminal/terminal.spec.ts @@ -1,5 +1,5 @@ -import { test, expect } from "./fixtures" -import { terminalSelector, terminalToggleKey } from "./utils" +import { test, expect } from "../fixtures" +import { terminalSelector, terminalToggleKey } from "../utils" test("terminal panel can be toggled", async ({ page, gotoSession }) => { await gotoSession() diff --git a/packages/app/e2e/utils.ts b/packages/app/e2e/utils.ts index 3de488bd9c..3dec125922 100644 --- a/packages/app/e2e/utils.ts +++ b/packages/app/e2e/utils.ts @@ -14,6 +14,8 @@ export const promptSelector = '[data-component="prompt-input"]' export const terminalSelector = '[data-component="terminal"]' export const modelVariantCycleSelector = '[data-action="model-variant-cycle"]' +export const settingsLanguageSelectSelector = '[data-action="settings-language"]' + export function createSdk(directory?: string) { return createOpencodeClient({ baseUrl: serverUrl, directory, throwOnError: true }) } diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx index 054fa6ef4a..b2fb435362 100644 --- a/packages/app/src/components/settings-general.tsx +++ b/packages/app/src/components/settings-general.tsx @@ -154,6 +154,7 @@ export const SettingsGeneral: Component = () => { description={language.t("settings.general.row.language.description")} > = (props) => { e.currentTarget.value = "" }} /> -
+
@@ -2074,7 +2036,7 @@ export const PromptInput: Component = (props) => {
{language.t("prompt.action.send")} - +
@@ -2085,7 +2047,7 @@ export const PromptInput: Component = (props) => { disabled={!prompt.dirty() && !working()} icon={working() ? "stop" : "arrow-up"} variant="primary" - class="h-6 w-5.5" + class="h-6 w-4.5" aria-label={working() ? language.t("prompt.action.stop") : language.t("prompt.action.send")} /> diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index 92b060212d..1e37d8f6a2 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -64,8 +64,8 @@ export function SessionContextUsage(props: SessionContextUsageProps) { } const circle = () => ( -
- +
+
) @@ -101,7 +101,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
) } diff --git a/packages/app/src/components/settings-keybinds.tsx b/packages/app/src/components/settings-keybinds.tsx index efd18c8bd6..393da0c2ab 100644 --- a/packages/app/src/components/settings-keybinds.tsx +++ b/packages/app/src/components/settings-keybinds.tsx @@ -9,7 +9,6 @@ import fuzzysort from "fuzzysort" import { formatKeybind, parseKeybind, useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { useSettings } from "@/context/settings" -import { ScrollFade } from "@opencode-ai/ui/scroll-fade" const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) const PALETTE_ID = "command.palette" @@ -353,12 +352,7 @@ export const SettingsKeybinds: Component = () => { }) return ( - +
@@ -435,6 +429,6 @@ export const SettingsKeybinds: Component = () => {
- +
) } diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs index d16416c9f2..29ac86f29a 100644 --- a/packages/desktop/src-tauri/src/lib.rs +++ b/packages/desktop/src-tauri/src/lib.rs @@ -345,7 +345,6 @@ pub fn run() { .decorations(false); let window = window_builder.build().expect("Failed to create window"); - let _ = window.show(); #[cfg(windows)] let _ = window.create_overlay_titlebar(); diff --git a/packages/ui/src/components/accordion.css b/packages/ui/src/components/accordion.css index b310eeedb6..7bf287fe54 100644 --- a/packages/ui/src/components/accordion.css +++ b/packages/ui/src/components/accordion.css @@ -36,9 +36,7 @@ border-radius: var(--radius-md); overflow: clip; color: var(--text-strong); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: background-color 0.15s ease; /* text-12-regular */ font-family: var(--font-family-sans); @@ -60,48 +58,41 @@ } } - [data-slot="accordion-arrow"] { - flex-shrink: 0; - width: 16px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - color: var(--text-weak); - } + &[data-expanded] { + [data-slot="accordion-trigger"] { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } - [data-slot="accordion-content"] { - display: grid; - grid-template-rows: 0fr; - transition-property: grid-template-rows, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - width: 100%; - - > * { - overflow: hidden; + [data-slot="accordion-content"] { + border: 1px solid var(--border-weak-base); + border-top: none; + border-bottom-left-radius: var(--radius-md); + border-bottom-right-radius: var(--radius-md); } } - [data-slot="accordion-content"][data-expanded] { - grid-template-rows: 1fr; - } - - [data-slot="accordion-content"][data-closed] { - grid-template-rows: 0fr; - } - - &[data-expanded] [data-slot="accordion-trigger"] { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } - - &[data-expanded] [data-slot="accordion-content"] { - border: 1px solid var(--border-weak-base); - border-top: none; - border-bottom-left-radius: var(--radius-md); - border-bottom-right-radius: var(--radius-md); - height: auto; + [data-slot="accordion-content"] { + overflow: hidden; + width: 100%; } } } + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--kb-accordion-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--kb-accordion-content-height); + } + to { + height: 0; + } +} diff --git a/packages/ui/src/components/accordion.tsx b/packages/ui/src/components/accordion.tsx index e30be95e05..535d38e3d0 100644 --- a/packages/ui/src/components/accordion.tsx +++ b/packages/ui/src/components/accordion.tsx @@ -1,7 +1,6 @@ import { Accordion as Kobalte } from "@kobalte/core/accordion" -import { Accessor, createContext, splitProps, useContext } from "solid-js" +import { splitProps } from "solid-js" import type { ComponentProps, ParentProps } from "solid-js" -import { MorphChevron } from "./morph-chevron" export interface AccordionProps extends ComponentProps {} export interface AccordionItemProps extends ComponentProps {} @@ -9,8 +8,6 @@ export interface AccordionHeaderProps extends ComponentProps {} export interface AccordionContentProps extends ComponentProps {} -const AccordionItemContext = createContext>() - function AccordionRoot(props: AccordionProps) { const [split, rest] = splitProps(props, ["class", "classList"]) return ( @@ -25,19 +22,17 @@ function AccordionRoot(props: AccordionProps) { ) } -function AccordionItem(props: AccordionItemProps & { expanded?: boolean }) { - const [split, rest] = splitProps(props, ["class", "classList", "expanded"]) +function AccordionItem(props: AccordionItemProps) { + const [split, rest] = splitProps(props, ["class", "classList"]) return ( - split.expanded ?? false}> - - + ) } @@ -89,25 +84,9 @@ function AccordionContent(props: ParentProps) { ) } -export interface AccordionArrowProps extends ComponentProps<"div"> { - expanded?: boolean -} - -function AccordionArrow(props: AccordionArrowProps = {}) { - const [local, rest] = splitProps(props, ["expanded"]) - const contextExpanded = useContext(AccordionItemContext) - const isExpanded = () => local.expanded ?? contextExpanded?.() ?? false - return ( -
- -
- ) -} - export const Accordion = Object.assign(AccordionRoot, { Item: AccordionItem, Header: AccordionHeader, Trigger: AccordionTrigger, Content: AccordionContent, - Arrow: AccordionArrow, }) diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index 02a7ade712..d9b3459230 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -8,13 +8,8 @@ text-decoration: none; user-select: none; cursor: default; - padding: 4px 8px; - white-space: nowrap; - transition-property: background-color, border-color, color, box-shadow, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); outline: none; - line-height: 20px; + white-space: nowrap; &[data-variant="primary"] { background-color: var(--button-primary-base); @@ -99,6 +94,7 @@ &:active:not(:disabled) { background-color: var(--button-secondary-base); scale: 0.99; + transition: all 150ms ease-out; } &:disabled { border-color: var(--border-disabled); @@ -113,27 +109,34 @@ } &[data-size="small"] { - padding: 2px 8px; + height: 22px; + padding: 0 8px; &[data-icon] { - padding: 2px 12px 2px 4px; + padding: 0 12px 0 4px; } + font-size: var(--font-size-small); + line-height: var(--line-height-large); gap: 4px; /* text-12-medium */ font-family: var(--font-family-sans); - font-size: var(--font-size-base); + font-size: var(--font-size-small); font-style: normal; font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ letter-spacing: var(--letter-spacing-normal); } &[data-size="normal"] { - padding: 4px 6px; + height: 24px; + line-height: 24px; + padding: 0 6px; &[data-icon] { - padding: 4px 12px 4px 4px; + padding: 0 12px 0 4px; } + font-size: var(--font-size-small); gap: 6px; /* text-12-medium */ @@ -145,10 +148,11 @@ } &[data-size="large"] { + height: 32px; padding: 6px 12px; &[data-icon] { - padding: 6px 12px 6px 8px; + padding: 0 12px 0 8px; } gap: 4px; @@ -158,6 +162,7 @@ font-size: 14px; font-style: normal; font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ letter-spacing: var(--letter-spacing-normal); } diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx index b2d2004d3c..7f974b2f76 100644 --- a/packages/ui/src/components/button.tsx +++ b/packages/ui/src/components/button.tsx @@ -4,7 +4,7 @@ import { Icon, IconProps } from "./icon" export interface ButtonProps extends ComponentProps, - Pick, "class" | "classList" | "children" | "style"> { + Pick, "class" | "classList" | "children"> { size?: "small" | "normal" | "large" variant?: "primary" | "secondary" | "ghost" icon?: IconProps["name"] diff --git a/packages/ui/src/components/card.css b/packages/ui/src/components/card.css index 809fbdacde..6dae47223d 100644 --- a/packages/ui/src/components/card.css +++ b/packages/ui/src/components/card.css @@ -4,9 +4,7 @@ flex-direction: column; background-color: var(--surface-inset-base); border: 1px solid var(--border-weaker-base); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: background-color 0.15s ease; border-radius: var(--radius-md); padding: 6px 12px; overflow: clip; diff --git a/packages/ui/src/components/checkbox.css b/packages/ui/src/components/checkbox.css index cad0dd2dd6..b10ebbbd19 100644 --- a/packages/ui/src/components/checkbox.css +++ b/packages/ui/src/components/checkbox.css @@ -4,18 +4,6 @@ gap: 12px; cursor: default; - [data-slot="checkbox-checkbox-control"] { - transition-property: border-color, background-color, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } - - [data-slot="checkbox-checkbox-indicator"] { - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } - [data-slot="checkbox-checkbox-input"] { position: absolute; width: 1px; diff --git a/packages/ui/src/components/collapsible.css b/packages/ui/src/components/collapsible.css index cc62b2b87c..1f20cf85d9 100644 --- a/packages/ui/src/components/collapsible.css +++ b/packages/ui/src/components/collapsible.css @@ -4,9 +4,7 @@ flex-direction: column; background-color: var(--surface-inset-base); border: 1px solid var(--border-weaker-base); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: background-color 0.15s ease; border-radius: var(--radius-md); overflow: clip; @@ -46,28 +44,16 @@ display: flex; align-items: center; justify-content: center; - color: var(--text-weak); } } [data-slot="collapsible-content"] { - display: grid; - grid-template-rows: 0fr; - transition-property: grid-template-rows, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + overflow: hidden; + /* animation: slideUp 250ms ease-out; */ - > * { - overflow: hidden; - } - - &[data-expanded] { - grid-template-rows: 1fr; - } - - &[data-closed] { - grid-template-rows: 0fr; - } + /* &[data-expanded] { */ + /* animation: slideDown 250ms ease-out; */ + /* } */ } &[data-variant="ghost"] { @@ -97,3 +83,21 @@ } } } + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--kb-collapsible-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--kb-collapsible-content-height); + } + to { + height: 0; + } +} diff --git a/packages/ui/src/components/collapsible.tsx b/packages/ui/src/components/collapsible.tsx index 55b7b60333..903afc3085 100644 --- a/packages/ui/src/components/collapsible.tsx +++ b/packages/ui/src/components/collapsible.tsx @@ -1,8 +1,6 @@ import { Collapsible as Kobalte, CollapsibleRootProps } from "@kobalte/core/collapsible" -import { Accessor, ComponentProps, createContext, createSignal, ParentProps, splitProps, useContext } from "solid-js" -import { MorphChevron } from "./morph-chevron" - -const CollapsibleContext = createContext>() +import { ComponentProps, ParentProps, splitProps } from "solid-js" +import { Icon } from "./icon" export interface CollapsibleProps extends ParentProps { class?: string @@ -11,30 +9,17 @@ export interface CollapsibleProps extends ParentProps { } function CollapsibleRoot(props: CollapsibleProps) { - const [local, others] = splitProps(props, ["class", "classList", "variant", "open", "onOpenChange", "children"]) - const [internalOpen, setInternalOpen] = createSignal(local.open ?? false) - - const handleOpenChange = (open: boolean) => { - setInternalOpen(open) - local.onOpenChange?.(open) - } - + const [local, others] = splitProps(props, ["class", "classList", "variant"]) return ( - - - {local.children} - - + ) } @@ -47,10 +32,9 @@ function CollapsibleContent(props: ComponentProps) { } function CollapsibleArrow(props?: ComponentProps<"div">) { - const isOpen = useContext(CollapsibleContext) return (
- +
) } diff --git a/packages/ui/src/components/cycle-label.css b/packages/ui/src/components/cycle-label.css deleted file mode 100644 index e3b5256d4f..0000000000 --- a/packages/ui/src/components/cycle-label.css +++ /dev/null @@ -1,51 +0,0 @@ -.cycle-label { - --c-dur: 200ms; - --c-stag: 30ms; - --c-ease: cubic-bezier(0.25, 0, 0.5, 1); - --c-opacity-start: 0; - --c-opacity-end: 1; - --c-blur-start: 0px; - --c-blur-end: 0px; - --c-skew: 10deg; - - display: inline-flex; - position: relative; - - transform-style: preserve-3d; - perspective: 500px; - transition: width 200ms var(--c-ease); - will-change: width; - overflow: hidden; - - .cycle-char { - display: inline-block; - transform-style: preserve-3d; - min-width: 0.25em; - backface-visibility: hidden; - - transition: - transform var(--c-dur) var(--c-ease), - opacity var(--c-dur) var(--c-ease), - filter var(--c-dur) var(--c-ease); - transition-delay: calc(var(--i, 0) * var(--c-stag)); - - &.enter { - opacity: var(--c-opacity-end); - filter: blur(var(--c-blur-end)); - transform: translateY(0) rotateX(0) skewX(0); - } - - &.exit { - opacity: var(--c-opacity-start); - filter: blur(var(--c-blur-start)); - transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); - } - - &.pre { - opacity: var(--c-opacity-start); - filter: blur(var(--c-blur-start)); - transition: none; - transform: translateY(-50%) rotateX(-90deg) skewX(calc(var(--c-skew) * -1)); - } - } -} diff --git a/packages/ui/src/components/cycle-label.tsx b/packages/ui/src/components/cycle-label.tsx deleted file mode 100644 index e34385a2c2..0000000000 --- a/packages/ui/src/components/cycle-label.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import "./cycle-label.css" -import { createEffect, createSignal, JSX, on } from "solid-js" - -export interface CycleLabelProps extends JSX.HTMLAttributes { - value: string - onValueChange?: (value: string) => void - duration?: number | ((value: string) => number) - stagger?: number - opacity?: [number, number] - blur?: [number, number] - skewX?: number - onAnimationStart?: () => void - onAnimationEnd?: () => void -} - -const segmenter = - typeof Intl !== "undefined" && Intl.Segmenter ? new Intl.Segmenter("en", { granularity: "grapheme" }) : null - -const getChars = (text: string): string[] => - segmenter ? Array.from(segmenter.segment(text), (s) => s.segment) : text.split("") - -const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) - -export function CycleLabel(props: CycleLabelProps) { - const getDuration = (text: string) => { - const d = props?.duration ?? 200 - return typeof d === "function" ? d(text) : d - } - const stagger = () => props?.stagger ?? 20 - const opacity = () => props?.opacity ?? [0, 1] - const blur = () => props?.blur ?? [0, 0] - const skewX = () => props?.skewX ?? 10 - - let containerRef: HTMLSpanElement | undefined - let isAnimating = false - const [currentText, setCurrentText] = createSignal(props.value) - - const setChars = (el: HTMLElement, text: string, state: "enter" | "exit" | "pre" = "enter") => { - el.innerHTML = "" - const chars = getChars(text) - chars.forEach((char, i) => { - const span = document.createElement("span") - span.textContent = char === " " ? "\u00A0" : char - span.className = `cycle-char ${state}` - span.style.setProperty("--i", String(i)) - el.appendChild(span) - }) - } - - const animateToText = async (newText: string) => { - if (!containerRef || isAnimating) return - if (newText === currentText()) return - - isAnimating = true - props.onAnimationStart?.() - - const dur = getDuration(newText) - const stag = stagger() - - containerRef.style.width = containerRef.offsetWidth + "px" - - const oldChars = containerRef.querySelectorAll(".cycle-char") - oldChars.forEach((c) => c.classList.replace("enter", "exit")) - - const clone = containerRef.cloneNode(false) as HTMLElement - Object.assign(clone.style, { - position: "absolute", - visibility: "hidden", - width: "auto", - transition: "none", - }) - setChars(clone, newText) - document.body.appendChild(clone) - const nextWidth = clone.offsetWidth - clone.remove() - - const exitTime = oldChars.length * stag + dur - await wait(exitTime * 0.3) - - containerRef.style.width = nextWidth + "px" - - const widthDur = 200 - await wait(widthDur * 0.3) - - setChars(containerRef, newText, "pre") - containerRef.offsetWidth - - Array.from(containerRef.children).forEach((c) => (c.className = "cycle-char enter")) - setCurrentText(newText) - props.onValueChange?.(newText) - - const enterTime = getChars(newText).length * stag + dur - await wait(enterTime) - - containerRef.style.width = "" - isAnimating = false - props.onAnimationEnd?.() - } - - createEffect( - on( - () => props.value, - (newValue) => { - if (newValue !== currentText()) { - animateToText(newValue) - } - }, - ), - ) - - const initRef = (el: HTMLSpanElement) => { - containerRef = el - setChars(el, props.value) - } - - return ( - - ) -} diff --git a/packages/ui/src/components/dialog.css b/packages/ui/src/components/dialog.css index b788945dce..2e66b644fc 100644 --- a/packages/ui/src/components/dialog.css +++ b/packages/ui/src/components/dialog.css @@ -5,16 +5,6 @@ inset: 0; z-index: 50; background-color: hsl(from var(--background-base) h s l / 0.2); - - animation: overlayHide var(--transition-duration) var(--transition-easing) forwards; - - &[data-expanded] { - animation: overlayShow var(--transition-duration) var(--transition-easing) forwards; - } - - @starting-style { - animation: none; - } } [data-component="dialog"] { @@ -35,6 +25,7 @@ flex-direction: column; align-items: center; justify-items: start; + overflow: visible; [data-slot="dialog-content"] { display: flex; @@ -44,8 +35,16 @@ width: 100%; max-height: 100%; min-height: 280px; + overflow: auto; pointer-events: auto; + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + /* padding: 8px; */ /* padding: 8px 8px 0 8px; */ border-radius: var(--radius-xl); @@ -53,16 +52,6 @@ background-clip: padding-box; box-shadow: var(--shadow-lg-border-base); - animation: contentHide var(--transition-duration) var(--transition-easing) forwards; - - &[data-expanded] { - animation: contentShow var(--transition-duration) var(--transition-easing) forwards; - } - - @starting-style { - animation: none; - } - [data-slot="dialog-header"] { display: flex; padding: 20px; @@ -173,7 +162,7 @@ @keyframes contentShow { from { opacity: 0; - transform: translateY(2.5%) scale(0.975); + transform: scale(0.98); } to { opacity: 1; @@ -187,6 +176,6 @@ } to { opacity: 0; - transform: translateY(-2.5%) scale(0.975); + transform: scale(0.98); } } diff --git a/packages/ui/src/components/dropdown-menu.css b/packages/ui/src/components/dropdown-menu.css index 18266ac1a1..cba041613e 100644 --- a/packages/ui/src/components/dropdown-menu.css +++ b/packages/ui/src/components/dropdown-menu.css @@ -2,29 +2,26 @@ [data-component="dropdown-menu-sub-content"] { min-width: 8rem; overflow: hidden; - border: none; border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); + border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); background-clip: padding-box; background-color: var(--surface-raised-stronger-non-alpha); padding: 4px; - z-index: 100; + box-shadow: var(--shadow-md); + z-index: 50; transform-origin: var(--kb-menu-content-transform-origin); - &:focus-within, - &:focus { + &:focus, + &:focus-visible { outline: none; } - animation: dropdownMenuContentHide var(--transition-duration) var(--transition-easing) forwards; - - @starting-style { - animation: none; + &[data-closed] { + animation: dropdown-menu-close 0.15s ease-out; } &[data-expanded] { - pointer-events: auto; - animation: dropdownMenuContentShow var(--transition-duration) var(--transition-easing) forwards; + animation: dropdown-menu-open 0.15s ease-out; } } @@ -41,22 +38,18 @@ padding: 4px 8px; border-radius: var(--radius-sm); cursor: default; + user-select: none; outline: none; font-family: var(--font-family-sans); - font-size: var(--font-size-base); + font-size: var(--font-size-small); font-weight: var(--font-weight-medium); line-height: var(--line-height-large); letter-spacing: var(--letter-spacing-normal); color: var(--text-strong); - transition-property: background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - user-select: none; - - &:hover { - background-color: var(--surface-raised-base-hover); + &[data-highlighted] { + background: var(--surface-raised-base-hover); } &[data-disabled] { @@ -68,8 +61,6 @@ [data-slot="dropdown-menu-sub-trigger"] { &[data-expanded] { background: var(--surface-raised-base-hover); - outline: none; - border: none; } } @@ -111,24 +102,24 @@ } } -@keyframes dropdownMenuContentShow { +@keyframes dropdown-menu-open { from { opacity: 0; - transform: scaleY(0.95); + transform: scale(0.96); } to { opacity: 1; - transform: scaleY(1); + transform: scale(1); } } -@keyframes dropdownMenuContentHide { +@keyframes dropdown-menu-close { from { opacity: 1; - transform: scaleY(1); + transform: scale(1); } to { opacity: 0; - transform: scaleY(0.95); + transform: scale(0.96); } } diff --git a/packages/ui/src/components/hover-card.css b/packages/ui/src/components/hover-card.css index d23e43946d..02d1f10ad1 100644 --- a/packages/ui/src/components/hover-card.css +++ b/packages/ui/src/components/hover-card.css @@ -24,11 +24,11 @@ } &[data-closed] { - animation: hover-card-close var(--transition-duration) var(--transition-easing); + animation: hover-card-close 0.15s ease-out; } &[data-expanded] { - animation: hover-card-open var(--transition-duration) var(--transition-easing); + animation: hover-card-open 0.15s ease-out; } [data-slot="hover-card-body"] { diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index f1371bfa9a..aa550e990f 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -7,9 +7,6 @@ user-select: none; aspect-ratio: 1; flex-shrink: 0; - transition-property: background-color, color, opacity, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); &[data-variant="primary"] { background-color: var(--icon-strong-base); @@ -102,7 +99,7 @@ /* color: var(--icon-active); */ /* } */ } - &[data-selected]:not(:disabled) { + &:selected:not(:disabled) { background-color: var(--surface-raised-base-active); /* [data-slot="icon-svg"] { */ /* color: var(--icon-selected); */ diff --git a/packages/ui/src/components/icon.css b/packages/ui/src/components/icon.css index 467ff21bcc..a2ebee30bc 100644 --- a/packages/ui/src/components/icon.css +++ b/packages/ui/src/components/icon.css @@ -4,7 +4,7 @@ justify-content: center; flex-shrink: 0; /* resize: both; */ - aspect-ratio: 1 / 1; + aspect-ratio: 1/1; color: var(--icon-base); &[data-size="small"] { diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index 97488a42f0..544c6abdd2 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -80,16 +80,13 @@ const icons = { export interface IconProps extends ComponentProps<"svg"> { name: keyof typeof icons - size?: "small" | "normal" | "medium" | "large" | number + size?: "small" | "normal" | "medium" | "large" } export function Icon(props: IconProps) { const [local, others] = splitProps(props, ["name", "size", "class", "classList"]) return ( -
+
('[data-slot="list-item"][data-key]') @@ -268,7 +267,7 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void }) {searchAction()}
- +
0 || showAdd()} fallback={ @@ -340,7 +339,7 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void })
-
+
) } diff --git a/packages/ui/src/components/logo.css b/packages/ui/src/components/logo.css index 091649e8bb..a909782b77 100644 --- a/packages/ui/src/components/logo.css +++ b/packages/ui/src/components/logo.css @@ -1,4 +1,4 @@ [data-component="logo-mark"] { width: 16px; - aspect-ratio: 4 / 5; + aspect-ratio: 4/5; } diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 9c975d5490..7aad01acea 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -49,7 +49,6 @@ import { Tooltip } from "./tooltip" import { IconButton } from "./icon-button" import { createAutoScroll } from "../hooks" import { createResizeObserver } from "@solid-primitives/resize-observer" -import { MorphChevron } from "./morph-chevron" interface Diagnostic { range: { @@ -416,7 +415,7 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp toggleExpanded() }} > - +
props.expanded, - (expanded, prev) => { - if (prev === undefined) { - // Set initial state without animation - path?.setAttribute("d", expanded ? EXPANDED : COLLAPSED) - return - } - if (expanded) { - expandAnim?.beginElement() - } else { - collapseAnim?.beginElement() - } - }, - ), - ) - - return ( - - ) -} diff --git a/packages/ui/src/components/popover.css b/packages/ui/src/components/popover.css index d200fe8b24..b49542afd9 100644 --- a/packages/ui/src/components/popover.css +++ b/packages/ui/src/components/popover.css @@ -15,35 +15,16 @@ transform-origin: var(--kb-popover-content-transform-origin); - animation: popoverContentHide var(--transition-duration) var(--transition-easing) forwards; + &:focus-within { + outline: none; + } - @starting-style { - animation: none; + &[data-closed] { + animation: popover-close 0.15s ease-out; } &[data-expanded] { - pointer-events: auto; - animation: popoverContentShow var(--transition-duration) var(--transition-easing) forwards; - } - - [data-origin-top-right] { - transform-origin: top right; - } - - [data-origin-top-left] { - transform-origin: top left; - } - - [data-origin-bottom-right] { - transform-origin: bottom right; - } - - [data-origin-bottom-left] { - transform-origin: bottom left; - } - - &:focus-within { - outline: none; + animation: popover-open 0.15s ease-out; } [data-slot="popover-header"] { @@ -94,39 +75,24 @@ } } -@keyframes popoverContentShow { +@keyframes popover-open { from { opacity: 0; - transform: scaleY(0.95); + transform: scale(0.96); } to { opacity: 1; - transform: scaleY(1); + transform: scale(1); } } -@keyframes popoverContentHide { +@keyframes popover-close { from { opacity: 1; - transform: scaleY(1); + transform: scale(1); } to { opacity: 0; - transform: scaleY(0.95); - } -} - -[data-component="model-popover-content"] { - transform-origin: var(--kb-popper-content-transform-origin); - pointer-events: none; - animation: popoverContentHide var(--transition-duration) var(--transition-easing) forwards; - - @starting-style { - animation: none; - } - - &[data-expanded] { - pointer-events: auto; - animation: popoverContentShow var(--transition-duration) var(--transition-easing) forwards; + transform: scale(0.96); } } diff --git a/packages/ui/src/components/progress-circle.css b/packages/ui/src/components/progress-circle.css index d8dc4e1d05..afaf72af61 100644 --- a/packages/ui/src/components/progress-circle.css +++ b/packages/ui/src/components/progress-circle.css @@ -1,10 +1,12 @@ [data-component="progress-circle"] { - color: inherit; + transform: rotate(-90deg); [data-slot="progress-circle-background"] { - transform-origin: 50% 50%; - transform: rotate(270deg); - stroke-opacity: 0.5; + stroke: var(--border-weak-base); + } + + [data-slot="progress-circle-progress"] { + stroke: var(--border-active); transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); } } diff --git a/packages/ui/src/components/progress-circle.tsx b/packages/ui/src/components/progress-circle.tsx index 40d1e2022f..02bd36bb71 100644 --- a/packages/ui/src/components/progress-circle.tsx +++ b/packages/ui/src/components/progress-circle.tsx @@ -1,4 +1,4 @@ -import { type ComponentProps, splitProps } from "solid-js" +import { type ComponentProps, createMemo, splitProps } from "solid-js" export interface ProgressCircleProps extends Pick, "class" | "classList"> { percentage: number @@ -9,15 +9,26 @@ export interface ProgressCircleProps extends Pick, "class" export function ProgressCircle(props: ProgressCircleProps) { const [split, rest] = splitProps(props, ["percentage", "size", "strokeWidth", "class", "classList"]) - const size = () => split.size || 18 - const r = 7 + const size = () => split.size || 16 + const strokeWidth = () => split.strokeWidth || 3 + + const viewBoxSize = 16 + const center = viewBoxSize / 2 + const radius = () => center - strokeWidth() / 2 + const circumference = createMemo(() => 2 * Math.PI * radius()) + + const offset = createMemo(() => { + const clampedPercentage = Math.max(0, Math.min(100, split.percentage || 0)) + const progress = clampedPercentage / 100 + return circumference() * (1 - progress) + }) return ( - - { - const pct = Math.min(100, Math.max(0, split.percentage)) - const angle = (pct / 100) * 2 * Math.PI - Math.PI / 2 - const x = 9 + r * Math.cos(angle) - const y = 9 + r * Math.sin(angle) - const largeArc = pct > 50 ? 1 : 0 - return `M9 2A${r} ${r} 0 ${largeArc} 1 ${x} ${y}L9 9Z` - })()} - fill="currentColor" + + ) diff --git a/packages/ui/src/components/radio-group.css b/packages/ui/src/components/radio-group.css index df51fc8e86..3d672bb300 100644 --- a/packages/ui/src/components/radio-group.css +++ b/packages/ui/src/components/radio-group.css @@ -27,9 +27,12 @@ content: ""; opacity: var(--indicator-opacity, 1); position: absolute; - transition-property: opacity, box-shadow, width, height, transform; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: + opacity 300ms ease-in-out, + box-shadow 100ms ease-in-out, + width 150ms ease, + height 150ms ease, + transform 150ms ease; } [data-slot="radio-group-item"] { @@ -43,9 +46,7 @@ content: ""; inset: 6px 0; position: absolute; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: opacity 150ms ease; width: 1px; transform: translateX(-0.5px); } @@ -71,9 +72,9 @@ padding: 6px 12px; place-content: center; position: relative; + transition-duration: 150ms; transition-property: color, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition-timing-function: ease-in-out; user-select: none; } diff --git a/packages/ui/src/components/reasoning-icon.css b/packages/ui/src/components/reasoning-icon.css deleted file mode 100644 index b03f69a931..0000000000 --- a/packages/ui/src/components/reasoning-icon.css +++ /dev/null @@ -1,8 +0,0 @@ -[data-component="reasoning-icon"] { - color: var(--icon-strong-base); - - [data-slot="reasoning-icon-percentage"] { - transition: clip-path 200ms cubic-bezier(0.25, 0, 0.5, 1); - clip-path: inset(calc(100% - var(--reasoning-icon-percentage) * 100%) 0 0 0); - } -} diff --git a/packages/ui/src/components/reasoning-icon.tsx b/packages/ui/src/components/reasoning-icon.tsx deleted file mode 100644 index 7bac49ffd2..0000000000 --- a/packages/ui/src/components/reasoning-icon.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { type ComponentProps, splitProps } from "solid-js" - -export interface ReasoningIconProps extends Pick, "class" | "classList"> { - percentage: number - size?: number - strokeWidth?: number -} - -export function ReasoningIcon(props: ReasoningIconProps) { - const [split, rest] = splitProps(props, ["percentage", "size", "strokeWidth", "class", "classList"]) - - const size = () => split.size || 16 - const strokeWidth = () => split.strokeWidth || 1.25 - - return ( - - - - - ) -} diff --git a/packages/ui/src/components/resize-handle.css b/packages/ui/src/components/resize-handle.css index 0aad9b9678..c309ff838b 100644 --- a/packages/ui/src/components/resize-handle.css +++ b/packages/ui/src/components/resize-handle.css @@ -6,9 +6,7 @@ content: ""; position: absolute; opacity: 0; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: opacity 0.15s ease-in-out; } &:hover::after, diff --git a/packages/ui/src/components/scroll-fade.css b/packages/ui/src/components/scroll-fade.css deleted file mode 100644 index ede5fabec4..0000000000 --- a/packages/ui/src/components/scroll-fade.css +++ /dev/null @@ -1,82 +0,0 @@ -[data-component="scroll-fade"] { - overflow: auto; - overscroll-behavior: contain; - scrollbar-width: none; - box-sizing: border-box; - color: inherit; - font: inherit; - -ms-overflow-style: none; - - &::-webkit-scrollbar { - display: none; - } - - &[data-direction="horizontal"] { - overflow-x: auto; - overflow-y: hidden; - - /* Both fades */ - &[data-fade-start][data-fade-end] { - mask-image: linear-gradient( - to right, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - -webkit-mask-image: linear-gradient( - to right, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - } - - /* Only start fade */ - &[data-fade-start]:not([data-fade-end]) { - mask-image: linear-gradient(to right, transparent, black var(--scroll-fade-start), black 100%); - -webkit-mask-image: linear-gradient(to right, transparent, black var(--scroll-fade-start), black 100%); - } - - /* Only end fade */ - &:not([data-fade-start])[data-fade-end] { - mask-image: linear-gradient(to right, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); - -webkit-mask-image: linear-gradient(to right, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); - } - } - - &[data-direction="vertical"] { - overflow-y: auto; - overflow-x: hidden; - - &[data-fade-start][data-fade-end] { - mask-image: linear-gradient( - to bottom, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - -webkit-mask-image: linear-gradient( - to bottom, - transparent, - black var(--scroll-fade-start), - black calc(100% - var(--scroll-fade-end)), - transparent - ); - } - - /* Only start fade */ - &[data-fade-start]:not([data-fade-end]) { - mask-image: linear-gradient(to bottom, transparent, black var(--scroll-fade-start), black 100%); - -webkit-mask-image: linear-gradient(to bottom, transparent, black var(--scroll-fade-start), black 100%); - } - - /* Only end fade */ - &:not([data-fade-start])[data-fade-end] { - mask-image: linear-gradient(to bottom, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); - -webkit-mask-image: linear-gradient(to bottom, black 0%, black calc(100% - var(--scroll-fade-end)), transparent); - } - } -} diff --git a/packages/ui/src/components/scroll-fade.tsx b/packages/ui/src/components/scroll-fade.tsx deleted file mode 100644 index 0effb678a5..0000000000 --- a/packages/ui/src/components/scroll-fade.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import { type JSX, createEffect, createSignal, onCleanup, onMount, splitProps } from "solid-js" -import "./scroll-fade.css" - -export interface ScrollFadeProps extends JSX.HTMLAttributes { - direction?: "horizontal" | "vertical" - fadeStartSize?: number - fadeEndSize?: number - trackTransformSelector?: string - ref?: (el: HTMLDivElement) => void -} - -export function ScrollFade(props: ScrollFadeProps) { - const [local, others] = splitProps(props, [ - "children", - "direction", - "fadeStartSize", - "fadeEndSize", - "trackTransformSelector", - "class", - "style", - "ref", - ]) - - const direction = () => local.direction ?? "vertical" - const fadeStartSize = () => local.fadeStartSize ?? 20 - const fadeEndSize = () => local.fadeEndSize ?? 20 - - const getTransformOffset = (element: Element): number => { - const style = getComputedStyle(element) - const transform = style.transform - if (!transform || transform === "none") return 0 - - const match = transform.match(/matrix(?:3d)?\(([^)]+)\)/) - if (!match) return 0 - - const values = match[1].split(",").map((v) => parseFloat(v.trim())) - const isHorizontal = direction() === "horizontal" - - if (transform.startsWith("matrix3d")) { - return isHorizontal ? -(values[12] || 0) : -(values[13] || 0) - } else { - return isHorizontal ? -(values[4] || 0) : -(values[5] || 0) - } - } - - let containerRef: HTMLDivElement | undefined - - const [fadeStart, setFadeStart] = createSignal(0) - const [fadeEnd, setFadeEnd] = createSignal(0) - const [isScrollable, setIsScrollable] = createSignal(false) - - let lastScrollPos = 0 - let lastTransformPos = 0 - let lastScrollSize = 0 - let lastClientSize = 0 - - const updateFade = () => { - if (!containerRef) return - - const isHorizontal = direction() === "horizontal" - const scrollPos = isHorizontal ? containerRef.scrollLeft : containerRef.scrollTop - const scrollSize = isHorizontal ? containerRef.scrollWidth : containerRef.scrollHeight - const clientSize = isHorizontal ? containerRef.clientWidth : containerRef.clientHeight - - let transformPos = 0 - if (local.trackTransformSelector) { - const transformElement = containerRef.querySelector(local.trackTransformSelector) - if (transformElement) { - transformPos = getTransformOffset(transformElement) - } - } - - const effectiveScrollPos = Math.max(scrollPos, transformPos) - - if ( - effectiveScrollPos === lastScrollPos && - transformPos === lastTransformPos && - scrollSize === lastScrollSize && - clientSize === lastClientSize - ) { - return - } - - lastScrollPos = effectiveScrollPos - lastTransformPos = transformPos - lastScrollSize = scrollSize - lastClientSize = clientSize - - const maxScroll = scrollSize - clientSize - const canScroll = maxScroll > 1 - - setIsScrollable(canScroll) - - if (!canScroll) { - setFadeStart(0) - setFadeEnd(0) - return - } - - const progress = maxScroll > 0 ? effectiveScrollPos / maxScroll : 0 - - const startProgress = Math.min(progress / 0.1, 1) - setFadeStart(startProgress * fadeStartSize()) - - const endProgress = progress > 0.9 ? (1 - progress) / 0.1 : 1 - setFadeEnd(Math.max(0, endProgress) * fadeEndSize()) - } - - onMount(() => { - if (!containerRef) return - - updateFade() - - let rafId: number | undefined - let isPolling = false - let pollTimeout: ReturnType | undefined - - const startPolling = () => { - if (isPolling) return - isPolling = true - - const pollScroll = () => { - updateFade() - rafId = requestAnimationFrame(pollScroll) - } - rafId = requestAnimationFrame(pollScroll) - } - - const stopPolling = () => { - if (!isPolling) return - isPolling = false - if (rafId !== undefined) { - cancelAnimationFrame(rafId) - rafId = undefined - } - } - - const schedulePollingStop = () => { - if (pollTimeout !== undefined) clearTimeout(pollTimeout) - pollTimeout = setTimeout(stopPolling, 1000) - } - - const onActivity = () => { - updateFade() - if (local.trackTransformSelector) { - startPolling() - schedulePollingStop() - } - } - - containerRef.addEventListener("scroll", onActivity, { passive: true }) - - const resizeObserver = new ResizeObserver(() => { - lastScrollSize = 0 - lastClientSize = 0 - onActivity() - }) - resizeObserver.observe(containerRef) - - const mutationObserver = new MutationObserver(() => { - lastScrollSize = 0 - lastClientSize = 0 - requestAnimationFrame(onActivity) - }) - mutationObserver.observe(containerRef, { - childList: true, - subtree: true, - characterData: true, - }) - - onCleanup(() => { - containerRef?.removeEventListener("scroll", onActivity) - resizeObserver.disconnect() - mutationObserver.disconnect() - stopPolling() - if (pollTimeout !== undefined) clearTimeout(pollTimeout) - }) - }) - - createEffect(() => { - local.children - requestAnimationFrame(updateFade) - }) - - return ( -
{ - containerRef = el - local.ref?.(el) - }} - data-component="scroll-fade" - data-direction={direction()} - data-scrollable={isScrollable() || undefined} - data-fade-start={fadeStart() > 0 || undefined} - data-fade-end={fadeEnd() > 0 || undefined} - class={local.class} - style={{ - ...(typeof local.style === "object" ? local.style : {}), - "--scroll-fade-start": `${fadeStart()}px`, - "--scroll-fade-end": `${fadeEnd()}px`, - }} - {...others} - > - {local.children} -
- ) -} diff --git a/packages/ui/src/components/scroll-reveal.tsx b/packages/ui/src/components/scroll-reveal.tsx deleted file mode 100644 index 6e5072dc81..0000000000 --- a/packages/ui/src/components/scroll-reveal.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { type JSX, onCleanup, splitProps } from "solid-js" -import { ScrollFade, type ScrollFadeProps } from "./scroll-fade" - -const SCROLL_SPEED = 60 -const PAUSE_DURATION = 800 - -type ScrollAnimationState = { - rafId: number | null - startTime: number - running: boolean -} - -const startScrollAnimation = (containerEl: HTMLElement): ScrollAnimationState | null => { - containerEl.offsetHeight - - const extraWidth = containerEl.scrollWidth - containerEl.clientWidth - - if (extraWidth <= 0) { - return null - } - - const scrollDuration = (extraWidth / SCROLL_SPEED) * 1000 - const totalDuration = PAUSE_DURATION + scrollDuration + PAUSE_DURATION + scrollDuration + PAUSE_DURATION - - const state: ScrollAnimationState = { - rafId: null, - startTime: performance.now(), - running: true, - } - - const animate = (currentTime: number) => { - if (!state.running) return - - const elapsed = currentTime - state.startTime - const progress = (elapsed % totalDuration) / totalDuration - - const pausePercent = PAUSE_DURATION / totalDuration - const scrollPercent = scrollDuration / totalDuration - - const pauseEnd1 = pausePercent - const scrollEnd1 = pauseEnd1 + scrollPercent - const pauseEnd2 = scrollEnd1 + pausePercent - const scrollEnd2 = pauseEnd2 + scrollPercent - - let scrollPos = 0 - - if (progress < pauseEnd1) { - scrollPos = 0 - } else if (progress < scrollEnd1) { - const scrollProgress = (progress - pauseEnd1) / scrollPercent - scrollPos = scrollProgress * extraWidth - } else if (progress < pauseEnd2) { - scrollPos = extraWidth - } else if (progress < scrollEnd2) { - const scrollProgress = (progress - pauseEnd2) / scrollPercent - scrollPos = extraWidth * (1 - scrollProgress) - } else { - scrollPos = 0 - } - - containerEl.scrollLeft = scrollPos - state.rafId = requestAnimationFrame(animate) - } - - state.rafId = requestAnimationFrame(animate) - return state -} - -const stopScrollAnimation = (state: ScrollAnimationState | null, containerEl?: HTMLElement) => { - if (state) { - state.running = false - if (state.rafId !== null) { - cancelAnimationFrame(state.rafId) - } - } - if (containerEl) { - containerEl.scrollLeft = 0 - } -} - -export interface ScrollRevealProps extends Omit { - hoverDelay?: number -} - -export function ScrollReveal(props: ScrollRevealProps) { - const [local, others] = splitProps(props, ["children", "hoverDelay", "ref"]) - - const hoverDelay = () => local.hoverDelay ?? 300 - - let containerRef: HTMLDivElement | undefined - let hoverTimeout: ReturnType | undefined - let scrollAnimationState: ScrollAnimationState | null = null - - const handleMouseEnter: JSX.EventHandler = () => { - hoverTimeout = setTimeout(() => { - if (!containerRef) return - - containerRef.offsetHeight - - const isScrollable = containerRef.scrollWidth > containerRef.clientWidth + 1 - - if (isScrollable) { - stopScrollAnimation(scrollAnimationState, containerRef) - scrollAnimationState = startScrollAnimation(containerRef) - } - }, hoverDelay()) - } - - const handleMouseLeave: JSX.EventHandler = () => { - if (hoverTimeout) { - clearTimeout(hoverTimeout) - hoverTimeout = undefined - } - stopScrollAnimation(scrollAnimationState, containerRef) - scrollAnimationState = null - } - - onCleanup(() => { - if (hoverTimeout) { - clearTimeout(hoverTimeout) - } - stopScrollAnimation(scrollAnimationState, containerRef) - }) - - return ( - { - containerRef = el - local.ref?.(el) - }} - fadeStartSize={8} - fadeEndSize={8} - direction="horizontal" - onMouseEnter={handleMouseEnter} - onMouseLeave={handleMouseLeave} - {...others} - > - {local.children} - - ) -} diff --git a/packages/ui/src/components/select.css b/packages/ui/src/components/select.css index 5c79698835..25dd2eb40b 100644 --- a/packages/ui/src/components/select.css +++ b/packages/ui/src/components/select.css @@ -1,13 +1,7 @@ [data-component="select"] { [data-slot="select-select-trigger"] { - display: flex; - padding: 4px 8px !important; - align-items: center; - justify-content: space-between; + padding: 0 4px 0 8px; box-shadow: none; - transition-property: background-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); [data-slot="select-select-trigger-value"] { overflow: hidden; @@ -21,10 +15,10 @@ align-items: center; justify-content: center; flex-shrink: 0; - color: var(--icon-base); + color: var(--text-weak); + transition: transform 0.1s ease-in-out; } - &:hover, &[data-expanded] { &[data-variant="secondary"] { background-color: var(--button-secondary-hover); @@ -36,42 +30,78 @@ background-color: var(--icon-strong-active); } } - &:not([data-expanded]):focus, + &:not([data-expanded]):focus-visible { &[data-variant="secondary"] { background-color: var(--button-secondary-base); } &[data-variant="ghost"] { - background-color: transparent; + background-color: var(--surface-raised-base-hover); } &[data-variant="primary"] { background-color: var(--icon-strong-base); } } } + + &[data-trigger-style="settings"] { + [data-slot="select-select-trigger"] { + padding: 6px 6px 6px 12px; + box-shadow: none; + border-radius: 6px; + min-width: 160px; + height: 32px; + justify-content: flex-end; + gap: 12px; + background-color: transparent; + + [data-slot="select-select-trigger-value"] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: var(--font-size-base); + font-weight: var(--font-weight-regular); + } + [data-slot="select-select-trigger-icon"] { + width: 16px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: var(--text-weak); + background-color: var(--surface-raised-base); + border-radius: 4px; + transition: transform 0.1s ease-in-out; + } + + &[data-slot="select-select-trigger"]:hover:not(:disabled), + &[data-slot="select-select-trigger"][data-expanded], + &[data-slot="select-select-trigger"][data-expanded]:hover:not(:disabled) { + background-color: var(--input-base); + box-shadow: var(--shadow-xs-border-base); + } + + &:not([data-expanded]):focus { + background-color: transparent; + box-shadow: none; + } + } + } } [data-component="select-content"] { - min-width: 8rem; + min-width: 104px; max-width: 23rem; overflow: hidden; border-radius: var(--radius-md); background-color: var(--surface-raised-stronger-non-alpha); padding: 4px; box-shadow: var(--shadow-xs-border); - z-index: 50; - transform-origin: var(--kb-popper-content-transform-origin); - pointer-events: none; - - animation: selectContentHide var(--transition-duration) var(--transition-easing) forwards; - - @starting-style { - animation: none; - } + z-index: 60; &[data-expanded] { - pointer-events: auto; - animation: selectContentShow var(--transition-duration) var(--transition-easing) forwards; + animation: select-open 0.15s ease-out; } [data-slot="select-select-content-list"] { @@ -81,38 +111,43 @@ overflow-x: hidden; display: flex; flex-direction: column; + &:focus { outline: none; } + > *:not([role="presentation"]) + *:not([role="presentation"]) { margin-top: 2px; } } + [data-slot="select-select-item"] { position: relative; display: flex; align-items: center; - padding: 4px 8px; + padding: 2px 8px; gap: 12px; - border-radius: var(--radius-sm); + border-radius: 4px; + cursor: default; /* text-12-medium */ font-family: var(--font-family-sans); - font-size: var(--font-size-base); + font-size: var(--font-size-small); font-style: normal; font-weight: var(--font-weight-medium); line-height: var(--line-height-large); /* 166.667% */ letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); - transition-property: background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: + background-color 0.2s ease-in-out, + color 0.2s ease-in-out; outline: none; user-select: none; - &:hover { - background-color: var(--surface-raised-base-hover); + &[data-highlighted] { + background: var(--surface-raised-base-hover); } &[data-disabled] { background-color: var(--surface-raised-base); @@ -125,11 +160,6 @@ margin-left: auto; width: 16px; height: 16px; - color: var(--icon-strong-base); - - svg { - color: var(--icon-strong-base); - } } &:focus { outline: none; @@ -140,24 +170,33 @@ } } -@keyframes selectContentShow { - from { - opacity: 0; - transform: scaleY(0.95); +[data-component="select-content"][data-trigger-style="settings"] { + min-width: 160px; + border-radius: 8px; + padding: 0; + + [data-slot="select-select-content-list"] { + padding: 4px; } - to { - opacity: 1; - transform: scaleY(1); + + [data-slot="select-select-item"] { + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); } } -@keyframes selectContentHide { +@keyframes select-open { from { - opacity: 1; - transform: scaleY(1); + opacity: 0; + transform: scale(0.95); } to { - opacity: 0; - transform: scaleY(0.95); + opacity: 1; + transform: scale(1); } } diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index fef00500a7..0386c329ec 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -1,10 +1,8 @@ import { Select as Kobalte } from "@kobalte/core/select" -import { createMemo, createSignal, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" +import { createMemo, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" import { pipe, groupBy, entries, map } from "remeda" -import { Show } from "solid-js" import { Button, ButtonProps } from "./button" import { Icon } from "./icon" -import { MorphChevron } from "./morph-chevron" export type SelectProps = Omit>, "value" | "onSelect" | "children"> & { placeholder?: string @@ -40,8 +38,6 @@ export function Select(props: SelectProps & Omit) "triggerVariant", ]) - const [isOpen, setIsOpen] = createSignal(false) - const state = { key: undefined as string | undefined, cleanup: undefined as (() => void) | void, @@ -89,7 +85,7 @@ export function Select(props: SelectProps & Omit) data-component="select" data-trigger-style={local.triggerVariant} placement={local.triggerVariant === "settings" ? "bottom-end" : "bottom-start"} - gutter={8} + gutter={4} value={local.current} options={grouped()} optionValue={(x) => (local.value ? local.value(x) : (x as string))} @@ -119,7 +115,7 @@ export function Select(props: SelectProps & Omit) : (itemProps.item.rawValue as string)} - + )} @@ -128,7 +124,6 @@ export function Select(props: SelectProps & Omit) stop() }} onOpenChange={(open) => { - setIsOpen(open) local.onOpenChange?.(open) if (!open) stop() }} @@ -154,12 +149,7 @@ export function Select(props: SelectProps & Omit) }} - - - - - - + diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index 4fc88b1994..20d2fef152 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -63,8 +63,12 @@ [data-slot="accordion-item"] { [data-slot="accordion-content"] { - /* Use grid-template-rows for smooth height transition */ - display: grid; + display: none; + } + &[data-expanded] { + [data-slot="accordion-content"] { + display: block; + } } } @@ -126,9 +130,7 @@ cursor: pointer; border-radius: 4px; opacity: 0; - transition-property: opacity, background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: opacity 0.15s ease; &:hover { color: var(--text-strong); diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index b5a359707c..84ec934e24 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -290,8 +290,8 @@ export const SessionReview = (props: SessionReviewProps) => {
{i18n.t("ui.sessionReview.title")}
- - options={["unified", "split"]} + style} label={(style) => @@ -501,7 +501,6 @@ export const SessionReview = (props: SessionReviewProps) => { value={diff.file} id={diffId(diff.file)} data-file={diff.file} - expanded={open().includes(diff.file)} data-slot="session-review-accordion-item" data-selected={props.focusedFile === diff.file ? "" : undefined} > diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index 088b377cb7..d1ade879e2 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -102,11 +102,10 @@ [data-component="user-message"] [data-slot="user-message-text"] { max-height: var(--user-message-collapsed-height, 64px); - transition: max-height 200ms cubic-bezier(0.25, 0, 0.5, 1); } [data-component="user-message"][data-expanded="true"] [data-slot="user-message-text"] { - max-height: 2000px; + max-height: none; } [data-component="user-message"][data-can-expand="true"] [data-slot="user-message-text"] { @@ -152,6 +151,17 @@ background: transparent; cursor: pointer; color: var(--text-weak); + + [data-slot="icon-svg"] { + transition: transform 0.15s ease; + } + } + + [data-component="user-message"][data-expanded="true"] + [data-slot="user-message-text"] + [data-slot="user-message-expand"] + [data-slot="icon-svg"] { + transform: rotate(180deg); } [data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"]:hover { @@ -457,7 +467,6 @@ gap: 16px; align-items: center; justify-content: flex-end; - color: var(--icon-base); } [data-slot="session-turn-accordion-content"] { diff --git a/packages/ui/src/components/switch.css b/packages/ui/src/components/switch.css index 9ea722760a..89e8447322 100644 --- a/packages/ui/src/components/switch.css +++ b/packages/ui/src/components/switch.css @@ -26,9 +26,9 @@ border-radius: 3px; border: 1px solid var(--border-weak-base); background: var(--surface-base); - transition-property: background-color, border-color, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: + background-color 150ms, + border-color 150ms; } [data-slot="switch-thumb"] { @@ -47,9 +47,9 @@ 0 1px 3px 0 rgba(19, 16, 16, 0.08); transform: translateX(-1px); - transition-property: transform, background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + transition: + transform 150ms, + background-color 150ms; } [data-slot="switch-label"] { diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css index dab07dab91..56c3e083f5 100644 --- a/packages/ui/src/components/tabs.css +++ b/packages/ui/src/components/tabs.css @@ -58,9 +58,6 @@ border-bottom: 1px solid var(--border-weak-base); border-right: 1px solid var(--border-weak-base); background-color: var(--background-base); - transition-property: background-color, border-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); [data-slot="tabs-trigger"] { display: flex; diff --git a/packages/ui/src/components/tag.css b/packages/ui/src/components/tag.css index 5ffd2b9115..0e8b7b9f10 100644 --- a/packages/ui/src/components/tag.css +++ b/packages/ui/src/components/tag.css @@ -8,9 +8,6 @@ border: 0.5px solid var(--border-weak-base); background: var(--surface-raised-base); color: var(--text-base); - transition-property: background-color, border-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); &[data-size="normal"] { height: 18px; diff --git a/packages/ui/src/context/dialog.tsx b/packages/ui/src/context/dialog.tsx index 4132125122..afba5f648c 100644 --- a/packages/ui/src/context/dialog.tsx +++ b/packages/ui/src/context/dialog.tsx @@ -28,7 +28,6 @@ const Context = createContext>() function init() { const [active, setActive] = createSignal() - const [renders, setRenders] = createSignal>({}) const timer = { current: undefined as ReturnType | undefined } const lock = { value: false } @@ -119,32 +118,12 @@ function init() { setActive({ id, node, dispose, owner, onClose, setClosing }) } - const render = (element: JSX.Element, id: string, owner: Owner) => { - setRenders((renders) => ({ ...renders, [id]: element })) - show( - () => element, - owner, - () => { - setRenders((renders) => { - const { [id]: _, ...rest } = renders - return rest - }) - }, - ) - } - - const isActive = (id: string) => { - return renders()[id] !== undefined - } - return { get active() { return active() }, - isActive, close, show, - render, } } @@ -173,17 +152,10 @@ export function useDialog() { get active() { return ctx.active }, - isActive(id: string) { - return ctx.isActive(id) - }, show(element: DialogElement, onClose?: () => void) { const base = ctx.active?.owner ?? owner ctx.show(element, base, onClose) }, - render(element: JSX.Element, id: string) { - const base = ctx.active?.owner ?? owner - ctx.render(element, id, base) - }, close() { ctx.close() }, diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css index 7c8548734d..3ed0310ef2 100644 --- a/packages/ui/src/styles/index.css +++ b/packages/ui/src/styles/index.css @@ -33,10 +33,8 @@ @import "../components/markdown.css" layer(components); @import "../components/message-part.css" layer(components); @import "../components/message-nav.css" layer(components); -@import "../components/morph-chevron.css" layer(components); @import "../components/popover.css" layer(components); @import "../components/progress-circle.css" layer(components); -@import "../components/reasoning-icon.css" layer(components); @import "../components/radio-group.css" layer(components); @import "../components/resize-handle.css" layer(components); @import "../components/select.css" layer(components); diff --git a/packages/ui/src/styles/utilities.css b/packages/ui/src/styles/utilities.css index 82a913c883..8c954f1fe4 100644 --- a/packages/ui/src/styles/utilities.css +++ b/packages/ui/src/styles/utilities.css @@ -1,17 +1,6 @@ :root { interpolate-size: allow-keywords; - /* Transition tokens */ - --transition-duration: 200ms; - --transition-easing: cubic-bezier(0.25, 0, 0.5, 1); - --transition-fast: 150ms; - --transition-slow: 300ms; - - /* Allow height transitions from 0 to auto */ - @supports (interpolate-size: allow-keywords) { - interpolate-size: allow-keywords; - } - [data-popper-positioner] { pointer-events: none; } @@ -140,34 +129,3 @@ line-height: var(--line-height-x-large); /* 120% */ letter-spacing: var(--letter-spacing-tightest); } - -/* Transition utility classes */ -.transition-colors { - transition-property: background-color, border-color, color, fill, stroke; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); -} - -.transition-opacity { - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); -} - -.transition-transform { - transition-property: transform; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); -} - -.transition-shadow { - transition-property: box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); -} - -.transition-interactive { - transition-property: background-color, border-color, color, box-shadow, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); -} From 597ae57bb16ea8b4314f718bc3250c8b9433d7dc Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 31 Jan 2026 13:48:22 +0000 Subject: [PATCH 48/58] release: v1.1.48 --- bun.lock | 30 +++++++++++++------------- packages/app/package.json | 2 +- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++------ packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/slack/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 18 files changed, 37 insertions(+), 37 deletions(-) diff --git a/bun.lock b/bun.lock index 746360f1b5..0857283634 100644 --- a/bun.lock +++ b/bun.lock @@ -23,7 +23,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -73,7 +73,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -107,7 +107,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -134,7 +134,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -158,7 +158,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -182,7 +182,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -213,7 +213,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -242,7 +242,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -258,7 +258,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.1.47", + "version": "1.1.48", "bin": { "opencode": "./bin/opencode", }, @@ -362,7 +362,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -382,7 +382,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.1.47", + "version": "1.1.48", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -393,7 +393,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -406,7 +406,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -448,7 +448,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "zod": "catalog:", }, @@ -459,7 +459,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/app/package.json b/packages/app/package.json index f9866cfda3..e1232cb1ce 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.1.47", + "version": "1.1.48", "description": "", "type": "module", "exports": { diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 7fdb09a46e..83405bf634 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.1.47", + "version": "1.1.48", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 3ee9860804..d110dc117b 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.1.47", + "version": "1.1.48", "private": true, "type": "module", "license": "MIT", diff --git a/packages/console/function/package.json b/packages/console/function/package.json index bf8abdabbe..e04aa5e310 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.1.47", + "version": "1.1.48", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index a4eaeec088..1f69a0c75c 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.1.47", + "version": "1.1.48", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 993489de92..4f60bd58a2 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "1.1.47", + "version": "1.1.48", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index b7bf51afbd..4e901e23e2 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.1.47", + "version": "1.1.48", "private": true, "type": "module", "license": "MIT", diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 527ea3994f..576d6bbcd9 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The open source coding agent." -version = "1.1.47" +version = "1.1.48" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/anomalyco/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.47/opencode-darwin-arm64.zip" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.48/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.47/opencode-darwin-x64.zip" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.48/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.47/opencode-linux-arm64.tar.gz" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.48/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.47/opencode-linux-x64.tar.gz" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.48/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.47/opencode-windows-x64.zip" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.48/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 6fdb0d3090..88792e1e6a 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.1.47", + "version": "1.1.48", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 9d60283e8c..4afb724300 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.1.47", + "version": "1.1.48", "name": "opencode", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 2bcc3e8f99..5a4afbae43 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.1.47", + "version": "1.1.48", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 0fc2cac341..f9bf9c1e0b 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.1.47", + "version": "1.1.48", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/slack/package.json b/packages/slack/package.json index 41879e230c..3f5a30fadc 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.1.47", + "version": "1.1.48", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/ui/package.json b/packages/ui/package.json index 5db88629fd..7692331192 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.1.47", + "version": "1.1.48", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index b776ce2eee..9a3f13b10d 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.1.47", + "version": "1.1.48", "private": true, "type": "module", "license": "MIT", diff --git a/packages/web/package.json b/packages/web/package.json index 7d2eb66cfb..2db4cffe99 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -2,7 +2,7 @@ "name": "@opencode-ai/web", "type": "module", "license": "MIT", - "version": "1.1.47", + "version": "1.1.48", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 405514cca0..2f4a499645 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.1.47", + "version": "1.1.48", "publisher": "sst-dev", "repository": { "type": "git", From ac254fb44271e9589c766eac6c3a78e24e2da3f8 Mon Sep 17 00:00:00 2001 From: Alex Yaroshuk <34632190+alexyaroshuk@users.noreply.github.com> Date: Sat, 31 Jan 2026 22:53:49 +0800 Subject: [PATCH 49/58] fix(app): session header 'share' button to hug content (#11371) --- packages/app/src/components/session/session-header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index 449f2091bd..5b00f80c05 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -167,7 +167,7 @@ export function SessionHeader() { triggerAs={Button} triggerProps={{ variant: "secondary", - class: "rounded-sm w-[60px] h-[24px]", + class: "rounded-sm h-[24px] px-3", classList: { "rounded-r-none": shareUrl() !== undefined }, style: { scale: 1 }, }} From f73f88fb56381f0ea6746964bbd4a6496f7ec229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=86=E5=A5=95=E4=B8=9E?= <01luyicheng@gmail.com> Date: Sat, 31 Jan 2026 22:55:34 +0800 Subject: [PATCH 50/58] fix(pty): Add UTF-8 encoding defaults for Windows PTY (#11459) --- packages/opencode/src/pty/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/opencode/src/pty/index.ts b/packages/opencode/src/pty/index.ts index 73474ed4f8..d01b2b02e9 100644 --- a/packages/opencode/src/pty/index.ts +++ b/packages/opencode/src/pty/index.ts @@ -108,6 +108,12 @@ export namespace Pty { TERM: "xterm-256color", OPENCODE_TERMINAL: "1", } as Record + + if (process.platform === "win32") { + env.LC_ALL = "C.UTF-8" + env.LC_CTYPE = "C.UTF-8" + env.LANG = "C.UTF-8" + } log.info("creating session", { id, cmd: command, args, cwd }) const spawn = await pty() From 786ae0a584688214c99d613f18b6dc1b4ccefb9e Mon Sep 17 00:00:00 2001 From: Ryan Vogel Date: Sat, 31 Jan 2026 09:59:28 -0500 Subject: [PATCH 51/58] feat(app): add skill slash commands (#11369) --- packages/app/src/components/prompt-input.tsx | 36 +++++++++++++++++-- packages/app/src/context/global-sync.tsx | 6 ++++ packages/app/src/i18n/en.ts | 1 + .../cmd/tui/component/prompt/autocomplete.tsx | 14 ++++++++ .../opencode/src/cli/cmd/tui/context/sync.tsx | 4 +++ 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 5c1d417eb0..2bf9acf326 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -111,7 +111,7 @@ interface SlashCommand { title: string description?: string keybind?: string - type: "builtin" | "custom" + type: "builtin" | "custom" | "skill" } export const PromptInput: Component = (props) => { @@ -519,7 +519,15 @@ export const PromptInput: Component = (props) => { type: "custom" as const, })) - return [...custom, ...builtin] + const skills = sync.data.skill.map((skill) => ({ + id: `skill.${skill.name}`, + trigger: `skill:${skill.name}`, + title: skill.name, + description: skill.description, + type: "skill" as const, + })) + + return [...skills, ...custom, ...builtin] }) const handleSlashSelect = (cmd: SlashCommand | undefined) => { @@ -543,6 +551,25 @@ export const PromptInput: Component = (props) => { return } + if (cmd.type === "skill") { + // Extract skill name from the id (skill.{name}) + const skillName = cmd.id.replace("skill.", "") + const text = `Load the "${skillName}" skill and follow its instructions.` + editorRef.innerHTML = "" + editorRef.textContent = text + prompt.set([{ type: "text", content: text, start: 0, end: text.length }], text.length) + requestAnimationFrame(() => { + editorRef.focus() + const range = document.createRange() + const sel = window.getSelection() + range.selectNodeContents(editorRef) + range.collapse(false) + sel?.removeAllRanges() + sel?.addRange(range) + }) + return + } + editorRef.innerHTML = "" prompt.set([{ type: "text", content: "", start: 0, end: 0 }], 0) command.trigger(cmd.id, "slash") @@ -1706,6 +1733,11 @@ export const PromptInput: Component = (props) => { {language.t("prompt.slash.badge.custom")} + + + {language.t("prompt.slash.badge.skill")} + + {command.keybind(cmd.id)} diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index ad3d124b2c..6977b86a32 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -17,6 +17,7 @@ import { type VcsInfo, type PermissionRequest, type QuestionRequest, + type AppSkillsResponse, createOpencodeClient, } from "@opencode-ai/sdk/v2/client" import { createStore, produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store" @@ -56,10 +57,13 @@ type ProjectMeta = { } } +export type Skill = AppSkillsResponse[number] + type State = { status: "loading" | "partial" | "complete" agent: Agent[] command: Command[] + skill: Skill[] project: string projectMeta: ProjectMeta | undefined icon: string | undefined @@ -388,6 +392,7 @@ function createGlobalSync() { status: "loading" as const, agent: [], command: [], + skill: [], session: [], sessionTotal: 0, session_status: {}, @@ -528,6 +533,7 @@ function createGlobalSync() { Promise.all([ sdk.path.get().then((x) => setStore("path", x.data!)), sdk.command.list().then((x) => setStore("command", x.data ?? [])), + sdk.app.skills().then((x) => setStore("skill", x.data ?? [])), sdk.session.status().then((x) => setStore("session_status", x.data!)), loadSessions(directory), sdk.mcp.status().then((x) => setStore("mcp", x.data!)), diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index a6a50506a0..7b18f54aff 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -216,6 +216,7 @@ export const dict = { "prompt.popover.emptyCommands": "No matching commands", "prompt.dropzone.label": "Drop images or PDFs here", "prompt.slash.badge.custom": "custom", + "prompt.slash.badge.skill": "skill", "prompt.context.active": "active", "prompt.context.includeActiveFile": "Include active file", "prompt.context.removeActiveFile": "Remove active file from context", diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index bd000e2ab0..0c2ef61a62 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -359,6 +359,20 @@ export function Autocomplete(props: { }) } + for (const skill of sync.data.skill) { + results.push({ + display: "/skill:" + skill.name, + description: skill.description, + onSelect: () => { + const newText = `Load the "${skill.name}" skill and follow its instructions.` + const cursor = props.input().logicalCursor + props.input().deleteRange(0, 0, cursor.row, cursor.col) + props.input().insertText(newText) + props.input().cursorOffset = Bun.stringWidth(newText) + }, + }) + } + results.sort((a, b) => a.display.localeCompare(b.display)) const max = firstBy(results, [(x) => x.display.length, "desc"])?.display.length diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index eb8ed2d9bb..e7fedd6c35 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -17,6 +17,7 @@ import type { ProviderListResponse, ProviderAuthMethod, VcsInfo, + AppSkillsResponse, } from "@opencode-ai/sdk/v2" import { createStore, produce, reconcile } from "solid-js/store" import { useSDK } from "@tui/context/sdk" @@ -40,6 +41,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ provider_auth: Record agent: Agent[] command: Command[] + skill: AppSkillsResponse permission: { [sessionID: string]: PermissionRequest[] } @@ -86,6 +88,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ permission: {}, question: {}, command: [], + skill: [], provider: [], provider_default: {}, session: [], @@ -385,6 +388,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ Promise.all([ ...(args.continue ? [] : [sessionListPromise.then((sessions) => setStore("session", reconcile(sessions)))]), sdk.client.command.list().then((x) => setStore("command", reconcile(x.data ?? []))), + sdk.client.app.skills().then((x) => setStore("skill", reconcile(x.data ?? []))), sdk.client.lsp.status().then((x) => setStore("lsp", reconcile(x.data!))), sdk.client.mcp.status().then((x) => setStore("mcp", reconcile(x.data!))), sdk.client.experimental.resource.list().then((x) => setStore("mcp_resource", reconcile(x.data ?? {}))), From 53f118c57afa57464c561114693648fc65b05554 Mon Sep 17 00:00:00 2001 From: Ryan Vogel Date: Sat, 31 Jan 2026 10:20:23 -0500 Subject: [PATCH 52/58] Revert "feat(app): add skill slash commands" (#11484) --- packages/app/src/components/prompt-input.tsx | 36 ++----------------- packages/app/src/context/global-sync.tsx | 6 ---- packages/app/src/i18n/en.ts | 1 - .../cmd/tui/component/prompt/autocomplete.tsx | 14 -------- .../opencode/src/cli/cmd/tui/context/sync.tsx | 4 --- 5 files changed, 2 insertions(+), 59 deletions(-) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 2bf9acf326..5c1d417eb0 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -111,7 +111,7 @@ interface SlashCommand { title: string description?: string keybind?: string - type: "builtin" | "custom" | "skill" + type: "builtin" | "custom" } export const PromptInput: Component = (props) => { @@ -519,15 +519,7 @@ export const PromptInput: Component = (props) => { type: "custom" as const, })) - const skills = sync.data.skill.map((skill) => ({ - id: `skill.${skill.name}`, - trigger: `skill:${skill.name}`, - title: skill.name, - description: skill.description, - type: "skill" as const, - })) - - return [...skills, ...custom, ...builtin] + return [...custom, ...builtin] }) const handleSlashSelect = (cmd: SlashCommand | undefined) => { @@ -551,25 +543,6 @@ export const PromptInput: Component = (props) => { return } - if (cmd.type === "skill") { - // Extract skill name from the id (skill.{name}) - const skillName = cmd.id.replace("skill.", "") - const text = `Load the "${skillName}" skill and follow its instructions.` - editorRef.innerHTML = "" - editorRef.textContent = text - prompt.set([{ type: "text", content: text, start: 0, end: text.length }], text.length) - requestAnimationFrame(() => { - editorRef.focus() - const range = document.createRange() - const sel = window.getSelection() - range.selectNodeContents(editorRef) - range.collapse(false) - sel?.removeAllRanges() - sel?.addRange(range) - }) - return - } - editorRef.innerHTML = "" prompt.set([{ type: "text", content: "", start: 0, end: 0 }], 0) command.trigger(cmd.id, "slash") @@ -1733,11 +1706,6 @@ export const PromptInput: Component = (props) => { {language.t("prompt.slash.badge.custom")} - - - {language.t("prompt.slash.badge.skill")} - - {command.keybind(cmd.id)} diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index 6977b86a32..ad3d124b2c 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -17,7 +17,6 @@ import { type VcsInfo, type PermissionRequest, type QuestionRequest, - type AppSkillsResponse, createOpencodeClient, } from "@opencode-ai/sdk/v2/client" import { createStore, produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store" @@ -57,13 +56,10 @@ type ProjectMeta = { } } -export type Skill = AppSkillsResponse[number] - type State = { status: "loading" | "partial" | "complete" agent: Agent[] command: Command[] - skill: Skill[] project: string projectMeta: ProjectMeta | undefined icon: string | undefined @@ -392,7 +388,6 @@ function createGlobalSync() { status: "loading" as const, agent: [], command: [], - skill: [], session: [], sessionTotal: 0, session_status: {}, @@ -533,7 +528,6 @@ function createGlobalSync() { Promise.all([ sdk.path.get().then((x) => setStore("path", x.data!)), sdk.command.list().then((x) => setStore("command", x.data ?? [])), - sdk.app.skills().then((x) => setStore("skill", x.data ?? [])), sdk.session.status().then((x) => setStore("session_status", x.data!)), loadSessions(directory), sdk.mcp.status().then((x) => setStore("mcp", x.data!)), diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 7b18f54aff..a6a50506a0 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -216,7 +216,6 @@ export const dict = { "prompt.popover.emptyCommands": "No matching commands", "prompt.dropzone.label": "Drop images or PDFs here", "prompt.slash.badge.custom": "custom", - "prompt.slash.badge.skill": "skill", "prompt.context.active": "active", "prompt.context.includeActiveFile": "Include active file", "prompt.context.removeActiveFile": "Remove active file from context", diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 0c2ef61a62..bd000e2ab0 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -359,20 +359,6 @@ export function Autocomplete(props: { }) } - for (const skill of sync.data.skill) { - results.push({ - display: "/skill:" + skill.name, - description: skill.description, - onSelect: () => { - const newText = `Load the "${skill.name}" skill and follow its instructions.` - const cursor = props.input().logicalCursor - props.input().deleteRange(0, 0, cursor.row, cursor.col) - props.input().insertText(newText) - props.input().cursorOffset = Bun.stringWidth(newText) - }, - }) - } - results.sort((a, b) => a.display.localeCompare(b.display)) const max = firstBy(results, [(x) => x.display.length, "desc"])?.display.length diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index e7fedd6c35..eb8ed2d9bb 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -17,7 +17,6 @@ import type { ProviderListResponse, ProviderAuthMethod, VcsInfo, - AppSkillsResponse, } from "@opencode-ai/sdk/v2" import { createStore, produce, reconcile } from "solid-js/store" import { useSDK } from "@tui/context/sdk" @@ -41,7 +40,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ provider_auth: Record agent: Agent[] command: Command[] - skill: AppSkillsResponse permission: { [sessionID: string]: PermissionRequest[] } @@ -88,7 +86,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ permission: {}, question: {}, command: [], - skill: [], provider: [], provider_default: {}, session: [], @@ -388,7 +385,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ Promise.all([ ...(args.continue ? [] : [sessionListPromise.then((sessions) => setStore("session", reconcile(sessions)))]), sdk.client.command.list().then((x) => setStore("command", reconcile(x.data ?? []))), - sdk.client.app.skills().then((x) => setStore("skill", reconcile(x.data ?? []))), sdk.client.lsp.status().then((x) => setStore("lsp", reconcile(x.data!))), sdk.client.mcp.status().then((x) => setStore("mcp", reconcile(x.data!))), sdk.client.experimental.resource.list().then((x) => setStore("mcp_resource", reconcile(x.data ?? {}))), From feca42b0255b5a099477ee7ce60b51eb5911a055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 31 Jan 2026 16:26:23 +0100 Subject: [PATCH 53/58] feat(opencode): add reasoning variants support for SAP AI Core (#8753) Co-authored-by: Github Action --- packages/opencode/src/provider/transform.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 05e2272415..f5fe419db9 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -575,6 +575,26 @@ export namespace ProviderTransform { case "@ai-sdk/perplexity": // https://v5.ai-sdk.dev/providers/ai-sdk-providers/perplexity return {} + + case "@mymediset/sap-ai-provider": + case "@jerome-benoit/sap-ai-provider-v2": + if (model.api.id.includes("anthropic")) { + return { + high: { + thinking: { + type: "enabled", + budgetTokens: 16000, + }, + }, + max: { + thinking: { + type: "enabled", + budgetTokens: 31999, + }, + }, + } + } + return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }])) } return {} } From 35f64b80fa6825f8c14fd1654a1331b19db94a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E7=8C=AB=E5=AD=90?= Date: Sun, 1 Feb 2026 02:30:45 +0800 Subject: [PATCH 54/58] docs: fix documentation issues (#11435) Co-authored-by: damaozi <1811866786@qq.com> --- .../src/cli/cmd/tui/component/tips.tsx | 2 +- packages/web/src/content/docs/lsp.mdx | 44 +++++++++++++++++++ packages/web/src/content/docs/providers.mdx | 4 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/tips.tsx b/packages/opencode/src/cli/cmd/tui/component/tips.tsx index 3f0318e269..7870ab2ea4 100644 --- a/packages/opencode/src/cli/cmd/tui/component/tips.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/tips.tsx @@ -100,7 +100,7 @@ const TIPS = [ 'Set {highlight}"formatter": false{/highlight} in config to disable all auto-formatting', "Define custom formatter commands with file extensions in config", "OpenCode uses LSP servers for intelligent code analysis", - "Create {highlight}.ts{/highlight} files in {highlight}.opencode/tool/{/highlight} to define new LLM tools", + "Create {highlight}.ts{/highlight} files in {highlight}.opencode/tools/{/highlight} to define new LLM tools", "Tool definitions can invoke scripts written in Python, Go, etc", "Add {highlight}.ts{/highlight} files to {highlight}.opencode/plugin/{/highlight} for event hooks", "Use plugins to send OS notifications when sessions complete", diff --git a/packages/web/src/content/docs/lsp.mdx b/packages/web/src/content/docs/lsp.mdx index c1d23d4f50..707af84a01 100644 --- a/packages/web/src/content/docs/lsp.mdx +++ b/packages/web/src/content/docs/lsp.mdx @@ -87,6 +87,50 @@ Let's look at some examples. --- +### Environment variables + +Use the `env` property to set environment variables when starting the LSP server: + +```json title="opencode.json" {5-7} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "rust": { + "env": { + "RUST_LOG": "debug" + } + } + } +} +``` + +--- + +### Initialization options + +Use the `initialization` property to pass initialization options to the LSP server. These are server-specific settings sent during the LSP `initialize` request: + +```json title="opencode.json" {5-9} +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "initialization": { + "preferences": { + "importModuleSpecifierPreference": "relative" + } + } + } + } +} +``` + +:::note +Initialization options vary by LSP server. Check your LSP server's documentation for available options. +::: + +--- + ### Disabling LSP servers To disable **all** LSP servers globally, set `lsp` to `false`: diff --git a/packages/web/src/content/docs/providers.mdx b/packages/web/src/content/docs/providers.mdx index 2a80394528..6852672149 100644 --- a/packages/web/src/content/docs/providers.mdx +++ b/packages/web/src/content/docs/providers.mdx @@ -1222,6 +1222,10 @@ To use Kimi K2 from Moonshot AI: You can configure opencode to use local models through Ollama. +:::tip +Ollama can automatically configure itself for OpenCode. See the [Ollama integration docs](https://docs.ollama.com/integrations/opencode) for details. +::: + ```json title="opencode.json" "ollama" {5, 6, 8, 10-14} { "$schema": "https://opencode.ai/config.json", From 121d6a72c0bc62c8a0699db87fb4f11b1bb73a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 31 Jan 2026 19:32:11 +0100 Subject: [PATCH 55/58] fix(nix): restore native runners for darwin hash computation (#11495) --- .github/workflows/nix-hashes.yml | 167 +++++++++++++++++-------------- flake.nix | 23 +---- nix/node_modules.nix | 11 +- 3 files changed, 99 insertions(+), 102 deletions(-) diff --git a/.github/workflows/nix-hashes.yml b/.github/workflows/nix-hashes.yml index 061b4ada8d..bb4db70882 100644 --- a/.github/workflows/nix-hashes.yml +++ b/.github/workflows/nix-hashes.yml @@ -21,11 +21,68 @@ on: - ".github/workflows/nix-hashes.yml" jobs: - nix-hashes: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + # Native runners required: bun install cross-compilation flags (--os/--cpu) + # do not produce byte-identical node_modules as native installs. + compute-hash: + strategy: + fail-fast: false + matrix: + include: + - system: x86_64-linux + runner: blacksmith-4vcpu-ubuntu-2404 + - system: aarch64-linux + runner: blacksmith-4vcpu-ubuntu-2404-arm + - system: x86_64-darwin + runner: macos-15-intel + - system: aarch64-darwin + runner: macos-latest + runs-on: ${{ matrix.runner }} + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Nix + uses: nixbuild/nix-quick-install-action@v34 + + - name: Compute node_modules hash + id: hash + env: + SYSTEM: ${{ matrix.system }} + run: | + set -euo pipefail + + BUILD_LOG=$(mktemp) + trap 'rm -f "$BUILD_LOG"' EXIT + + # Build with fakeHash to trigger hash mismatch and reveal correct hash + nix build ".#packages.${SYSTEM}.node_modules_updater" --no-link 2>&1 | tee "$BUILD_LOG" || true + + HASH="$(grep -E 'got:\s+sha256-' "$BUILD_LOG" | sed -E 's/.*got:\s+(sha256-[A-Za-z0-9+/=]+).*/\1/' | head -n1 || true)" + if [ -z "$HASH" ]; then + HASH="$(grep -A2 'hash mismatch' "$BUILD_LOG" | grep 'got:' | sed -E 's/.*got:\s+(sha256-[A-Za-z0-9+/=]+).*/\1/' | head -n1 || true)" + fi + + if [ -z "$HASH" ]; then + echo "::error::Failed to compute hash for ${SYSTEM}" + cat "$BUILD_LOG" + exit 1 + fi + + echo "$HASH" > hash.txt + echo "Computed hash for ${SYSTEM}: $HASH" + + - name: Upload hash + uses: actions/upload-artifact@v4 + with: + name: hash-${{ matrix.system }} + path: hash.txt + retention-days: 1 + + update-hashes: + needs: compute-hash + if: github.event_name != 'pull_request' runs-on: blacksmith-4vcpu-ubuntu-2404 - env: - TITLE: node_modules hashes steps: - name: Checkout repository @@ -33,108 +90,64 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - ref: ${{ github.head_ref || github.ref_name }} - repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + ref: ${{ github.ref_name }} - name: Setup git committer - id: committer uses: ./.github/actions/setup-git-committer with: opencode-app-id: ${{ vars.OPENCODE_APP_ID }} opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - name: Setup Nix - uses: nixbuild/nix-quick-install-action@v34 - - name: Pull latest changes - env: - TARGET_BRANCH: ${{ github.head_ref || github.ref_name }} run: | - BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}" - git pull --rebase --autostash origin "$BRANCH" + git pull --rebase --autostash origin "$GITHUB_REF_NAME" - - name: Compute all node_modules hashes + - name: Download hash artifacts + uses: actions/download-artifact@v4 + with: + path: hashes + pattern: hash-* + + - name: Update hashes.json run: | set -euo pipefail HASH_FILE="nix/hashes.json" - SYSTEMS="x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin" - if [ ! -f "$HASH_FILE" ]; then - mkdir -p "$(dirname "$HASH_FILE")" - echo '{"nodeModules":{}}' > "$HASH_FILE" - fi + [ -f "$HASH_FILE" ] || echo '{"nodeModules":{}}' > "$HASH_FILE" - for SYSTEM in $SYSTEMS; do - echo "Computing hash for ${SYSTEM}..." - BUILD_LOG=$(mktemp) - trap 'rm -f "$BUILD_LOG"' EXIT - - # The updater derivations use fakeHash, so they will fail and reveal the correct hash - UPDATER_ATTR=".#packages.x86_64-linux.${SYSTEM}_node_modules" - - nix build "$UPDATER_ATTR" --no-link 2>&1 | tee "$BUILD_LOG" || true - - CORRECT_HASH="$(grep -E 'got:\s+sha256-[A-Za-z0-9+/=]+' "$BUILD_LOG" | awk '{print $2}' | head -n1 || true)" - - if [ -z "$CORRECT_HASH" ]; then - CORRECT_HASH="$(grep -A2 'hash mismatch' "$BUILD_LOG" | grep 'got:' | awk '{print $2}' | sed 's/sha256:/sha256-/' || true)" + for SYSTEM in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do + FILE="hashes/hash-${SYSTEM}/hash.txt" + if [ -f "$FILE" ]; then + HASH="$(tr -d '[:space:]' < "$FILE")" + echo "${SYSTEM}: ${HASH}" + jq --arg sys "$SYSTEM" --arg h "$HASH" '.nodeModules[$sys] = $h' "$HASH_FILE" > tmp.json + mv tmp.json "$HASH_FILE" + else + echo "::warning::Missing hash for ${SYSTEM}" fi - - if [ -z "$CORRECT_HASH" ]; then - echo "Failed to determine correct node_modules hash for ${SYSTEM}." - cat "$BUILD_LOG" - exit 1 - fi - - echo " ${SYSTEM}: ${CORRECT_HASH}" - jq --arg sys "$SYSTEM" --arg h "$CORRECT_HASH" \ - '.nodeModules[$sys] = $h' "$HASH_FILE" > "${HASH_FILE}.tmp" - mv "${HASH_FILE}.tmp" "$HASH_FILE" done - echo "All hashes computed:" cat "$HASH_FILE" - - name: Commit ${{ env.TITLE }} changes - env: - TARGET_BRANCH: ${{ github.head_ref || github.ref_name }} + - name: Commit changes run: | set -euo pipefail HASH_FILE="nix/hashes.json" - echo "Checking for changes..." - summarize() { - local status="$1" - { - echo "### Nix $TITLE" - echo "" - echo "- ref: ${GITHUB_REF_NAME}" - echo "- status: ${status}" - } >> "$GITHUB_STEP_SUMMARY" - if [ -n "${GITHUB_SERVER_URL:-}" ] && [ -n "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_RUN_ID:-}" ]; then - echo "- run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" >> "$GITHUB_STEP_SUMMARY" - fi - echo "" >> "$GITHUB_STEP_SUMMARY" - } - - FILES=("$HASH_FILE") - STATUS="$(git status --short -- "${FILES[@]}" || true)" - if [ -z "$STATUS" ]; then - echo "No changes detected." - summarize "no changes" + if [ -z "$(git status --short -- "$HASH_FILE")" ]; then + echo "No changes to commit" + echo "### Nix hashes" >> "$GITHUB_STEP_SUMMARY" + echo "Status: no changes" >> "$GITHUB_STEP_SUMMARY" exit 0 fi - echo "Changes detected:" - echo "$STATUS" - git add "${FILES[@]}" + git add "$HASH_FILE" git commit -m "chore: update nix node_modules hashes" - BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}" - git pull --rebase --autostash origin "$BRANCH" - git push origin HEAD:"$BRANCH" - echo "Changes pushed successfully" + git pull --rebase --autostash origin "$GITHUB_REF_NAME" + git push origin HEAD:"$GITHUB_REF_NAME" - summarize "committed $(git rev-parse --short HEAD)" + echo "### Nix hashes" >> "$GITHUB_STEP_SUMMARY" + echo "Status: committed $(git rev-parse --short HEAD)" >> "$GITHUB_STEP_SUMMARY" diff --git a/flake.nix b/flake.nix index e4d214a0b9..ea78b1a434 100644 --- a/flake.nix +++ b/flake.nix @@ -42,28 +42,15 @@ desktop = pkgs.callPackage ./nix/desktop.nix { inherit opencode; }; - # nixpkgs cpu naming to bun cpu naming - cpuMap = { x86_64 = "x64"; aarch64 = "arm64"; }; - # matrix of node_modules builds - these will always fail due to fakeHash usage - # but allow computation of the correct hash from any build machine for any cpu/os - # see the update-nix-hashes workflow for usage - moduleUpdaters = pkgs.lib.listToAttrs ( - pkgs.lib.concatMap (cpu: - map (os: { - name = "${cpu}-${os}_node_modules"; - value = node_modules.override { - bunCpu = cpuMap.${cpu}; - bunOs = os; - hash = pkgs.lib.fakeHash; - }; - }) [ "linux" "darwin" ] - ) [ "x86_64" "aarch64" ] - ); in { default = opencode; inherit opencode desktop; - } // moduleUpdaters + # Updater derivation with fakeHash - build fails and reveals correct hash + node_modules_updater = node_modules.override { + hash = pkgs.lib.fakeHash; + }; + } ); }; } diff --git a/nix/node_modules.nix b/nix/node_modules.nix index 981a60ef9b..6d75b9e750 100644 --- a/nix/node_modules.nix +++ b/nix/node_modules.nix @@ -2,8 +2,6 @@ lib, stdenvNoCC, bun, - bunCpu ? if stdenvNoCC.hostPlatform.isAarch64 then "arm64" else "x64", - bunOs ? if stdenvNoCC.hostPlatform.isLinux then "linux" else "darwin", rev ? "dirty", hash ? (lib.pipe ./hashes.json [ @@ -16,6 +14,9 @@ let builtins.readFile builtins.fromJSON ]; + platform = stdenvNoCC.hostPlatform; + bunCpu = if platform.isAarch64 then "arm64" else "x64"; + bunOs = if platform.isLinux then "linux" else "darwin"; in stdenvNoCC.mkDerivation { pname = "opencode-node_modules"; @@ -39,9 +40,7 @@ stdenvNoCC.mkDerivation { "SOCKS_SERVER" ]; - nativeBuildInputs = [ - bun - ]; + nativeBuildInputs = [ bun ]; dontConfigure = true; @@ -63,10 +62,8 @@ stdenvNoCC.mkDerivation { installPhase = '' runHook preInstall - mkdir -p $out find . -type d -name node_modules -exec cp -R --parents {} $out \; - runHook postInstall ''; From a19ef17bcbedc42b802c4de1edf5df4991d942f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 31 Jan 2026 19:35:23 +0100 Subject: [PATCH 56/58] fix(provider): use process.env directly for runtime env mutations (#11482) --- packages/opencode/src/provider/provider.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index e79cb17089..e01c583ff3 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -195,11 +195,13 @@ export namespace Provider { const awsAccessKeyId = Env.get("AWS_ACCESS_KEY_ID") + // TODO: Using process.env directly because Env.set only updates a process.env shallow copy, + // until the scope of the Env API is clarified (test only or runtime?) const awsBearerToken = iife(() => { - const envToken = Env.get("AWS_BEARER_TOKEN_BEDROCK") + const envToken = process.env.AWS_BEARER_TOKEN_BEDROCK if (envToken) return envToken if (auth?.type === "api") { - Env.set("AWS_BEARER_TOKEN_BEDROCK", auth.key) + process.env.AWS_BEARER_TOKEN_BEDROCK = auth.key return auth.key } return undefined @@ -376,17 +378,19 @@ export namespace Provider { }, "sap-ai-core": async () => { const auth = await Auth.get("sap-ai-core") + // TODO: Using process.env directly because Env.set only updates a shallow copy (not process.env), + // until the scope of the Env API is clarified (test only or runtime?) const envServiceKey = iife(() => { - const envAICoreServiceKey = Env.get("AICORE_SERVICE_KEY") + const envAICoreServiceKey = process.env.AICORE_SERVICE_KEY if (envAICoreServiceKey) return envAICoreServiceKey if (auth?.type === "api") { - Env.set("AICORE_SERVICE_KEY", auth.key) + process.env.AICORE_SERVICE_KEY = auth.key return auth.key } return undefined }) - const deploymentId = Env.get("AICORE_DEPLOYMENT_ID") - const resourceGroup = Env.get("AICORE_RESOURCE_GROUP") + const deploymentId = process.env.AICORE_DEPLOYMENT_ID + const resourceGroup = process.env.AICORE_RESOURCE_GROUP return { autoload: !!envServiceKey, From da7c874808b82544a9eb5981eb9ba83106b74378 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 31 Jan 2026 13:15:42 -0600 Subject: [PATCH 57/58] tweak: show actual retry error message instead of generic error msg (#11520) --- packages/opencode/src/session/retry.ts | 8 +------- packages/opencode/test/session/retry.test.ts | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/session/retry.ts b/packages/opencode/src/session/retry.ts index dddeae1cf3..a71a6a3824 100644 --- a/packages/opencode/src/session/retry.ts +++ b/packages/opencode/src/session/retry.ts @@ -89,13 +89,7 @@ export namespace SessionRetry { if (json.type === "error" && json.error?.code?.includes("rate_limit")) { return "Rate Limited" } - if ( - json.error?.message?.includes("no_kv_space") || - (json.type === "error" && json.error?.type === "server_error") || - !!json.error - ) { - return "Provider Server Error" - } + return JSON.stringify(json) } catch { return undefined } diff --git a/packages/opencode/test/session/retry.test.ts b/packages/opencode/test/session/retry.test.ts index 9cfdd7fca5..a483a01527 100644 --- a/packages/opencode/test/session/retry.test.ts +++ b/packages/opencode/test/session/retry.test.ts @@ -99,7 +99,7 @@ describe("session.retry.retryable", () => { test("handles json messages without code", () => { const error = wrap(JSON.stringify({ error: { message: "no_kv_space" } })) - expect(SessionRetry.retryable(error)).toBe("Provider Server Error") + expect(SessionRetry.retryable(error)).toBe(`{"error":{"message":"no_kv_space"}}`) }) test("does not throw on numeric error codes", () => { From e70d984320571597f89421d85c2f74009951027c Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 31 Jan 2026 14:42:36 -0500 Subject: [PATCH 58/58] tui: enable password authentication for remote session attachment Allow users to authenticate when attaching to a remote OpenCode session by supporting basic auth via a password flag or OPENCODE_SERVER_PASSWORD environment variable --- packages/opencode/src/cli/cmd/tui/app.tsx | 2 ++ packages/opencode/src/cli/cmd/tui/attach.ts | 21 +++++++++++++++---- .../opencode/src/cli/cmd/tui/context/sdk.tsx | 9 +++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 10d7a25f88..713def2e5a 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -104,6 +104,7 @@ export function tui(input: { args: Args directory?: string fetch?: typeof fetch + headers?: RequestInit["headers"] events?: EventSource onExit?: () => Promise }) { @@ -130,6 +131,7 @@ export function tui(input: { url={input.url} directory={input.directory} fetch={input.fetch} + headers={input.headers} events={input.events} > diff --git a/packages/opencode/src/cli/cmd/tui/attach.ts b/packages/opencode/src/cli/cmd/tui/attach.ts index f641ff0988..e852cb73d4 100644 --- a/packages/opencode/src/cli/cmd/tui/attach.ts +++ b/packages/opencode/src/cli/cmd/tui/attach.ts @@ -19,21 +19,34 @@ export const AttachCommand = cmd({ alias: ["s"], type: "string", describe: "session id to continue", + }) + .option("password", { + alias: ["p"], + type: "string", + describe: "basic auth password (defaults to OPENCODE_SERVER_PASSWORD)", }), handler: async (args) => { - let directory = args.dir - if (args.dir) { + const directory = (() => { + if (!args.dir) return undefined try { process.chdir(args.dir) - directory = process.cwd() + return process.cwd() } catch { // If the directory doesn't exist locally (remote attach), pass it through. + return args.dir } - } + })() + const headers = (() => { + const password = args.password ?? process.env.OPENCODE_SERVER_PASSWORD + if (!password) return undefined + const auth = `Basic ${Buffer.from(`opencode:${password}`).toString("base64")}` + return { Authorization: auth } + })() await tui({ url: args.url, args: { sessionID: args.session }, directory, + headers, }) }, }) diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx index 3339e7b00d..7fa7e05c3d 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx @@ -9,13 +9,20 @@ export type EventSource = { export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ name: "SDK", - init: (props: { url: string; directory?: string; fetch?: typeof fetch; events?: EventSource }) => { + init: (props: { + url: string + directory?: string + fetch?: typeof fetch + headers?: RequestInit["headers"] + events?: EventSource + }) => { const abort = new AbortController() const sdk = createOpencodeClient({ baseUrl: props.url, signal: abort.signal, directory: props.directory, fetch: props.fetch, + headers: props.headers, }) const emitter = createGlobalEmitter<{