mirror of
https://github.com/anomalyco/opencode.git
synced 2026-03-09 08:04:10 +00:00
Compare commits
16 Commits
fix/memory
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18fb19da3b | ||
|
|
849e1ac543 | ||
|
|
656a8d8f55 | ||
|
|
b976f339e8 | ||
|
|
7d7837e5b6 | ||
|
|
1db292f4df | ||
|
|
49a3a9fe36 | ||
|
|
e51ed460a6 | ||
|
|
d15c2ce349 | ||
|
|
5cc4bb4089 | ||
|
|
6e9e027886 | ||
|
|
f9a3d129a4 | ||
|
|
c53d1d3ad8 | ||
|
|
f386137fba | ||
|
|
c797b60069 | ||
|
|
a139e9297d |
39
bun.lock
39
bun.lock
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
@@ -76,7 +76,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -110,7 +110,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -137,7 +137,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "2.0.0",
|
||||
"@ai-sdk/openai": "2.0.2",
|
||||
@@ -161,7 +161,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -185,7 +185,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/app": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -218,7 +218,7 @@
|
||||
},
|
||||
"packages/desktop-electron": {
|
||||
"name": "@opencode-ai/desktop-electron",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/app": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -248,7 +248,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@opencode-ai/util": "workspace:*",
|
||||
@@ -277,7 +277,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -293,7 +293,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -409,7 +409,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"zod": "catalog:",
|
||||
@@ -429,7 +429,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "0.90.10",
|
||||
"@tsconfig/node22": "catalog:",
|
||||
@@ -440,7 +440,7 @@
|
||||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
@@ -475,7 +475,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
@@ -483,8 +483,11 @@
|
||||
"@pierre/diffs": "catalog:",
|
||||
"@shikijs/transformers": "3.9.2",
|
||||
"@solid-primitives/bounds": "0.1.3",
|
||||
"@solid-primitives/lifecycle": "0.1.2",
|
||||
"@solid-primitives/media": "2.3.3",
|
||||
"@solid-primitives/page-visibility": "2.1.1",
|
||||
"@solid-primitives/resize-observer": "2.1.3",
|
||||
"@solid-primitives/rootless": "1.5.2",
|
||||
"@solidjs/meta": "catalog:",
|
||||
"@solidjs/router": "catalog:",
|
||||
"dompurify": "3.3.1",
|
||||
@@ -521,7 +524,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"zod": "catalog:",
|
||||
},
|
||||
@@ -532,7 +535,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
@@ -1834,10 +1837,14 @@
|
||||
|
||||
"@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.3", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zNadtyYBhJSOjXtogkGHmRxjGdz9KHc8sGGVAGlUABkE8BED2tbIZoxkwSqzOwde8OcUEH0bb5DLZUWIMvyBSA=="],
|
||||
|
||||
"@solid-primitives/lifecycle": ["@solid-primitives/lifecycle@0.1.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-+K0T10kZXqorocFj0coIqt8NYm2UqoZfpF3nm2RwrDMZMV+C+SC0Oi3N6Dnq2i7W/n1cHAnfpoV4CBLsW21lJw=="],
|
||||
|
||||
"@solid-primitives/map": ["@solid-primitives/map@0.4.13", "", { "dependencies": { "@solid-primitives/trigger": "^1.1.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew=="],
|
||||
|
||||
"@solid-primitives/media": ["@solid-primitives/media@2.3.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-hQ4hLOGvfbugQi5Eu1BFWAIJGIAzztq9x0h02xgBGl2l0Jaa3h7tg6bz5tV1NSuNYVGio4rPoa7zVQQLkkx9dA=="],
|
||||
|
||||
"@solid-primitives/page-visibility": ["@solid-primitives/page-visibility@2.1.1", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.1", "@solid-primitives/rootless": "^1.5.1", "@solid-primitives/utils": "^6.3.1" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-CV9BqMqhunf4OOyBkhJCH9f5ivg0ADavdcaBsrqoFvwIk1FoD/blPSHYM4CK8IjS/AEXNcsjlNVc34lMu+2Wdg=="],
|
||||
|
||||
"@solid-primitives/props": ["@solid-primitives/props@3.2.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-lZOTwFJajBrshSyg14nBMEP0h8MXzPowGO0s3OeiR3z6nXHTfj0FhzDtJMv+VYoRJKQHG2QRnJTgCzK6erARAw=="],
|
||||
|
||||
"@solid-primitives/refs": ["@solid-primitives/refs@1.1.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-K7tf2thy7L+YJjdqXspXOg5xvNEOH8tgEWsp0+1mQk3obHBRD6hEjYZk7p7FlJphSZImS35je3UfmWuD7MhDfg=="],
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-4kjoJ06VNvHltPHfzQRBG0bC6R39jao10ffGzrNZ230=",
|
||||
"aarch64-linux": "sha256-6Uio+S2rcyBWbBEeOZb9N1CCKgkbKi68lOIKi3Ws/pQ=",
|
||||
"aarch64-darwin": "sha256-8ngN5KVN4vhdsk0QJ11BGgSVBrcaEbwSj23c77HBpgs=",
|
||||
"x86_64-darwin": "sha256-v/ueYGb9a0Nymzy+mkO4uQr78DAuJnES1qOT0onFgnQ="
|
||||
"x86_64-linux": "sha256-c99eE1cKAQHvwJosaFo42U9Hk0Rtp/U5oTTlyiz2Zw4=",
|
||||
"aarch64-linux": "sha256-LbdssPrf8Bijyp4mRo8QaO/swxwUWSo1g0jLPm2rvUA=",
|
||||
"aarch64-darwin": "sha256-0L9y6Zk4l2vAxsM2bENahhtRZY1C3XhdxLgnnYlhkkY=",
|
||||
"x86_64-darwin": "sha256-0J5sFG/kHHRDcTpdpdPBMJEOHwCRnAUYmbxEHPPLDvU="
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,16 +25,26 @@ test("closing active project navigates to another open project", async ({ page,
|
||||
await clickMenuItem(menu, /^Close$/i, { force: true })
|
||||
|
||||
await expect
|
||||
.poll(() => {
|
||||
const pathname = new URL(page.url()).pathname
|
||||
if (new RegExp(`^/${slug}/session(?:/[^/]+)?/?$`).test(pathname)) return "project"
|
||||
if (pathname === "/") return "home"
|
||||
return ""
|
||||
})
|
||||
.poll(
|
||||
() => {
|
||||
const pathname = new URL(page.url()).pathname
|
||||
if (new RegExp(`^/${slug}/session(?:/[^/]+)?/?$`).test(pathname)) return "project"
|
||||
if (pathname === "/") return "home"
|
||||
return ""
|
||||
},
|
||||
{ timeout: 15_000 },
|
||||
)
|
||||
.toMatch(/^(project|home)$/)
|
||||
|
||||
await expect(page).not.toHaveURL(new RegExp(`/${otherSlug}/session(?:[/?#]|$)`))
|
||||
await expect(otherButton).toHaveCount(0)
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
return await page.locator(projectSwitchSelector(otherSlug)).count()
|
||||
},
|
||||
{ timeout: 15_000 },
|
||||
)
|
||||
.toBe(0)
|
||||
},
|
||||
{ extra: [other] },
|
||||
)
|
||||
|
||||
@@ -83,16 +83,23 @@ test("changing theme persists in localStorage", async ({ page, gotoSession }) =>
|
||||
const select = dialog.locator(settingsThemeSelector)
|
||||
await expect(select).toBeVisible()
|
||||
|
||||
const currentThemeId = await page.evaluate(() => {
|
||||
return document.documentElement.getAttribute("data-theme")
|
||||
})
|
||||
const currentTheme = (await select.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? ""
|
||||
|
||||
await select.locator('[data-slot="select-select-trigger"]').click()
|
||||
|
||||
const items = page.locator('[data-slot="select-select-item"]')
|
||||
const count = await items.count()
|
||||
expect(count).toBeGreaterThan(1)
|
||||
|
||||
const firstTheme = await items.nth(1).locator('[data-slot="select-select-item-label"]').textContent()
|
||||
expect(firstTheme).toBeTruthy()
|
||||
const nextTheme = (await items.locator('[data-slot="select-select-item-label"]').allTextContents())
|
||||
.map((x) => x.trim())
|
||||
.find((x) => x && x !== currentTheme)
|
||||
expect(nextTheme).toBeTruthy()
|
||||
|
||||
await items.nth(1).click()
|
||||
await items.filter({ hasText: nextTheme! }).first().click()
|
||||
|
||||
await page.keyboard.press("Escape")
|
||||
|
||||
@@ -101,7 +108,7 @@ test("changing theme persists in localStorage", async ({ page, gotoSession }) =>
|
||||
})
|
||||
|
||||
expect(storedThemeId).not.toBeNull()
|
||||
expect(storedThemeId).not.toBe("oc-1")
|
||||
expect(storedThemeId).not.toBe(currentThemeId)
|
||||
|
||||
const dataTheme = await page.evaluate(() => {
|
||||
return document.documentElement.getAttribute("data-theme")
|
||||
|
||||
@@ -44,12 +44,14 @@ async function store(page: Page, key: string) {
|
||||
}, key)
|
||||
}
|
||||
|
||||
test("terminal tab buffers persist across tab switches", async ({ page, withProject }) => {
|
||||
test("inactive terminal tab buffers persist across tab switches", async ({ page, withProject }) => {
|
||||
await withProject(async ({ directory, gotoSession }) => {
|
||||
const key = workspacePersistKey(directory, "terminal")
|
||||
const one = `E2E_TERM_ONE_${Date.now()}`
|
||||
const two = `E2E_TERM_TWO_${Date.now()}`
|
||||
const tabs = page.locator('#terminal-panel [data-slot="tabs-trigger"]')
|
||||
const first = tabs.filter({ hasText: /Terminal 1/ }).first()
|
||||
const second = tabs.filter({ hasText: /Terminal 2/ }).first()
|
||||
|
||||
await gotoSession()
|
||||
await open(page)
|
||||
@@ -61,22 +63,39 @@ test("terminal tab buffers persist across tab switches", async ({ page, withProj
|
||||
|
||||
await run(page, `echo ${two}`)
|
||||
|
||||
await tabs
|
||||
.filter({ hasText: /Terminal 1/ })
|
||||
.first()
|
||||
.click()
|
||||
|
||||
await first.click()
|
||||
await expect(first).toHaveAttribute("aria-selected", "true")
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
const state = await store(page, key)
|
||||
const first = state?.all.find((item) => item.titleNumber === 1)?.buffer ?? ""
|
||||
const second = state?.all.find((item) => item.titleNumber === 2)?.buffer ?? ""
|
||||
return first.includes(one) && second.includes(two)
|
||||
return {
|
||||
first: first.includes(one),
|
||||
second: second.includes(two),
|
||||
}
|
||||
},
|
||||
{ timeout: 30_000 },
|
||||
)
|
||||
.toBe(true)
|
||||
.toEqual({ first: false, second: true })
|
||||
|
||||
await second.click()
|
||||
await expect(second).toHaveAttribute("aria-selected", "true")
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
const state = await store(page, key)
|
||||
const first = state?.all.find((item) => item.titleNumber === 1)?.buffer ?? ""
|
||||
const second = state?.all.find((item) => item.titleNumber === 2)?.buffer ?? ""
|
||||
return {
|
||||
first: first.includes(one),
|
||||
second: second.includes(two),
|
||||
}
|
||||
},
|
||||
{ timeout: 30_000 },
|
||||
)
|
||||
.toEqual({ first: true, second: false })
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
;(function () {
|
||||
var themeId = localStorage.getItem("opencode-theme-id")
|
||||
if (!themeId) return
|
||||
var themeId = localStorage.getItem("opencode-theme-id") || "oc-2"
|
||||
|
||||
var scheme = localStorage.getItem("opencode-color-scheme") || "system"
|
||||
var isDark = scheme === "dark" || (scheme === "system" && matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
@@ -9,9 +8,9 @@
|
||||
document.documentElement.dataset.theme = themeId
|
||||
document.documentElement.dataset.colorScheme = mode
|
||||
|
||||
if (themeId === "oc-1") return
|
||||
if (themeId === "oc-2") return
|
||||
|
||||
var css = localStorage.getItem("opencode-theme-css-" + themeId + "-" + mode)
|
||||
var css = localStorage.getItem("opencode-theme-css-" + mode)
|
||||
if (css) {
|
||||
var style = document.createElement("style")
|
||||
style.id = "oc-theme-preload"
|
||||
|
||||
@@ -217,7 +217,7 @@ export const Terminal = (props: TerminalProps) => {
|
||||
const currentTheme = theme.themes()[theme.themeId()]
|
||||
if (!currentTheme) return fallback
|
||||
const variant = mode === "dark" ? currentTheme.dark : currentTheme.light
|
||||
if (!variant?.seeds) return fallback
|
||||
if (!variant?.seeds && !variant?.palette) return fallback
|
||||
const resolved = resolveThemeVariant(variant, mode === "dark")
|
||||
const text = resolved["text-stronger"] ?? fallback.foreground
|
||||
const background = resolved["background-stronger"] ?? fallback.background
|
||||
|
||||
@@ -27,7 +27,7 @@ import type { InitError } from "../pages/error"
|
||||
import { useGlobalSDK } from "./global-sdk"
|
||||
import { bootstrapDirectory, bootstrapGlobal } from "./global-sync/bootstrap"
|
||||
import { createChildStoreManager } from "./global-sync/child-store"
|
||||
import { applyDirectoryEvent, applyGlobalEvent } from "./global-sync/event-reducer"
|
||||
import { applyDirectoryEvent, applyGlobalEvent, cleanupDroppedSessionCaches } from "./global-sync/event-reducer"
|
||||
import { createRefreshQueue } from "./global-sync/queue"
|
||||
import { estimateRootSessionTotal, loadRootSessionsWithFallback } from "./global-sync/session-load"
|
||||
import { trimSessions } from "./global-sync/session-trim"
|
||||
@@ -189,6 +189,7 @@ function createGlobalSync() {
|
||||
})
|
||||
if (next.length !== store.session.length) {
|
||||
setStore("session", reconcile(next, { key: "id" }))
|
||||
cleanupDroppedSessionCaches(store, setStore, next, setSessionTodo)
|
||||
}
|
||||
children.unpin(directory)
|
||||
return
|
||||
@@ -220,6 +221,7 @@ function createGlobalSync() {
|
||||
}),
|
||||
)
|
||||
setStore("session", reconcile(sessions, { key: "id" }))
|
||||
cleanupDroppedSessionCaches(store, setStore, sessions, setSessionTodo)
|
||||
sessionMeta.set(directory, { limit })
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"
|
||||
import type { Message, Part, PermissionRequest, Project, QuestionRequest, Session } from "@opencode-ai/sdk/v2/client"
|
||||
import { createStore } from "solid-js/store"
|
||||
import type { State } from "./types"
|
||||
import { applyDirectoryEvent, applyGlobalEvent } from "./event-reducer"
|
||||
import { applyDirectoryEvent, applyGlobalEvent, cleanupDroppedSessionCaches } from "./event-reducer"
|
||||
|
||||
const rootSession = (input: { id: string; parentID?: string; archived?: number }) =>
|
||||
({
|
||||
@@ -248,6 +248,62 @@ describe("applyDirectoryEvent", () => {
|
||||
}
|
||||
})
|
||||
|
||||
test("cleans caches for trimmed sessions on session.created", () => {
|
||||
const dropped = rootSession({ id: "ses_b" })
|
||||
const kept = rootSession({ id: "ses_a" })
|
||||
const message = userMessage("msg_1", dropped.id)
|
||||
const todos: string[] = []
|
||||
const [store, setStore] = createStore(
|
||||
baseState({
|
||||
limit: 1,
|
||||
session: [dropped],
|
||||
message: { [dropped.id]: [message] },
|
||||
part: { [message.id]: [textPart("prt_1", dropped.id, message.id)] },
|
||||
session_diff: { [dropped.id]: [] },
|
||||
todo: { [dropped.id]: [] },
|
||||
permission: { [dropped.id]: [] },
|
||||
question: { [dropped.id]: [] },
|
||||
session_status: { [dropped.id]: { type: "busy" } },
|
||||
}),
|
||||
)
|
||||
|
||||
applyDirectoryEvent({
|
||||
event: { type: "session.created", properties: { info: kept } },
|
||||
store,
|
||||
setStore,
|
||||
push() {},
|
||||
directory: "/tmp",
|
||||
loadLsp() {},
|
||||
setSessionTodo(sessionID, value) {
|
||||
if (value !== undefined) return
|
||||
todos.push(sessionID)
|
||||
},
|
||||
})
|
||||
|
||||
expect(store.session.map((x) => x.id)).toEqual([kept.id])
|
||||
expect(store.message[dropped.id]).toBeUndefined()
|
||||
expect(store.part[message.id]).toBeUndefined()
|
||||
expect(store.session_diff[dropped.id]).toBeUndefined()
|
||||
expect(store.todo[dropped.id]).toBeUndefined()
|
||||
expect(store.permission[dropped.id]).toBeUndefined()
|
||||
expect(store.question[dropped.id]).toBeUndefined()
|
||||
expect(store.session_status[dropped.id]).toBeUndefined()
|
||||
expect(todos).toEqual([dropped.id])
|
||||
})
|
||||
|
||||
test("cleanupDroppedSessionCaches clears part-only orphan state", () => {
|
||||
const [store, setStore] = createStore(
|
||||
baseState({
|
||||
session: [rootSession({ id: "ses_keep" })],
|
||||
part: { msg_1: [textPart("prt_1", "ses_drop", "msg_1")] },
|
||||
}),
|
||||
)
|
||||
|
||||
cleanupDroppedSessionCaches(store, setStore, store.session)
|
||||
|
||||
expect(store.part.msg_1).toBeUndefined()
|
||||
})
|
||||
|
||||
test("upserts and removes messages while clearing orphaned parts", () => {
|
||||
const sessionID = "ses_1"
|
||||
const [store, setStore] = createStore(
|
||||
|
||||
@@ -13,6 +13,7 @@ import type {
|
||||
} from "@opencode-ai/sdk/v2/client"
|
||||
import type { State, VcsCache } from "./types"
|
||||
import { trimSessions } from "./session-trim"
|
||||
import { dropSessionCaches } from "./session-cache"
|
||||
|
||||
export function applyGlobalEvent(input: {
|
||||
event: { type: string; properties?: unknown }
|
||||
@@ -40,37 +41,44 @@ export function applyGlobalEvent(input: {
|
||||
}
|
||||
|
||||
function cleanupSessionCaches(
|
||||
store: Store<State>,
|
||||
setStore: SetStoreFunction<State>,
|
||||
sessionID: string,
|
||||
setSessionTodo?: (sessionID: string, todos: Todo[] | undefined) => void,
|
||||
) {
|
||||
if (!sessionID) return
|
||||
const hasAny =
|
||||
store.message[sessionID] !== undefined ||
|
||||
store.session_diff[sessionID] !== undefined ||
|
||||
store.todo[sessionID] !== undefined ||
|
||||
store.permission[sessionID] !== undefined ||
|
||||
store.question[sessionID] !== undefined ||
|
||||
store.session_status[sessionID] !== undefined
|
||||
setSessionTodo?.(sessionID, undefined)
|
||||
if (!hasAny) return
|
||||
setStore(
|
||||
produce((draft) => {
|
||||
const messages = draft.message[sessionID]
|
||||
if (messages) {
|
||||
for (const message of messages) {
|
||||
const id = message?.id
|
||||
if (!id) continue
|
||||
delete draft.part[id]
|
||||
}
|
||||
}
|
||||
delete draft.message[sessionID]
|
||||
delete draft.session_diff[sessionID]
|
||||
delete draft.todo[sessionID]
|
||||
delete draft.permission[sessionID]
|
||||
delete draft.question[sessionID]
|
||||
delete draft.session_status[sessionID]
|
||||
dropSessionCaches(draft, [sessionID])
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
export function cleanupDroppedSessionCaches(
|
||||
store: Store<State>,
|
||||
setStore: SetStoreFunction<State>,
|
||||
next: Session[],
|
||||
setSessionTodo?: (sessionID: string, todos: Todo[] | undefined) => void,
|
||||
) {
|
||||
const keep = new Set(next.map((item) => item.id))
|
||||
const stale = [
|
||||
...Object.keys(store.message),
|
||||
...Object.keys(store.session_diff),
|
||||
...Object.keys(store.todo),
|
||||
...Object.keys(store.permission),
|
||||
...Object.keys(store.question),
|
||||
...Object.keys(store.session_status),
|
||||
...Object.values(store.part)
|
||||
.map((parts) => parts?.find((part) => !!part?.sessionID)?.sessionID)
|
||||
.filter((sessionID): sessionID is string => !!sessionID),
|
||||
].filter((sessionID, index, list) => !keep.has(sessionID) && list.indexOf(sessionID) === index)
|
||||
if (stale.length === 0) return
|
||||
for (const sessionID of stale) {
|
||||
setSessionTodo?.(sessionID, undefined)
|
||||
}
|
||||
setStore(
|
||||
produce((draft) => {
|
||||
dropSessionCaches(draft, stale)
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -102,6 +110,7 @@ export function applyDirectoryEvent(input: {
|
||||
next.splice(result.index, 0, info)
|
||||
const trimmed = trimSessions(next, { limit: input.store.limit, permission: input.store.permission })
|
||||
input.setStore("session", reconcile(trimmed, { key: "id" }))
|
||||
cleanupDroppedSessionCaches(input.store, input.setStore, trimmed, input.setSessionTodo)
|
||||
if (!info.parentID) input.setStore("sessionTotal", (value) => value + 1)
|
||||
break
|
||||
}
|
||||
@@ -117,7 +126,7 @@ export function applyDirectoryEvent(input: {
|
||||
}),
|
||||
)
|
||||
}
|
||||
cleanupSessionCaches(input.store, input.setStore, info.id, input.setSessionTodo)
|
||||
cleanupSessionCaches(input.setStore, info.id, input.setSessionTodo)
|
||||
if (info.parentID) break
|
||||
input.setStore("sessionTotal", (value) => Math.max(0, value - 1))
|
||||
break
|
||||
@@ -130,6 +139,7 @@ export function applyDirectoryEvent(input: {
|
||||
next.splice(result.index, 0, info)
|
||||
const trimmed = trimSessions(next, { limit: input.store.limit, permission: input.store.permission })
|
||||
input.setStore("session", reconcile(trimmed, { key: "id" }))
|
||||
cleanupDroppedSessionCaches(input.store, input.setStore, trimmed, input.setSessionTodo)
|
||||
break
|
||||
}
|
||||
case "session.deleted": {
|
||||
@@ -143,7 +153,7 @@ export function applyDirectoryEvent(input: {
|
||||
}),
|
||||
)
|
||||
}
|
||||
cleanupSessionCaches(input.store, input.setStore, info.id, input.setSessionTodo)
|
||||
cleanupSessionCaches(input.setStore, info.id, input.setSessionTodo)
|
||||
if (info.parentID) break
|
||||
input.setStore("sessionTotal", (value) => Math.max(0, value - 1))
|
||||
break
|
||||
|
||||
102
packages/app/src/context/global-sync/session-cache.test.ts
Normal file
102
packages/app/src/context/global-sync/session-cache.test.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import type {
|
||||
FileDiff,
|
||||
Message,
|
||||
Part,
|
||||
PermissionRequest,
|
||||
QuestionRequest,
|
||||
SessionStatus,
|
||||
Todo,
|
||||
} from "@opencode-ai/sdk/v2/client"
|
||||
import { dropSessionCaches, pickSessionCacheEvictions } from "./session-cache"
|
||||
|
||||
const msg = (id: string, sessionID: string) =>
|
||||
({
|
||||
id,
|
||||
sessionID,
|
||||
role: "user",
|
||||
time: { created: 1 },
|
||||
agent: "assistant",
|
||||
model: { providerID: "openai", modelID: "gpt" },
|
||||
}) as Message
|
||||
|
||||
const part = (id: string, sessionID: string, messageID: string) =>
|
||||
({
|
||||
id,
|
||||
sessionID,
|
||||
messageID,
|
||||
type: "text",
|
||||
text: id,
|
||||
}) as Part
|
||||
|
||||
describe("app session cache", () => {
|
||||
test("dropSessionCaches clears orphaned parts without message rows", () => {
|
||||
const store: {
|
||||
session_status: Record<string, SessionStatus | undefined>
|
||||
session_diff: Record<string, FileDiff[] | undefined>
|
||||
todo: Record<string, Todo[] | undefined>
|
||||
message: Record<string, Message[] | undefined>
|
||||
part: Record<string, Part[] | undefined>
|
||||
permission: Record<string, PermissionRequest[] | undefined>
|
||||
question: Record<string, QuestionRequest[] | undefined>
|
||||
} = {
|
||||
session_status: { ses_1: { type: "busy" } as SessionStatus },
|
||||
session_diff: { ses_1: [] },
|
||||
todo: { ses_1: [] as Todo[] },
|
||||
message: {},
|
||||
part: { msg_1: [part("prt_1", "ses_1", "msg_1")] },
|
||||
permission: { ses_1: [] as PermissionRequest[] },
|
||||
question: { ses_1: [] as QuestionRequest[] },
|
||||
}
|
||||
|
||||
dropSessionCaches(store, ["ses_1"])
|
||||
|
||||
expect(store.message.ses_1).toBeUndefined()
|
||||
expect(store.part.msg_1).toBeUndefined()
|
||||
expect(store.todo.ses_1).toBeUndefined()
|
||||
expect(store.session_diff.ses_1).toBeUndefined()
|
||||
expect(store.session_status.ses_1).toBeUndefined()
|
||||
expect(store.permission.ses_1).toBeUndefined()
|
||||
expect(store.question.ses_1).toBeUndefined()
|
||||
})
|
||||
|
||||
test("dropSessionCaches clears message-backed parts", () => {
|
||||
const m = msg("msg_1", "ses_1")
|
||||
const store: {
|
||||
session_status: Record<string, SessionStatus | undefined>
|
||||
session_diff: Record<string, FileDiff[] | undefined>
|
||||
todo: Record<string, Todo[] | undefined>
|
||||
message: Record<string, Message[] | undefined>
|
||||
part: Record<string, Part[] | undefined>
|
||||
permission: Record<string, PermissionRequest[] | undefined>
|
||||
question: Record<string, QuestionRequest[] | undefined>
|
||||
} = {
|
||||
session_status: {},
|
||||
session_diff: {},
|
||||
todo: {},
|
||||
message: { ses_1: [m] },
|
||||
part: { [m.id]: [part("prt_1", "ses_1", m.id)] },
|
||||
permission: {},
|
||||
question: {},
|
||||
}
|
||||
|
||||
dropSessionCaches(store, ["ses_1"])
|
||||
|
||||
expect(store.message.ses_1).toBeUndefined()
|
||||
expect(store.part[m.id]).toBeUndefined()
|
||||
})
|
||||
|
||||
test("pickSessionCacheEvictions preserves requested sessions", () => {
|
||||
const seen = new Set(["ses_1", "ses_2", "ses_3"])
|
||||
|
||||
const stale = pickSessionCacheEvictions({
|
||||
seen,
|
||||
keep: "ses_4",
|
||||
limit: 2,
|
||||
preserve: ["ses_1"],
|
||||
})
|
||||
|
||||
expect(stale).toEqual(["ses_2", "ses_3"])
|
||||
expect([...seen]).toEqual(["ses_1", "ses_4"])
|
||||
})
|
||||
})
|
||||
62
packages/app/src/context/global-sync/session-cache.ts
Normal file
62
packages/app/src/context/global-sync/session-cache.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import type {
|
||||
FileDiff,
|
||||
Message,
|
||||
Part,
|
||||
PermissionRequest,
|
||||
QuestionRequest,
|
||||
SessionStatus,
|
||||
Todo,
|
||||
} from "@opencode-ai/sdk/v2/client"
|
||||
|
||||
export const SESSION_CACHE_LIMIT = 40
|
||||
|
||||
type SessionCache = {
|
||||
session_status: Record<string, SessionStatus | undefined>
|
||||
session_diff: Record<string, FileDiff[] | undefined>
|
||||
todo: Record<string, Todo[] | undefined>
|
||||
message: Record<string, Message[] | undefined>
|
||||
part: Record<string, Part[] | undefined>
|
||||
permission: Record<string, PermissionRequest[] | undefined>
|
||||
question: Record<string, QuestionRequest[] | undefined>
|
||||
}
|
||||
|
||||
export function dropSessionCaches(store: SessionCache, sessionIDs: Iterable<string>) {
|
||||
const stale = new Set(Array.from(sessionIDs).filter(Boolean))
|
||||
if (stale.size === 0) return
|
||||
|
||||
for (const key of Object.keys(store.part)) {
|
||||
const parts = store.part[key]
|
||||
if (!parts?.some((part) => stale.has(part?.sessionID ?? ""))) continue
|
||||
delete store.part[key]
|
||||
}
|
||||
|
||||
for (const sessionID of stale) {
|
||||
delete store.message[sessionID]
|
||||
delete store.todo[sessionID]
|
||||
delete store.session_diff[sessionID]
|
||||
delete store.session_status[sessionID]
|
||||
delete store.permission[sessionID]
|
||||
delete store.question[sessionID]
|
||||
}
|
||||
}
|
||||
|
||||
export function pickSessionCacheEvictions(input: {
|
||||
seen: Set<string>
|
||||
keep: string
|
||||
limit: number
|
||||
preserve?: Iterable<string>
|
||||
}) {
|
||||
const stale: string[] = []
|
||||
const keep = new Set([input.keep, ...Array.from(input.preserve ?? [])])
|
||||
if (input.seen.has(input.keep)) input.seen.delete(input.keep)
|
||||
input.seen.add(input.keep)
|
||||
for (const id of input.seen) {
|
||||
if (input.seen.size - stale.length <= input.limit) break
|
||||
if (keep.has(id)) continue
|
||||
stale.push(id)
|
||||
}
|
||||
for (const id of stale) {
|
||||
input.seen.delete(id)
|
||||
}
|
||||
return stale
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||
import { useGlobalSync } from "./global-sync"
|
||||
import { useSDK } from "./sdk"
|
||||
import type { Message, Part } from "@opencode-ai/sdk/v2/client"
|
||||
import { SESSION_CACHE_LIMIT, dropSessionCaches, pickSessionCacheEvictions } from "./global-sync/session-cache"
|
||||
|
||||
function sortParts(parts: Part[]) {
|
||||
return parts.filter((part) => !!part?.id).sort((a, b) => cmp(a.id, b.id))
|
||||
@@ -108,6 +109,8 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const inflight = new Map<string, Promise<void>>()
|
||||
const inflightDiff = new Map<string, Promise<void>>()
|
||||
const inflightTodo = new Map<string, Promise<void>>()
|
||||
const maxDirs = 30
|
||||
const seen = new Map<string, Set<string>>()
|
||||
const [meta, setMeta] = createStore({
|
||||
limit: {} as Record<string, number>,
|
||||
complete: {} as Record<string, boolean>,
|
||||
@@ -121,6 +124,62 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
return undefined
|
||||
}
|
||||
|
||||
const seenFor = (directory: string) => {
|
||||
const existing = seen.get(directory)
|
||||
if (existing) {
|
||||
seen.delete(directory)
|
||||
seen.set(directory, existing)
|
||||
return existing
|
||||
}
|
||||
const created = new Set<string>()
|
||||
seen.set(directory, created)
|
||||
while (seen.size > maxDirs) {
|
||||
const first = seen.keys().next().value
|
||||
if (!first) break
|
||||
const stale = [...(seen.get(first) ?? [])]
|
||||
seen.delete(first)
|
||||
const [, setStore] = globalSync.child(first, { bootstrap: false })
|
||||
evict(first, setStore, stale)
|
||||
}
|
||||
return created
|
||||
}
|
||||
|
||||
const clearMeta = (directory: string, sessionIDs: string[]) => {
|
||||
if (sessionIDs.length === 0) return
|
||||
setMeta(
|
||||
produce((draft) => {
|
||||
for (const sessionID of sessionIDs) {
|
||||
const key = keyFor(directory, sessionID)
|
||||
delete draft.limit[key]
|
||||
delete draft.complete[key]
|
||||
delete draft.loading[key]
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
const evict = (directory: string, setStore: Setter, sessionIDs: string[]) => {
|
||||
if (sessionIDs.length === 0) return
|
||||
for (const sessionID of sessionIDs) {
|
||||
globalSync.todo.set(sessionID, undefined)
|
||||
}
|
||||
setStore(
|
||||
produce((draft) => {
|
||||
dropSessionCaches(draft, sessionIDs)
|
||||
}),
|
||||
)
|
||||
clearMeta(directory, sessionIDs)
|
||||
}
|
||||
|
||||
const touch = (directory: string, setStore: Setter, sessionID: string) => {
|
||||
const stale = pickSessionCacheEvictions({
|
||||
seen: seenFor(directory),
|
||||
keep: sessionID,
|
||||
limit: SESSION_CACHE_LIMIT,
|
||||
})
|
||||
evict(directory, setStore, stale)
|
||||
}
|
||||
|
||||
const fetchMessages = async (input: { client: typeof sdk.client; sessionID: string; limit: number }) => {
|
||||
const messages = await retry(() =>
|
||||
input.client.session.messages({ sessionID: input.sessionID, limit: input.limit }),
|
||||
@@ -135,6 +194,8 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
}
|
||||
}
|
||||
|
||||
const tracked = (directory: string, sessionID: string) => seen.get(directory)?.has(sessionID) ?? false
|
||||
|
||||
const loadMessages = async (input: {
|
||||
directory: string
|
||||
client: typeof sdk.client
|
||||
@@ -148,6 +209,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
setMeta("loading", key, true)
|
||||
await fetchMessages(input)
|
||||
.then((next) => {
|
||||
if (!tracked(input.directory, input.sessionID)) return
|
||||
batch(() => {
|
||||
input.setStore("message", input.sessionID, reconcile(next.session, { key: "id" }))
|
||||
for (const p of next.part) {
|
||||
@@ -158,6 +220,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
if (!tracked(input.directory, input.sessionID)) return
|
||||
setMeta("loading", key, false)
|
||||
})
|
||||
}
|
||||
@@ -224,11 +287,16 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const key = keyFor(directory, sessionID)
|
||||
const hasSession = Binary.search(store.session, sessionID, (s) => s.id).found
|
||||
|
||||
touch(directory, setStore, sessionID)
|
||||
|
||||
if (store.message[sessionID] !== undefined && hasSession && meta.limit[key] !== undefined) return
|
||||
|
||||
const limit = meta.limit[key] ?? messagePageSize
|
||||
|
||||
const sessionReq = hasSession
|
||||
? Promise.resolve()
|
||||
: retry(() => client.session.get({ sessionID })).then((session) => {
|
||||
if (!tracked(directory, sessionID)) return
|
||||
const data = session.data
|
||||
if (!data) return
|
||||
setStore(
|
||||
@@ -258,11 +326,13 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const directory = sdk.directory
|
||||
const client = sdk.client
|
||||
const [store, setStore] = globalSync.child(directory)
|
||||
touch(directory, setStore, sessionID)
|
||||
if (store.session_diff[sessionID] !== undefined) return
|
||||
|
||||
const key = keyFor(directory, sessionID)
|
||||
return runInflight(inflightDiff, key, () =>
|
||||
retry(() => client.session.diff({ sessionID })).then((diff) => {
|
||||
if (!tracked(directory, sessionID)) return
|
||||
setStore("session_diff", sessionID, reconcile(diff.data ?? [], { key: "file" }))
|
||||
}),
|
||||
)
|
||||
@@ -271,6 +341,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const directory = sdk.directory
|
||||
const client = sdk.client
|
||||
const [store, setStore] = globalSync.child(directory)
|
||||
touch(directory, setStore, sessionID)
|
||||
const existing = store.todo[sessionID]
|
||||
const cached = globalSync.data.session_todo[sessionID]
|
||||
if (existing !== undefined) {
|
||||
@@ -287,6 +358,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const key = keyFor(directory, sessionID)
|
||||
return runInflight(inflightTodo, key, () =>
|
||||
retry(() => client.session.todo({ sessionID })).then((todo) => {
|
||||
if (!tracked(directory, sessionID)) return
|
||||
const list = todo.data ?? []
|
||||
setStore("todo", sessionID, reconcile(list, { key: "id" }))
|
||||
globalSync.todo.set(sessionID, list)
|
||||
@@ -310,6 +382,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const directory = sdk.directory
|
||||
const client = sdk.client
|
||||
const [, setStore] = globalSync.child(directory)
|
||||
touch(directory, setStore, sessionID)
|
||||
const key = keyFor(directory, sessionID)
|
||||
const step = count ?? messagePageSize
|
||||
if (meta.loading[key]) return
|
||||
@@ -325,6 +398,11 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
})
|
||||
},
|
||||
},
|
||||
evict(sessionID: string, directory = sdk.directory) {
|
||||
const [, setStore] = globalSync.child(directory)
|
||||
seenFor(directory).delete(sessionID)
|
||||
evict(directory, setStore, [sessionID])
|
||||
},
|
||||
fetch: async (count = 10) => {
|
||||
const directory = sdk.directory
|
||||
const client = sdk.client
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createStore, produce } from "solid-js/store"
|
||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||
import { batch, createEffect, createMemo, createRoot, onCleanup } from "solid-js"
|
||||
import { batch, createEffect, createMemo, createRoot, on, onCleanup } from "solid-js"
|
||||
import { useParams } from "@solidjs/router"
|
||||
import { useSDK } from "./sdk"
|
||||
import type { Platform } from "./platform"
|
||||
@@ -38,6 +38,16 @@ type TerminalCacheEntry = {
|
||||
|
||||
const caches = new Set<Map<string, TerminalCacheEntry>>()
|
||||
|
||||
const trimTerminal = (pty: LocalPTY) => {
|
||||
if (!pty.buffer && pty.cursor === undefined && pty.scrollY === undefined) return pty
|
||||
return {
|
||||
...pty,
|
||||
buffer: undefined,
|
||||
cursor: undefined,
|
||||
scrollY: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
export function clearWorkspaceTerminals(dir: string, sessionIDs?: string[], platform?: Platform) {
|
||||
const key = getWorkspaceTerminalCacheKey(dir)
|
||||
for (const cache of caches) {
|
||||
@@ -188,6 +198,18 @@ function createWorkspaceTerminalSession(sdk: ReturnType<typeof useSDK>, dir: str
|
||||
console.error("Failed to update terminal", error)
|
||||
})
|
||||
},
|
||||
trim(id: string) {
|
||||
const index = store.all.findIndex((x) => x.id === id)
|
||||
if (index === -1) return
|
||||
setStore("all", index, (pty) => trimTerminal(pty))
|
||||
},
|
||||
trimAll() {
|
||||
setStore("all", (all) => {
|
||||
const next = all.map(trimTerminal)
|
||||
if (next.every((pty, index) => pty === all[index])) return all
|
||||
return next
|
||||
})
|
||||
},
|
||||
async clone(id: string) {
|
||||
const index = store.all.findIndex((x) => x.id === id)
|
||||
const pty = store.all[index]
|
||||
@@ -322,12 +344,27 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont
|
||||
|
||||
const workspace = createMemo(() => loadWorkspace(params.dir!, params.id))
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => ({ dir: params.dir, id: params.id }),
|
||||
(next, prev) => {
|
||||
if (!prev?.dir) return
|
||||
if (next.dir === prev.dir && next.id === prev.id) return
|
||||
if (next.dir === prev.dir && next.id) return
|
||||
loadWorkspace(prev.dir, prev.id).trimAll()
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
return {
|
||||
ready: () => workspace().ready(),
|
||||
all: () => workspace().all(),
|
||||
active: () => workspace().active(),
|
||||
new: () => workspace().new(),
|
||||
update: (pty: Partial<LocalPTY> & { id: string }) => workspace().update(pty),
|
||||
trim: (id: string) => workspace().trim(id),
|
||||
trimAll: () => workspace().trimAll(),
|
||||
clone: (id: string) => workspace().clone(id),
|
||||
open: (id: string) => workspace().open(id),
|
||||
close: (id: string) => workspace().close(id),
|
||||
|
||||
@@ -34,6 +34,7 @@ import { useProviders } from "@/hooks/use-providers"
|
||||
import { showToast, Toast, toaster } from "@opencode-ai/ui/toast"
|
||||
import { useGlobalSDK } from "@/context/global-sdk"
|
||||
import { clearWorkspaceTerminals } from "@/context/terminal"
|
||||
import { dropSessionCaches, pickSessionCacheEvictions } from "@/context/global-sync/session-cache"
|
||||
import { useNotification } from "@/context/notification"
|
||||
import { usePermission } from "@/context/permission"
|
||||
import { Binary } from "@opencode-ai/util/binary"
|
||||
@@ -657,25 +658,24 @@ export default function Layout(props: ParentProps) {
|
||||
const prefetchQueues = new Map<string, PrefetchQueue>()
|
||||
|
||||
const PREFETCH_MAX_SESSIONS_PER_DIR = 10
|
||||
const prefetchedByDir = new Map<string, Map<string, true>>()
|
||||
const prefetchedByDir = new Map<string, Set<string>>()
|
||||
|
||||
const lruFor = (directory: string) => {
|
||||
const existing = prefetchedByDir.get(directory)
|
||||
if (existing) return existing
|
||||
const created = new Map<string, true>()
|
||||
const created = new Set<string>()
|
||||
prefetchedByDir.set(directory, created)
|
||||
return created
|
||||
}
|
||||
|
||||
const markPrefetched = (directory: string, sessionID: string) => {
|
||||
const lru = lruFor(directory)
|
||||
if (lru.has(sessionID)) lru.delete(sessionID)
|
||||
lru.set(sessionID, true)
|
||||
while (lru.size > PREFETCH_MAX_SESSIONS_PER_DIR) {
|
||||
const oldest = lru.keys().next().value as string | undefined
|
||||
if (!oldest) return
|
||||
lru.delete(oldest)
|
||||
}
|
||||
return pickSessionCacheEvictions({
|
||||
seen: lru,
|
||||
keep: sessionID,
|
||||
limit: PREFETCH_MAX_SESSIONS_PER_DIR,
|
||||
preserve: directory === params.dir && params.id ? [params.id] : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
@@ -724,6 +724,7 @@ export default function Layout(props: ParentProps) {
|
||||
return retry(() => globalSDK.client.session.messages({ directory, sessionID, limit: prefetchChunk }))
|
||||
.then((messages) => {
|
||||
if (prefetchToken.value !== token) return
|
||||
if (!lruFor(directory).has(sessionID)) return
|
||||
|
||||
const items = (messages.data ?? []).filter((x) => !!x?.info?.id)
|
||||
const next = items.map((x) => x.info).filter((m): m is Message => !!m?.id)
|
||||
@@ -787,7 +788,18 @@ export default function Layout(props: ParentProps) {
|
||||
const lru = lruFor(directory)
|
||||
const known = lru.has(session.id)
|
||||
if (!known && lru.size >= PREFETCH_MAX_SESSIONS_PER_DIR && priority !== "high") return
|
||||
markPrefetched(directory, session.id)
|
||||
const stale = markPrefetched(directory, session.id)
|
||||
if (stale.length > 0) {
|
||||
const [, setStore] = globalSync.child(directory, { bootstrap: false })
|
||||
for (const id of stale) {
|
||||
globalSync.todo.set(id, undefined)
|
||||
}
|
||||
setStore(
|
||||
produce((draft) => {
|
||||
dropSessionCaches(draft, stale)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
if (priority === "high") q.pending.unshift(session.id)
|
||||
if (priority !== "high") q.pending.push(session.id)
|
||||
@@ -1879,6 +1891,7 @@ export default function Layout(props: ParentProps) {
|
||||
|
||||
const SidebarPanel = (panelProps: { project: LocalProject | undefined; mobile?: boolean; merged?: boolean }) => {
|
||||
const merged = createMemo(() => panelProps.mobile || (panelProps.merged ?? layout.sidebar.opened()))
|
||||
const hover = createMemo(() => !panelProps.mobile && panelProps.merged === false && !layout.sidebar.opened())
|
||||
const projectName = createMemo(() => {
|
||||
const project = panelProps.project
|
||||
if (!project) return ""
|
||||
@@ -1907,8 +1920,8 @@ export default function Layout(props: ParentProps) {
|
||||
"flex flex-col min-h-0 min-w-0 rounded-tl-[12px] px-2": true,
|
||||
"border border-b-0 border-border-weak-base": !merged(),
|
||||
"border-l border-t border-border-weaker-base": merged(),
|
||||
"bg-background-base": merged(),
|
||||
"bg-background-stronger": !merged(),
|
||||
"bg-background-base": merged() || hover(),
|
||||
"bg-background-stronger": !merged() && !hover(),
|
||||
"flex-1 min-w-0": panelProps.mobile,
|
||||
"max-w-full overflow-hidden": panelProps.mobile,
|
||||
}}
|
||||
|
||||
@@ -91,6 +91,7 @@ const ProjectTile = (props: {
|
||||
modal={!props.sidebarHovering()}
|
||||
onOpenChange={(value) => {
|
||||
props.setMenu(value)
|
||||
props.setSuppressHover(value)
|
||||
if (value) props.setOpen(false)
|
||||
}}
|
||||
>
|
||||
@@ -107,6 +108,12 @@ const ProjectTile = (props: {
|
||||
!props.selected() && !props.active(),
|
||||
"bg-surface-base-hover border border-border-weak-base": !props.selected() && props.active(),
|
||||
}}
|
||||
onPointerDown={(event) => {
|
||||
if (!props.overlay()) return
|
||||
if (event.button !== 2 && !(event.button === 0 && event.ctrlKey)) return
|
||||
props.setSuppressHover(true)
|
||||
event.preventDefault()
|
||||
}}
|
||||
onMouseEnter={(event: MouseEvent) => {
|
||||
if (!props.overlay()) return
|
||||
if (props.suppressHover()) return
|
||||
|
||||
@@ -41,216 +41,12 @@ import { createScrollSpy } from "@/pages/session/scroll-spy"
|
||||
import { SessionMobileTabs } from "@/pages/session/session-mobile-tabs"
|
||||
import { SessionSidePanel } from "@/pages/session/session-side-panel"
|
||||
import { TerminalPanel } from "@/pages/session/terminal-panel"
|
||||
import { createSessionHistoryWindow, emptyUserMessages } from "@/pages/session/history-window"
|
||||
import { useSessionCommands } from "@/pages/session/use-session-commands"
|
||||
import { useSessionHashScroll } from "@/pages/session/use-session-hash-scroll"
|
||||
import { same } from "@/utils/same"
|
||||
import { formatServerError } from "@/utils/server-errors"
|
||||
|
||||
const emptyUserMessages: UserMessage[] = []
|
||||
|
||||
type SessionHistoryWindowInput = {
|
||||
sessionID: () => string | undefined
|
||||
messagesReady: () => boolean
|
||||
visibleUserMessages: () => UserMessage[]
|
||||
historyMore: () => boolean
|
||||
historyLoading: () => boolean
|
||||
loadMore: (sessionID: string) => Promise<void>
|
||||
userScrolled: () => boolean
|
||||
scroller: () => HTMLDivElement | undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Maintains the rendered history window for a session timeline.
|
||||
*
|
||||
* It keeps initial paint bounded to recent turns, reveals cached turns in
|
||||
* small batches while scrolling upward, and prefetches older history near top.
|
||||
*/
|
||||
function createSessionHistoryWindow(input: SessionHistoryWindowInput) {
|
||||
const turnInit = 10
|
||||
const turnBatch = 8
|
||||
const turnScrollThreshold = 200
|
||||
const turnPrefetchBuffer = 16
|
||||
const prefetchCooldownMs = 400
|
||||
const prefetchNoGrowthLimit = 2
|
||||
|
||||
const [state, setState] = createStore({
|
||||
turnID: undefined as string | undefined,
|
||||
turnStart: 0,
|
||||
prefetchUntil: 0,
|
||||
prefetchNoGrowth: 0,
|
||||
})
|
||||
|
||||
const initialTurnStart = (len: number) => (len > turnInit ? len - turnInit : 0)
|
||||
|
||||
const turnStart = createMemo(() => {
|
||||
const id = input.sessionID()
|
||||
const len = input.visibleUserMessages().length
|
||||
if (!id || len <= 0) return 0
|
||||
if (state.turnID !== id) return initialTurnStart(len)
|
||||
if (state.turnStart <= 0) return 0
|
||||
if (state.turnStart >= len) return initialTurnStart(len)
|
||||
return state.turnStart
|
||||
})
|
||||
|
||||
const setTurnStart = (start: number) => {
|
||||
const id = input.sessionID()
|
||||
const next = start > 0 ? start : 0
|
||||
if (!id) {
|
||||
setState({ turnID: undefined, turnStart: next })
|
||||
return
|
||||
}
|
||||
setState({ turnID: id, turnStart: next })
|
||||
}
|
||||
|
||||
const renderedUserMessages = createMemo(
|
||||
() => {
|
||||
const msgs = input.visibleUserMessages()
|
||||
const start = turnStart()
|
||||
if (start <= 0) return msgs
|
||||
return msgs.slice(start)
|
||||
},
|
||||
emptyUserMessages,
|
||||
{
|
||||
equals: same,
|
||||
},
|
||||
)
|
||||
|
||||
const preserveScroll = (fn: () => void) => {
|
||||
const el = input.scroller()
|
||||
if (!el) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
const beforeTop = el.scrollTop
|
||||
fn()
|
||||
void el.scrollHeight
|
||||
el.scrollTop = beforeTop
|
||||
}
|
||||
|
||||
const backfillTurns = () => {
|
||||
const start = turnStart()
|
||||
if (start <= 0) return
|
||||
|
||||
const next = start - turnBatch
|
||||
const nextStart = next > 0 ? next : 0
|
||||
|
||||
preserveScroll(() => setTurnStart(nextStart))
|
||||
}
|
||||
|
||||
/** Button path: reveal all cached turns, fetch older history, reveal one batch. */
|
||||
const loadAndReveal = async () => {
|
||||
const id = input.sessionID()
|
||||
if (!id) return
|
||||
|
||||
const start = turnStart()
|
||||
const beforeVisible = input.visibleUserMessages().length
|
||||
|
||||
if (start > 0) setTurnStart(0)
|
||||
|
||||
if (!input.historyMore() || input.historyLoading()) return
|
||||
|
||||
await input.loadMore(id)
|
||||
if (input.sessionID() !== id) return
|
||||
|
||||
const afterVisible = input.visibleUserMessages().length
|
||||
const growth = afterVisible - beforeVisible
|
||||
if (state.prefetchNoGrowth) setState("prefetchNoGrowth", 0)
|
||||
if (growth <= 0) return
|
||||
if (turnStart() !== 0) return
|
||||
|
||||
const target = Math.min(afterVisible, Math.max(beforeVisible, renderedUserMessages().length) + turnBatch)
|
||||
const nextStart = Math.max(0, afterVisible - target)
|
||||
preserveScroll(() => setTurnStart(nextStart))
|
||||
}
|
||||
|
||||
/** Scroll/prefetch path: fetch older history from server. */
|
||||
const fetchOlderMessages = async (opts?: { prefetch?: boolean }) => {
|
||||
const id = input.sessionID()
|
||||
if (!id) return
|
||||
if (!input.historyMore() || input.historyLoading()) return
|
||||
|
||||
if (opts?.prefetch) {
|
||||
const now = Date.now()
|
||||
if (state.prefetchUntil > now) return
|
||||
if (state.prefetchNoGrowth >= prefetchNoGrowthLimit) return
|
||||
setState("prefetchUntil", now + prefetchCooldownMs)
|
||||
}
|
||||
|
||||
const start = turnStart()
|
||||
const beforeVisible = input.visibleUserMessages().length
|
||||
const beforeRendered = start <= 0 ? beforeVisible : renderedUserMessages().length
|
||||
|
||||
await input.loadMore(id)
|
||||
if (input.sessionID() !== id) return
|
||||
|
||||
const afterVisible = input.visibleUserMessages().length
|
||||
const growth = afterVisible - beforeVisible
|
||||
|
||||
if (opts?.prefetch) {
|
||||
setState("prefetchNoGrowth", growth > 0 ? 0 : state.prefetchNoGrowth + 1)
|
||||
} else if (growth > 0 && state.prefetchNoGrowth) {
|
||||
setState("prefetchNoGrowth", 0)
|
||||
}
|
||||
|
||||
if (growth <= 0) return
|
||||
if (turnStart() !== start) return
|
||||
|
||||
const reveal = !opts?.prefetch
|
||||
const currentRendered = renderedUserMessages().length
|
||||
const base = Math.max(beforeRendered, currentRendered)
|
||||
const target = reveal ? Math.min(afterVisible, base + turnBatch) : base
|
||||
const nextStart = Math.max(0, afterVisible - target)
|
||||
preserveScroll(() => setTurnStart(nextStart))
|
||||
}
|
||||
|
||||
const onScrollerScroll = () => {
|
||||
if (!input.userScrolled()) return
|
||||
const el = input.scroller()
|
||||
if (!el) return
|
||||
if (el.scrollHeight - el.clientHeight + el.scrollTop >= turnScrollThreshold) return
|
||||
|
||||
const start = turnStart()
|
||||
if (start > 0) {
|
||||
if (start <= turnPrefetchBuffer) {
|
||||
void fetchOlderMessages({ prefetch: true })
|
||||
}
|
||||
backfillTurns()
|
||||
return
|
||||
}
|
||||
|
||||
void fetchOlderMessages()
|
||||
}
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
input.sessionID,
|
||||
() => {
|
||||
setState({ prefetchUntil: 0, prefetchNoGrowth: 0 })
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => [input.sessionID(), input.messagesReady()] as const,
|
||||
([id, ready]) => {
|
||||
if (!id || !ready) return
|
||||
setTurnStart(initialTurnStart(input.visibleUserMessages().length))
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
return {
|
||||
turnStart,
|
||||
setTurnStart,
|
||||
renderedUserMessages,
|
||||
loadAndReveal,
|
||||
onScrollerScroll,
|
||||
}
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
const globalSync = useGlobalSync()
|
||||
const layout = useLayout()
|
||||
@@ -426,10 +222,12 @@ export default function Page() {
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => params.id,
|
||||
(id, prev) => {
|
||||
if (id || !prev) return
|
||||
resetSessionModel(local)
|
||||
() => ({ dir: params.dir, id: params.id }),
|
||||
(next, prev) => {
|
||||
if (!prev) return
|
||||
if (next.dir === prev.dir && next.id === prev.id) return
|
||||
if (prev.id) sync.session.evict(prev.id, prev.dir)
|
||||
if (!next.id) resetSessionModel(local)
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
@@ -1088,6 +886,7 @@ export default function Page() {
|
||||
|
||||
let scrollStateFrame: number | undefined
|
||||
let scrollStateTarget: HTMLDivElement | undefined
|
||||
let historyFillFrame: number | undefined
|
||||
const scrollSpy = createScrollSpy({
|
||||
onActive: (id) => {
|
||||
if (id === store.messageId) return
|
||||
@@ -1157,7 +956,9 @@ export default function Page() {
|
||||
scroller = el
|
||||
autoScroll.scrollRef(el)
|
||||
scrollSpy.setContainer(el)
|
||||
if (el) scheduleScrollState(el)
|
||||
if (!el) return
|
||||
scheduleScrollState(el)
|
||||
scheduleHistoryFill()
|
||||
}
|
||||
|
||||
createResizeObserver(
|
||||
@@ -1166,6 +967,7 @@ export default function Page() {
|
||||
const el = scroller
|
||||
if (el) scheduleScrollState(el)
|
||||
scrollSpy.markDirty()
|
||||
scheduleHistoryFill()
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1180,6 +982,45 @@ export default function Page() {
|
||||
scroller: () => scroller,
|
||||
})
|
||||
|
||||
const scheduleHistoryFill = () => {
|
||||
if (historyFillFrame !== undefined) return
|
||||
|
||||
historyFillFrame = requestAnimationFrame(() => {
|
||||
historyFillFrame = undefined
|
||||
|
||||
if (!params.id || !messagesReady()) return
|
||||
if (autoScroll.userScrolled() || historyLoading()) return
|
||||
|
||||
const el = scroller
|
||||
if (!el) return
|
||||
if (el.scrollHeight > el.clientHeight + 1) return
|
||||
if (historyWindow.turnStart() <= 0 && !historyMore()) return
|
||||
|
||||
void historyWindow.loadAndReveal()
|
||||
})
|
||||
}
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() =>
|
||||
[
|
||||
params.id,
|
||||
messagesReady(),
|
||||
historyWindow.turnStart(),
|
||||
historyMore(),
|
||||
historyLoading(),
|
||||
autoScroll.userScrolled(),
|
||||
visibleUserMessages().length,
|
||||
] as const,
|
||||
([id, ready, start, more, loading, scrolled]) => {
|
||||
if (!id || !ready || loading || scrolled) return
|
||||
if (start <= 0 && !more) return
|
||||
scheduleHistoryFill()
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
createResizeObserver(
|
||||
() => promptDock,
|
||||
({ height }) => {
|
||||
@@ -1197,6 +1038,7 @@ export default function Page() {
|
||||
|
||||
if (el) scheduleScrollState(el)
|
||||
scrollSpy.markDirty()
|
||||
scheduleHistoryFill()
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1226,6 +1068,7 @@ export default function Page() {
|
||||
document.removeEventListener("keydown", handleKeyDown)
|
||||
scrollSpy.destroy()
|
||||
if (scrollStateFrame !== undefined) cancelAnimationFrame(scrollStateFrame)
|
||||
if (historyFillFrame !== undefined) cancelAnimationFrame(historyFillFrame)
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
35
packages/app/src/pages/session/history-window.test.ts
Normal file
35
packages/app/src/pages/session/history-window.test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { historyLoadMode, historyRevealTop } from "./history-window"
|
||||
|
||||
describe("historyLoadMode", () => {
|
||||
test("reveals cached turns before fetching", () => {
|
||||
expect(historyLoadMode({ start: 10, more: true, loading: false })).toBe("reveal")
|
||||
})
|
||||
|
||||
test("fetches older history when cache is already revealed", () => {
|
||||
expect(historyLoadMode({ start: 0, more: true, loading: false })).toBe("fetch")
|
||||
})
|
||||
|
||||
test("does nothing while history is unavailable or loading", () => {
|
||||
expect(historyLoadMode({ start: 0, more: false, loading: false })).toBe("noop")
|
||||
expect(historyLoadMode({ start: 0, more: true, loading: true })).toBe("noop")
|
||||
})
|
||||
})
|
||||
|
||||
describe("historyRevealTop", () => {
|
||||
test("pins the viewport to the top when older turns were revealed there", () => {
|
||||
expect(historyRevealTop({ top: -400, height: 1000, gap: 0, max: 400 }, { clientHeight: 600, height: 2000 })).toBe(
|
||||
-1400,
|
||||
)
|
||||
})
|
||||
|
||||
test("keeps the latest turns pinned when the viewport was underfilled", () => {
|
||||
expect(historyRevealTop({ top: 0, height: 200, gap: -400, max: -400 }, { clientHeight: 600, height: 2000 })).toBe(0)
|
||||
})
|
||||
|
||||
test("keeps the current anchor when the user was not at the top", () => {
|
||||
expect(historyRevealTop({ top: -200, height: 1000, gap: 200, max: 400 }, { clientHeight: 600, height: 2000 })).toBe(
|
||||
-200,
|
||||
)
|
||||
})
|
||||
})
|
||||
273
packages/app/src/pages/session/history-window.ts
Normal file
273
packages/app/src/pages/session/history-window.ts
Normal file
@@ -0,0 +1,273 @@
|
||||
import type { UserMessage } from "@opencode-ai/sdk/v2"
|
||||
import { createEffect, createMemo, on } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { same } from "@/utils/same"
|
||||
|
||||
export const emptyUserMessages: UserMessage[] = []
|
||||
|
||||
export type SessionHistoryWindowInput = {
|
||||
sessionID: () => string | undefined
|
||||
messagesReady: () => boolean
|
||||
visibleUserMessages: () => UserMessage[]
|
||||
historyMore: () => boolean
|
||||
historyLoading: () => boolean
|
||||
loadMore: (sessionID: string) => Promise<void>
|
||||
userScrolled: () => boolean
|
||||
scroller: () => HTMLDivElement | undefined
|
||||
}
|
||||
|
||||
type Snap = {
|
||||
top: number
|
||||
height: number
|
||||
gap: number
|
||||
max: number
|
||||
}
|
||||
|
||||
export const historyLoadMode = (input: { start: number; more: boolean; loading: boolean }) => {
|
||||
if (input.start > 0) return "reveal"
|
||||
if (!input.more || input.loading) return "noop"
|
||||
return "fetch"
|
||||
}
|
||||
|
||||
export const historyRevealTop = (
|
||||
mark: { top: number; height: number; gap: number; max: number },
|
||||
next: { clientHeight: number; height: number },
|
||||
threshold = 16,
|
||||
) => {
|
||||
const delta = next.height - mark.height
|
||||
if (delta <= 0) return mark.top
|
||||
if (mark.max <= 0) return mark.top
|
||||
if (mark.gap > threshold) return mark.top
|
||||
|
||||
const max = next.height - next.clientHeight
|
||||
if (max <= 0) return 0
|
||||
return Math.max(-max, Math.min(0, mark.top - delta))
|
||||
}
|
||||
|
||||
const snap = (el: HTMLDivElement | undefined): Snap | undefined => {
|
||||
if (!el) return
|
||||
const max = el.scrollHeight - el.clientHeight
|
||||
return {
|
||||
top: el.scrollTop,
|
||||
height: el.scrollHeight,
|
||||
gap: max + el.scrollTop,
|
||||
max,
|
||||
}
|
||||
}
|
||||
|
||||
const clamp = (el: HTMLDivElement, top: number) => {
|
||||
const max = el.scrollHeight - el.clientHeight
|
||||
if (max <= 0) return 0
|
||||
return Math.max(-max, Math.min(0, top))
|
||||
}
|
||||
|
||||
const revealThreshold = 16
|
||||
|
||||
const reveal = (input: SessionHistoryWindowInput, mark: Snap | undefined) => {
|
||||
const el = input.scroller()
|
||||
if (!el || !mark) return
|
||||
el.scrollTop = clamp(
|
||||
el,
|
||||
historyRevealTop(mark, { clientHeight: el.clientHeight, height: el.scrollHeight }, revealThreshold),
|
||||
)
|
||||
}
|
||||
|
||||
const preserve = (input: SessionHistoryWindowInput, fn: () => void) => {
|
||||
const el = input.scroller()
|
||||
if (!el) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
const top = el.scrollTop
|
||||
fn()
|
||||
el.scrollTop = top
|
||||
}
|
||||
|
||||
/**
|
||||
* Maintains the rendered history window for a session timeline.
|
||||
*
|
||||
* It keeps initial paint bounded to recent turns, reveals cached turns in
|
||||
* small batches while scrolling upward, and prefetches older history near top.
|
||||
*/
|
||||
export function createSessionHistoryWindow(input: SessionHistoryWindowInput) {
|
||||
const turnInit = 10
|
||||
const turnBatch = 8
|
||||
const turnScrollThreshold = 200
|
||||
const turnPrefetchBuffer = 16
|
||||
const prefetchCooldownMs = 400
|
||||
const prefetchNoGrowthLimit = 2
|
||||
|
||||
const [state, setState] = createStore({
|
||||
turnID: undefined as string | undefined,
|
||||
turnStart: 0,
|
||||
prefetchUntil: 0,
|
||||
prefetchNoGrowth: 0,
|
||||
})
|
||||
|
||||
const initialTurnStart = (len: number) => (len > turnInit ? len - turnInit : 0)
|
||||
|
||||
const turnStart = createMemo(() => {
|
||||
const id = input.sessionID()
|
||||
const len = input.visibleUserMessages().length
|
||||
if (!id || len <= 0) return 0
|
||||
if (state.turnID !== id) return initialTurnStart(len)
|
||||
if (state.turnStart <= 0) return 0
|
||||
if (state.turnStart >= len) return initialTurnStart(len)
|
||||
return state.turnStart
|
||||
})
|
||||
|
||||
const setTurnStart = (start: number) => {
|
||||
const id = input.sessionID()
|
||||
const next = start > 0 ? start : 0
|
||||
if (!id) {
|
||||
setState({ turnID: undefined, turnStart: next })
|
||||
return
|
||||
}
|
||||
setState({ turnID: id, turnStart: next })
|
||||
}
|
||||
|
||||
const renderedUserMessages = createMemo(
|
||||
() => {
|
||||
const msgs = input.visibleUserMessages()
|
||||
const start = turnStart()
|
||||
if (start <= 0) return msgs
|
||||
return msgs.slice(start)
|
||||
},
|
||||
emptyUserMessages,
|
||||
{
|
||||
equals: same,
|
||||
},
|
||||
)
|
||||
|
||||
const backfillTurns = () => {
|
||||
const start = turnStart()
|
||||
if (start <= 0) return
|
||||
|
||||
const next = start - turnBatch
|
||||
const nextStart = next > 0 ? next : 0
|
||||
|
||||
preserve(input, () => setTurnStart(nextStart))
|
||||
}
|
||||
|
||||
/** Button path: reveal cached turns first, then fetch older history. */
|
||||
const loadAndReveal = async () => {
|
||||
const id = input.sessionID()
|
||||
if (!id) return
|
||||
|
||||
const start = turnStart()
|
||||
const mode = historyLoadMode({
|
||||
start,
|
||||
more: input.historyMore(),
|
||||
loading: input.historyLoading(),
|
||||
})
|
||||
|
||||
if (mode === "reveal") {
|
||||
const mark = snap(input.scroller())
|
||||
setTurnStart(0)
|
||||
reveal(input, mark)
|
||||
return
|
||||
}
|
||||
|
||||
if (mode === "noop") return
|
||||
|
||||
const beforeVisible = input.visibleUserMessages().length
|
||||
const mark = snap(input.scroller())
|
||||
|
||||
await input.loadMore(id)
|
||||
if (input.sessionID() !== id) return
|
||||
|
||||
const afterVisible = input.visibleUserMessages().length
|
||||
const growth = afterVisible - beforeVisible
|
||||
if (growth <= 0) return
|
||||
if (state.prefetchNoGrowth) setState("prefetchNoGrowth", 0)
|
||||
|
||||
reveal(input, mark)
|
||||
}
|
||||
|
||||
/** Scroll/prefetch path: fetch older history from server. */
|
||||
const fetchOlderMessages = async (opts?: { prefetch?: boolean }) => {
|
||||
const id = input.sessionID()
|
||||
if (!id) return
|
||||
if (!input.historyMore() || input.historyLoading()) return
|
||||
|
||||
if (opts?.prefetch) {
|
||||
const now = Date.now()
|
||||
if (state.prefetchUntil > now) return
|
||||
if (state.prefetchNoGrowth >= prefetchNoGrowthLimit) return
|
||||
setState("prefetchUntil", now + prefetchCooldownMs)
|
||||
}
|
||||
|
||||
const start = turnStart()
|
||||
const beforeVisible = input.visibleUserMessages().length
|
||||
const beforeRendered = start <= 0 ? beforeVisible : renderedUserMessages().length
|
||||
|
||||
await input.loadMore(id)
|
||||
if (input.sessionID() !== id) return
|
||||
|
||||
const afterVisible = input.visibleUserMessages().length
|
||||
const growth = afterVisible - beforeVisible
|
||||
|
||||
if (opts?.prefetch) {
|
||||
setState("prefetchNoGrowth", growth > 0 ? 0 : state.prefetchNoGrowth + 1)
|
||||
} else if (growth > 0 && state.prefetchNoGrowth) {
|
||||
setState("prefetchNoGrowth", 0)
|
||||
}
|
||||
|
||||
if (growth <= 0) return
|
||||
if (turnStart() !== start) return
|
||||
|
||||
const revealMore = !opts?.prefetch
|
||||
const currentRendered = renderedUserMessages().length
|
||||
const base = Math.max(beforeRendered, currentRendered)
|
||||
const target = revealMore ? Math.min(afterVisible, base + turnBatch) : base
|
||||
const nextStart = Math.max(0, afterVisible - target)
|
||||
preserve(input, () => setTurnStart(nextStart))
|
||||
}
|
||||
|
||||
const onScrollerScroll = () => {
|
||||
if (!input.userScrolled()) return
|
||||
const el = input.scroller()
|
||||
if (!el) return
|
||||
if (el.scrollHeight - el.clientHeight + el.scrollTop >= turnScrollThreshold) return
|
||||
|
||||
const start = turnStart()
|
||||
if (start > 0) {
|
||||
if (start <= turnPrefetchBuffer) {
|
||||
void fetchOlderMessages({ prefetch: true })
|
||||
}
|
||||
backfillTurns()
|
||||
return
|
||||
}
|
||||
|
||||
void fetchOlderMessages()
|
||||
}
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
input.sessionID,
|
||||
() => {
|
||||
setState({ prefetchUntil: 0, prefetchNoGrowth: 0 })
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => [input.sessionID(), input.messagesReady()] as const,
|
||||
([id, ready]) => {
|
||||
if (!id || !ready) return
|
||||
setTurnStart(initialTurnStart(input.visibleUserMessages().length))
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
return {
|
||||
turnStart,
|
||||
setTurnStart,
|
||||
renderedUserMessages,
|
||||
loadAndReveal,
|
||||
onScrollerScroll,
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@ import { createEffect, createMemo, on, onCleanup, Show } from "solid-js"
|
||||
import { createStore, produce } from "solid-js/store"
|
||||
import { useNavigate, useParams } from "@solidjs/router"
|
||||
import { Button } from "@opencode-ai/ui/button"
|
||||
import { useReducedMotion } from "@opencode-ai/ui/hooks"
|
||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
||||
import { Dialog } from "@opencode-ai/ui/dialog"
|
||||
import { prefersReducedMotion } from "@opencode-ai/ui/hooks"
|
||||
import { InlineInput } from "@opencode-ai/ui/inline-input"
|
||||
import { animate, type AnimationPlaybackControls, clearFadeStyles, FAST_SPRING } from "@opencode-ai/ui/motion"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
@@ -32,7 +32,7 @@ export function SessionTimelineHeader(props: {
|
||||
const sync = useSync()
|
||||
const dialog = useDialog()
|
||||
const language = useLanguage()
|
||||
const reduce = prefersReducedMotion
|
||||
const reduce = useReducedMotion()
|
||||
|
||||
const [title, setTitle] = createStore({
|
||||
draft: "",
|
||||
|
||||
@@ -250,6 +250,7 @@ export function TerminalPanel() {
|
||||
<div id={`terminal-wrapper-${id}`} class="absolute inset-0">
|
||||
<Terminal
|
||||
pty={pty()}
|
||||
onConnect={() => terminal.trim(id)}
|
||||
onCleanup={terminal.update}
|
||||
onConnectError={() => terminal.clone(id)}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop-electron",
|
||||
"private": true,
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id = "opencode"
|
||||
name = "OpenCode"
|
||||
description = "The open source coding agent."
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
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.2.21/opencode-darwin-arm64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.22/opencode-darwin-arm64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.darwin-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.21/opencode-darwin-x64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.22/opencode-darwin-x64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-aarch64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.21/opencode-linux-arm64.tar.gz"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.22/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.2.21/opencode-linux-x64.tar.gz"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.22/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.2.21/opencode-windows-x64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.22/opencode-windows-x64.zip"
|
||||
cmd = "./opencode.exe"
|
||||
args = ["acp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -280,6 +280,11 @@ export const RunCommand = cmd({
|
||||
type: "string",
|
||||
describe: "attach to a running opencode server (e.g., http://localhost:4096)",
|
||||
})
|
||||
.option("password", {
|
||||
alias: ["p"],
|
||||
type: "string",
|
||||
describe: "basic auth password (defaults to OPENCODE_SERVER_PASSWORD)",
|
||||
})
|
||||
.option("dir", {
|
||||
type: "string",
|
||||
describe: "directory to run in, path on remote server if attaching",
|
||||
@@ -648,7 +653,14 @@ export const RunCommand = cmd({
|
||||
}
|
||||
|
||||
if (args.attach) {
|
||||
const sdk = createOpencodeClient({ baseUrl: args.attach, directory })
|
||||
const headers = (() => {
|
||||
const password = args.password ?? process.env.OPENCODE_SERVER_PASSWORD
|
||||
if (!password) return undefined
|
||||
const username = process.env.OPENCODE_SERVER_USERNAME ?? "opencode"
|
||||
const auth = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`
|
||||
return { Authorization: auth }
|
||||
})()
|
||||
const sdk = createOpencodeClient({ baseUrl: args.attach, directory, headers })
|
||||
return await execute(sdk)
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ export function tui(input: {
|
||||
fetch?: typeof fetch
|
||||
headers?: RequestInit["headers"]
|
||||
events?: EventSource
|
||||
onExit?: () => Promise<void>
|
||||
}) {
|
||||
// promise to prevent immediate exit
|
||||
return new Promise<void>(async (resolve) => {
|
||||
@@ -126,7 +125,6 @@ export function tui(input: {
|
||||
|
||||
const onExit = async () => {
|
||||
unguard?.()
|
||||
await input.onExit?.()
|
||||
resolve()
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ export const { use: useExit, provider: ExitProvider } = createSimpleContext({
|
||||
init: (input: { onExit?: () => Promise<void> }) => {
|
||||
const renderer = useRenderer()
|
||||
let message: string | undefined
|
||||
let task: Promise<void> | undefined
|
||||
const store = {
|
||||
set: (value?: string) => {
|
||||
const prev = message
|
||||
@@ -29,20 +30,24 @@ export const { use: useExit, provider: ExitProvider } = createSimpleContext({
|
||||
get: () => message,
|
||||
}
|
||||
const exit: Exit = Object.assign(
|
||||
async (reason?: unknown) => {
|
||||
// Reset window title before destroying renderer
|
||||
renderer.setTerminalTitle("")
|
||||
renderer.destroy()
|
||||
win32FlushInputBuffer()
|
||||
if (reason) {
|
||||
const formatted = FormatError(reason) ?? FormatUnknownError(reason)
|
||||
if (formatted) {
|
||||
process.stderr.write(formatted + "\n")
|
||||
(reason?: unknown) => {
|
||||
if (task) return task
|
||||
task = (async () => {
|
||||
// Reset window title before destroying renderer
|
||||
renderer.setTerminalTitle("")
|
||||
renderer.destroy()
|
||||
win32FlushInputBuffer()
|
||||
if (reason) {
|
||||
const formatted = FormatError(reason) ?? FormatUnknownError(reason)
|
||||
if (formatted) {
|
||||
process.stderr.write(formatted + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
const text = store.get()
|
||||
if (text) process.stdout.write(text + "\n")
|
||||
await input.onExit?.()
|
||||
const text = store.get()
|
||||
if (text) process.stdout.write(text + "\n")
|
||||
await input.onExit?.()
|
||||
})()
|
||||
return task
|
||||
},
|
||||
{
|
||||
message: store,
|
||||
|
||||
@@ -110,18 +110,20 @@ export const TuiThreadCommand = cmd({
|
||||
return
|
||||
}
|
||||
|
||||
// Resolve relative paths against PWD to preserve behavior when using --cwd flag
|
||||
// Resolve relative --project paths from PWD, then use the real cwd after
|
||||
// chdir so the thread and worker share the same directory key.
|
||||
const root = Filesystem.resolve(process.env.PWD ?? process.cwd())
|
||||
const cwd = args.project
|
||||
const next = args.project
|
||||
? Filesystem.resolve(path.isAbsolute(args.project) ? args.project : path.join(root, args.project))
|
||||
: root
|
||||
: Filesystem.resolve(process.cwd())
|
||||
const file = await target()
|
||||
try {
|
||||
process.chdir(cwd)
|
||||
process.chdir(next)
|
||||
} catch {
|
||||
UI.error("Failed to change directory to " + cwd)
|
||||
UI.error("Failed to change directory to " + next)
|
||||
return
|
||||
}
|
||||
const cwd = Filesystem.resolve(process.cwd())
|
||||
|
||||
const worker = new Worker(file, {
|
||||
env: Object.fromEntries(
|
||||
|
||||
@@ -1288,12 +1288,6 @@ export namespace Provider {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if opencode provider is available before using it
|
||||
const opencodeProvider = await state().then((state) => state.providers["opencode"])
|
||||
if (opencodeProvider && opencodeProvider.models["gpt-5-nano"]) {
|
||||
return getModel("opencode", "gpt-5-nano")
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
157
packages/opencode/test/cli/tui/thread.test.ts
Normal file
157
packages/opencode/test/cli/tui/thread.test.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { describe, expect, mock, test } from "bun:test"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { tmpdir } from "../../fixture/fixture"
|
||||
|
||||
const stop = new Error("stop")
|
||||
const seen = {
|
||||
tui: [] as string[],
|
||||
inst: [] as string[],
|
||||
}
|
||||
|
||||
mock.module("../../../src/cli/cmd/tui/app", () => ({
|
||||
tui: async (input: { directory: string }) => {
|
||||
seen.tui.push(input.directory)
|
||||
throw stop
|
||||
},
|
||||
}))
|
||||
|
||||
mock.module("@/util/rpc", () => ({
|
||||
Rpc: {
|
||||
client: () => ({
|
||||
call: async () => ({ url: "http://127.0.0.1" }),
|
||||
on: () => {},
|
||||
}),
|
||||
},
|
||||
}))
|
||||
|
||||
mock.module("@/cli/ui", () => ({
|
||||
UI: {
|
||||
error: () => {},
|
||||
},
|
||||
}))
|
||||
|
||||
mock.module("@/util/log", () => ({
|
||||
Log: {
|
||||
init: async () => {},
|
||||
create: () => ({
|
||||
error: () => {},
|
||||
info: () => {},
|
||||
warn: () => {},
|
||||
debug: () => {},
|
||||
time: () => ({ stop: () => {} }),
|
||||
}),
|
||||
Default: {
|
||||
error: () => {},
|
||||
info: () => {},
|
||||
warn: () => {},
|
||||
debug: () => {},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
mock.module("@/util/timeout", () => ({
|
||||
withTimeout: <T>(input: Promise<T>) => input,
|
||||
}))
|
||||
|
||||
mock.module("@/cli/network", () => ({
|
||||
withNetworkOptions: <T>(input: T) => input,
|
||||
resolveNetworkOptions: async () => ({
|
||||
mdns: false,
|
||||
port: 0,
|
||||
hostname: "127.0.0.1",
|
||||
}),
|
||||
}))
|
||||
|
||||
mock.module("../../../src/cli/cmd/tui/win32", () => ({
|
||||
win32DisableProcessedInput: () => {},
|
||||
win32InstallCtrlCGuard: () => undefined,
|
||||
}))
|
||||
|
||||
mock.module("@/config/tui", () => ({
|
||||
TuiConfig: {
|
||||
get: () => ({}),
|
||||
},
|
||||
}))
|
||||
|
||||
mock.module("@/project/instance", () => ({
|
||||
Instance: {
|
||||
provide: async (input: { directory: string; fn: () => Promise<unknown> | unknown }) => {
|
||||
seen.inst.push(input.directory)
|
||||
return input.fn()
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
describe("tui thread", () => {
|
||||
async function call(project?: string) {
|
||||
const { TuiThreadCommand } = await import("../../../src/cli/cmd/tui/thread")
|
||||
const args: Parameters<NonNullable<typeof TuiThreadCommand.handler>>[0] = {
|
||||
_: [],
|
||||
$0: "opencode",
|
||||
project,
|
||||
prompt: "hi",
|
||||
model: undefined,
|
||||
agent: undefined,
|
||||
session: undefined,
|
||||
continue: false,
|
||||
fork: false,
|
||||
port: 0,
|
||||
hostname: "127.0.0.1",
|
||||
mdns: false,
|
||||
"mdns-domain": "opencode.local",
|
||||
mdnsDomain: "opencode.local",
|
||||
cors: [],
|
||||
}
|
||||
return TuiThreadCommand.handler(args)
|
||||
}
|
||||
|
||||
async function check(project?: string) {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
const cwd = process.cwd()
|
||||
const pwd = process.env.PWD
|
||||
const worker = globalThis.Worker
|
||||
const tty = Object.getOwnPropertyDescriptor(process.stdin, "isTTY")
|
||||
const link = path.join(path.dirname(tmp.path), path.basename(tmp.path) + "-link")
|
||||
const type = process.platform === "win32" ? "junction" : "dir"
|
||||
seen.tui.length = 0
|
||||
seen.inst.length = 0
|
||||
await fs.symlink(tmp.path, link, type)
|
||||
|
||||
Object.defineProperty(process.stdin, "isTTY", {
|
||||
configurable: true,
|
||||
value: true,
|
||||
})
|
||||
globalThis.Worker = class extends EventTarget {
|
||||
onerror = null
|
||||
onmessage = null
|
||||
onmessageerror = null
|
||||
postMessage() {}
|
||||
terminate() {}
|
||||
} as unknown as typeof Worker
|
||||
|
||||
try {
|
||||
process.chdir(tmp.path)
|
||||
process.env.PWD = link
|
||||
await expect(call(project)).rejects.toBe(stop)
|
||||
expect(seen.inst[0]).toBe(tmp.path)
|
||||
expect(seen.tui[0]).toBe(tmp.path)
|
||||
} finally {
|
||||
process.chdir(cwd)
|
||||
if (pwd === undefined) delete process.env.PWD
|
||||
else process.env.PWD = pwd
|
||||
if (tty) Object.defineProperty(process.stdin, "isTTY", tty)
|
||||
else delete (process.stdin as { isTTY?: boolean }).isTTY
|
||||
globalThis.Worker = worker
|
||||
await fs.rm(link, { recursive: true, force: true }).catch(() => undefined)
|
||||
}
|
||||
}
|
||||
|
||||
test("uses the real cwd when PWD points at a symlink", async () => {
|
||||
await check()
|
||||
})
|
||||
|
||||
test("uses the real cwd after resolving a relative project from PWD", async () => {
|
||||
await check(".")
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
@@ -48,8 +48,11 @@
|
||||
"@pierre/diffs": "catalog:",
|
||||
"@shikijs/transformers": "3.9.2",
|
||||
"@solid-primitives/bounds": "0.1.3",
|
||||
"@solid-primitives/lifecycle": "0.1.2",
|
||||
"@solid-primitives/media": "2.3.3",
|
||||
"@solid-primitives/page-visibility": "2.1.1",
|
||||
"@solid-primitives/resize-observer": "2.1.3",
|
||||
"@solid-primitives/rootless": "1.5.2",
|
||||
"@solidjs/meta": "catalog:",
|
||||
"@solidjs/router": "catalog:",
|
||||
"dompurify": "3.3.1",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createMemo, createSignal, For, onMount } from "solid-js"
|
||||
import type { ToolPart } from "@opencode-ai/sdk/v2"
|
||||
import { getFilename } from "@opencode-ai/util/path"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { useI18n } from "../context/i18n"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { ToolCall } from "./basic-tool"
|
||||
import { ToolStatusTitle } from "./tool-status-title"
|
||||
import { AnimatedCountList } from "./tool-count-summary"
|
||||
@@ -58,11 +58,9 @@ export function ContextToolGroupHeader(props: {
|
||||
<ToolCall
|
||||
variant="row"
|
||||
icon="magnifying-glass-menu"
|
||||
open={!props.pending && props.open}
|
||||
showArrow={!props.pending}
|
||||
onOpenChange={(v) => {
|
||||
if (!props.pending) props.onOpenChange(v)
|
||||
}}
|
||||
open={props.open}
|
||||
showArrow
|
||||
onOpenChange={props.onOpenChange}
|
||||
trigger={
|
||||
<div data-component="context-tool-group-trigger" data-pending={props.pending || undefined}>
|
||||
<span
|
||||
@@ -149,10 +147,10 @@ export function ContextToolExpandedList(props: { parts: ToolPart[]; expanded: bo
|
||||
}
|
||||
|
||||
export function ContextToolRollingResults(props: { parts: ToolPart[]; pending: boolean }) {
|
||||
const reduce = useReducedMotion()
|
||||
const wiped = new Set<string>()
|
||||
const [mounted, setMounted] = createSignal(false)
|
||||
onMount(() => setMounted(true))
|
||||
const reduce = prefersReducedMotion
|
||||
const show = () => mounted() && props.pending
|
||||
const opacity = useSpring(() => (show() ? 1 : 0), GROW_SPRING)
|
||||
const blur = useSpring(() => (show() ? 0 : 2), GROW_SPRING)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createEffect, on, type JSX, onMount, onCleanup } from "solid-js"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { animate, tunableSpringValue, type AnimationPlaybackControls, GROW_SPRING, type SpringConfig } from "./motion"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
|
||||
export interface GrowBoxProps {
|
||||
children: JSX.Element
|
||||
@@ -49,7 +49,7 @@ export interface GrowBoxProps {
|
||||
* Used for timeline turns, assistant part groups, and user messages.
|
||||
*/
|
||||
export function GrowBox(props: GrowBoxProps) {
|
||||
const reduce = prefersReducedMotion
|
||||
const reduce = useReducedMotion()
|
||||
const spring = () => props.spring ?? GROW_SPRING
|
||||
const toggleSpring = () => props.toggleSpring ?? spring()
|
||||
let mode: "mount" | "toggle" = "mount"
|
||||
@@ -293,6 +293,18 @@ export function GrowBox(props: GrowBoxProps) {
|
||||
offChange()
|
||||
})
|
||||
|
||||
if (watch()) {
|
||||
observer = new ResizeObserver(() => {
|
||||
if (!open()) return
|
||||
if (resizeFrame !== undefined) return
|
||||
resizeFrame = requestAnimationFrame(() => {
|
||||
resizeFrame = undefined
|
||||
setHeight("mount")
|
||||
})
|
||||
})
|
||||
observer.observe(body)
|
||||
}
|
||||
|
||||
if (!animated()) {
|
||||
setInstant(open())
|
||||
return
|
||||
@@ -318,17 +330,6 @@ export function GrowBox(props: GrowBoxProps) {
|
||||
if (grow()) setHeight("mount")
|
||||
})
|
||||
}
|
||||
if (watch()) {
|
||||
observer = new ResizeObserver(() => {
|
||||
if (!open()) return
|
||||
if (resizeFrame !== undefined) return
|
||||
resizeFrame = requestAnimationFrame(() => {
|
||||
resizeFrame = undefined
|
||||
setHeight("mount")
|
||||
})
|
||||
})
|
||||
observer.observe(body)
|
||||
}
|
||||
})
|
||||
|
||||
createEffect(
|
||||
@@ -402,7 +403,12 @@ export function GrowBox(props: GrowBoxProps) {
|
||||
ref={root}
|
||||
data-slot={props.slot}
|
||||
class={props.class}
|
||||
style={{ transform: "translateZ(0)", position: "relative" }}
|
||||
style={{
|
||||
transform: "translateZ(0)",
|
||||
position: "relative",
|
||||
height: open() ? undefined : "0px",
|
||||
overflow: open() ? undefined : "clip",
|
||||
}}
|
||||
>
|
||||
<div ref={body} style={{ "padding-top": gap() > 0 ? `${gap()}px` : undefined }}>
|
||||
{props.children}
|
||||
|
||||
@@ -38,7 +38,7 @@ import { TextShimmer } from "./text-shimmer"
|
||||
import { list } from "./text-utils"
|
||||
import { GrowBox } from "./grow-box"
|
||||
import { COLLAPSIBLE_SPRING } from "./motion"
|
||||
import { busy, hold, createThrottledValue, useToolFade, useContextToolPending } from "./tool-utils"
|
||||
import { busy, createThrottledValue, useToolFade, useContextToolPending } from "./tool-utils"
|
||||
import { ContextToolGroupHeader, ContextToolExpandedList, ContextToolRollingResults } from "./context-tool-results"
|
||||
import { ShellRollingResults } from "./shell-rolling-results"
|
||||
|
||||
@@ -254,8 +254,6 @@ function urls(text: string | undefined) {
|
||||
const CONTEXT_GROUP_TOOLS = new Set(["read", "glob", "grep", "list"])
|
||||
const HIDDEN_TOOLS = new Set(["todowrite", "todoread"])
|
||||
|
||||
import { pageVisible } from "../hooks/use-page-visible"
|
||||
|
||||
function createGroupOpenState() {
|
||||
const [state, setState] = createStore<Record<string, boolean>>({})
|
||||
const read = (key?: string, collapse?: boolean) => {
|
||||
@@ -274,18 +272,6 @@ function createGroupOpenState() {
|
||||
return { read, controlled, write }
|
||||
}
|
||||
|
||||
function shouldCollapseGroup(
|
||||
statuses: (string | undefined)[],
|
||||
opts: { afterTool?: boolean; groupTail?: boolean; working?: boolean },
|
||||
) {
|
||||
if (opts.afterTool) return true
|
||||
if (opts.groupTail === false) return true
|
||||
if (!pageVisible()) return false
|
||||
if (opts.working) return false
|
||||
if (!statuses.length) return false
|
||||
return !statuses.some((s) => busy(s))
|
||||
}
|
||||
|
||||
function renderable(part: PartType, showReasoningSummaries = true) {
|
||||
if (part.type === "tool") {
|
||||
if (HIDDEN_TOOLS.has(part.tool)) return false
|
||||
@@ -480,20 +466,9 @@ export function AssistantParts(props: {
|
||||
return COLLAPSIBLE_SPRING
|
||||
})
|
||||
const contextOpen = createMemo(() => {
|
||||
const collapse = (
|
||||
afterTool?: boolean,
|
||||
groupTail?: boolean,
|
||||
group?: { part: ToolPart; message: AssistantMessage }[],
|
||||
) =>
|
||||
shouldCollapseGroup(group?.map((item) => item.part.state.status) ?? [], {
|
||||
afterTool,
|
||||
groupTail,
|
||||
working: props.working,
|
||||
})
|
||||
const value = ctx()
|
||||
if (value) return groupState.read(value.groupKey, collapse(value.afterTool, value.tail, value.parts))
|
||||
const entry = part()
|
||||
return groupState.read(entry?.groupKey, collapse(entry?.afterTool, entry?.groupTail, entry?.groupParts))
|
||||
if (value) return groupState.read(value.groupKey, true)
|
||||
return groupState.read(part()?.groupKey, true)
|
||||
})
|
||||
const visible = createMemo(() => {
|
||||
if (!context()) return true
|
||||
@@ -539,9 +514,7 @@ export function AssistantParts(props: {
|
||||
ctxPartsPrev = result
|
||||
return result
|
||||
})
|
||||
const ctxPendingRaw = useContextToolPending(ctxParts, () => !!(props.working && ctx()?.tail))
|
||||
const ctxPending = ctxPendingRaw
|
||||
const ctxHoldOpen = hold(ctxPendingRaw)
|
||||
const ctxPending = useContextToolPending(ctxParts, () => !!(props.working && ctx()?.tail))
|
||||
const shell = createMemo(() => {
|
||||
const value = part()
|
||||
if (!value) return
|
||||
@@ -593,12 +566,20 @@ export function AssistantParts(props: {
|
||||
onOpenChange={(value: boolean) => groupState.write(entry().groupKey, value)}
|
||||
/>
|
||||
</PartGrow>
|
||||
<ContextToolExpandedList parts={ctxParts()} expanded={!ctxPending() && contextOpen()} />
|
||||
<ContextToolRollingResults parts={ctxParts()} pending={ctxHoldOpen()} />
|
||||
<ContextToolExpandedList parts={ctxParts()} expanded={contextOpen() && !ctxPending()} />
|
||||
<ContextToolRollingResults parts={ctxParts()} pending={contextOpen() && ctxPending()} />
|
||||
</>
|
||||
)}
|
||||
</Show>
|
||||
<Show when={shell()}>{(value) => <ShellRollingResults part={value()} animate={props.animate} />}</Show>
|
||||
<Show when={shell()}>
|
||||
{(value) => (
|
||||
<ShellRollingResults
|
||||
part={value()}
|
||||
animate={props.animate}
|
||||
defaultOpen={props.shellToolDefaultOpen}
|
||||
/>
|
||||
)}
|
||||
</Show>
|
||||
<Show when={!shell() ? part() : undefined}>
|
||||
{(entry) => (
|
||||
<Show when={!entry().context}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { attachSpring, motionValue } from "motion"
|
||||
import type { SpringOptions } from "motion"
|
||||
import { createEffect, createSignal, onCleanup } from "solid-js"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
|
||||
type Opt = Pick<SpringOptions, "visualDuration" | "bounce" | "stiffness" | "damping" | "mass" | "velocity">
|
||||
const eq = (a: Opt | undefined, b: Opt | undefined) =>
|
||||
@@ -14,7 +14,7 @@ const eq = (a: Opt | undefined, b: Opt | undefined) =>
|
||||
|
||||
export function useSpring(target: () => number, options?: Opt | (() => Opt)) {
|
||||
const read = () => (typeof options === "function" ? options() : options)
|
||||
const reduce = prefersReducedMotion
|
||||
const reduce = useReducedMotion()
|
||||
const [value, setValue] = createSignal(target())
|
||||
const source = motionValue(value())
|
||||
const spring = motionValue(value())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { For, Show, batch, createEffect, createMemo, createSignal, on, onCleanup, onMount, type JSX } from "solid-js"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { animate, clearMaskStyles, GROW_SPRING, type AnimationPlaybackControls, type SpringConfig } from "./motion"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
|
||||
export type RollingResultsProps<T> = {
|
||||
items: T[]
|
||||
@@ -27,8 +27,7 @@ export function RollingResults<T>(props: RollingResultsProps<T>) {
|
||||
let shift: AnimationPlaybackControls | undefined
|
||||
let resize: AnimationPlaybackControls | undefined
|
||||
let edgeFade: AnimationPlaybackControls | undefined
|
||||
|
||||
const reducedMotion = prefersReducedMotion
|
||||
const reduce = useReducedMotion()
|
||||
|
||||
const rows = createMemo(() => Math.max(1, Math.round(props.rows ?? 3)))
|
||||
const rowHeight = createMemo(() => Math.max(16, Math.round(props.rowHeight ?? 22)))
|
||||
@@ -54,7 +53,7 @@ export function RollingResults<T>(props: RollingResultsProps<T>) {
|
||||
return count() - rendered().length
|
||||
})
|
||||
const open = createMemo(() => props.open !== false)
|
||||
const active = createMemo(() => (props.animate !== false || props.spring !== undefined) && !reducedMotion())
|
||||
const active = createMemo(() => (props.animate !== false || props.spring !== undefined) && !reduce())
|
||||
const noFade = () => props.noFadeOnCollapse === true
|
||||
const overflowing = createMemo(() => count() > rows())
|
||||
const shown = createMemo(() => Math.min(rows(), count()))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createEffect, createMemo, createSignal, onCleanup, onMount, Show } from "solid-js"
|
||||
import stripAnsi from "strip-ansi"
|
||||
import type { ToolPart } from "@opencode-ai/sdk/v2"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { useI18n } from "../context/i18n"
|
||||
import { RollingResults } from "./rolling-results"
|
||||
import { Icon } from "./icon"
|
||||
@@ -10,15 +10,7 @@ import { TextShimmer } from "./text-shimmer"
|
||||
import { Tooltip } from "./tooltip"
|
||||
import { GROW_SPRING } from "./motion"
|
||||
import { useSpring } from "./motion-spring"
|
||||
import {
|
||||
busy,
|
||||
createThrottledValue,
|
||||
hold,
|
||||
updateScrollMask,
|
||||
useCollapsible,
|
||||
useRowWipe,
|
||||
useToolFade,
|
||||
} from "./tool-utils"
|
||||
import { busy, createThrottledValue, updateScrollMask, useCollapsible, useRowWipe, useToolFade } from "./tool-utils"
|
||||
|
||||
function ShellRollingSubtitle(props: { text: string; animate?: boolean }) {
|
||||
let ref: HTMLSpanElement | undefined
|
||||
@@ -176,23 +168,17 @@ function ShellExpanded(props: { cmd: string; out: string; open: boolean }) {
|
||||
)
|
||||
}
|
||||
|
||||
export function ShellRollingResults(props: { part: ToolPart; animate?: boolean }) {
|
||||
export function ShellRollingResults(props: { part: ToolPart; animate?: boolean; defaultOpen?: boolean }) {
|
||||
const i18n = useI18n()
|
||||
const reduce = useReducedMotion()
|
||||
const wiped = new Set<string>()
|
||||
const [mounted, setMounted] = createSignal(false)
|
||||
const [userToggled, setUserToggled] = createSignal(false)
|
||||
const [userOpen, setUserOpen] = createSignal(false)
|
||||
const [open, setOpen] = createSignal(props.defaultOpen ?? true)
|
||||
onMount(() => setMounted(true))
|
||||
const state = createMemo(() => props.part.state as Record<string, any>)
|
||||
const pending = createMemo(() => busy(props.part.state.status))
|
||||
const autoOpen = hold(pending, 2000)
|
||||
const effectiveOpen = createMemo(() => {
|
||||
if (pending()) return true
|
||||
if (userToggled()) return userOpen()
|
||||
return autoOpen()
|
||||
})
|
||||
const expanded = createMemo(() => !pending() && !autoOpen() && userToggled() && userOpen())
|
||||
const previewOpen = createMemo(() => effectiveOpen() && !expanded())
|
||||
const expanded = createMemo(() => open() && !pending())
|
||||
const previewOpen = createMemo(() => open() && pending())
|
||||
const command = createMemo(() => {
|
||||
const value = state().input?.command ?? state().metadata?.command
|
||||
if (typeof value === "string") return value
|
||||
@@ -208,7 +194,6 @@ export function ShellRollingResults(props: { part: ToolPart; animate?: boolean }
|
||||
if (typeof value === "string") return value
|
||||
return ""
|
||||
})
|
||||
const reduce = prefersReducedMotion
|
||||
const skip = () => reduce() || props.animate === false
|
||||
const opacity = useSpring(() => (mounted() ? 1 : 0), GROW_SPRING)
|
||||
const blur = useSpring(() => (mounted() ? 0 : 2), GROW_SPRING)
|
||||
@@ -217,12 +202,10 @@ export function ShellRollingResults(props: { part: ToolPart; animate?: boolean }
|
||||
const headerHeight = useSpring(() => (mounted() ? 37 : 0), GROW_SPRING)
|
||||
let headerClipRef: HTMLDivElement | undefined
|
||||
const handleHeaderClick = () => {
|
||||
if (pending()) return
|
||||
const el = headerClipRef
|
||||
const viewport = el?.closest(".scroll-view__viewport") as HTMLElement | null
|
||||
const beforeY = el?.getBoundingClientRect().top ?? 0
|
||||
setUserToggled(true)
|
||||
setUserOpen((prev) => !prev)
|
||||
setOpen((prev) => !prev)
|
||||
if (viewport && el) {
|
||||
requestAnimationFrame(() => {
|
||||
const afterY = el.getBoundingClientRect().top
|
||||
@@ -249,7 +232,7 @@ export function ShellRollingResults(props: { part: ToolPart; animate?: boolean }
|
||||
ref={headerClipRef}
|
||||
data-slot="shell-rolling-header-clip"
|
||||
data-scroll-preserve
|
||||
data-clickable={!pending() ? "true" : "false"}
|
||||
data-clickable="true"
|
||||
onClick={handleHeaderClick}
|
||||
style={{ height: `${skip() ? (mounted() ? 37 : 0) : headerHeight()}px`, overflow: "clip" }}
|
||||
>
|
||||
@@ -258,13 +241,11 @@ export function ShellRollingResults(props: { part: ToolPart; animate?: boolean }
|
||||
<TextShimmer text={i18n.t("ui.tool.shell")} active={pending()} />
|
||||
</span>
|
||||
<Show when={subtitle()}>{(text) => <ShellRollingSubtitle text={text()} animate={props.animate} />}</Show>
|
||||
<Show when={!pending()}>
|
||||
<span data-slot="shell-rolling-actions">
|
||||
<span data-slot="shell-rolling-arrow" data-open={effectiveOpen() ? "true" : "false"}>
|
||||
<Icon name="chevron-down" size="small" />
|
||||
</span>
|
||||
<span data-slot="shell-rolling-actions">
|
||||
<span data-slot="shell-rolling-arrow" data-open={open() ? "true" : "false"}>
|
||||
<Icon name="chevron-down" size="small" />
|
||||
</span>
|
||||
</Show>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createEffect, createSignal, on, onCleanup, onMount } from "solid-js"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import {
|
||||
animate,
|
||||
type AnimationPlaybackControls,
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
GROW_SPRING,
|
||||
WIPE_MASK,
|
||||
} from "./motion"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
|
||||
const px = (value: number | string | undefined, fallback: number) => {
|
||||
if (typeof value === "number") return `${value}px`
|
||||
@@ -143,12 +143,13 @@ export function TextWipe(props: { text?: string; class?: string; delay?: number;
|
||||
let ref: HTMLSpanElement | undefined
|
||||
let frame: number | undefined
|
||||
let anim: AnimationPlaybackControls | undefined
|
||||
const reduce = useReducedMotion()
|
||||
|
||||
const run = () => {
|
||||
if (props.animate === false) return
|
||||
const el = ref
|
||||
if (!el || !props.text || typeof window === "undefined") return
|
||||
if (prefersReducedMotion()) return
|
||||
if (reduce()) return
|
||||
|
||||
const mask =
|
||||
typeof CSS !== "undefined" &&
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Show, createEffect, createMemo, createSignal, on, onCleanup, onMount } from "solid-js"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import { animate, type AnimationPlaybackControls, GROW_SPRING } from "./motion"
|
||||
import { TextShimmer } from "./text-shimmer"
|
||||
import { commonPrefix } from "./text-utils"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
|
||||
function contentWidth(el: HTMLSpanElement | undefined) {
|
||||
if (!el) return 0
|
||||
@@ -18,6 +18,7 @@ export function ToolStatusTitle(props: {
|
||||
class?: string
|
||||
split?: boolean
|
||||
}) {
|
||||
const reduce = useReducedMotion()
|
||||
const split = createMemo(() => commonPrefix(props.activeText, props.doneText))
|
||||
const suffix = createMemo(
|
||||
() =>
|
||||
@@ -38,8 +39,6 @@ export function ToolStatusTitle(props: {
|
||||
|
||||
const node = () => (suffix() ? tailRef : swapRef)
|
||||
|
||||
const reduce = prefersReducedMotion
|
||||
|
||||
const setNodeWidth = (width: string) => {
|
||||
if (swapRef) swapRef.style.width = width
|
||||
if (tailRef) tailRef.style.width = width
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { ToolPart } from "@opencode-ai/sdk/v2"
|
||||
import { createEffect, createMemo, createSignal, on, onCleanup, onMount } from "solid-js"
|
||||
import { useReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import {
|
||||
animate,
|
||||
type AnimationPlaybackControls,
|
||||
@@ -8,8 +10,6 @@ import {
|
||||
GROW_SPRING,
|
||||
WIPE_MASK,
|
||||
} from "./motion"
|
||||
import { prefersReducedMotion } from "../hooks/use-reduced-motion"
|
||||
import type { ToolPart } from "@opencode-ai/sdk/v2"
|
||||
|
||||
export const TEXT_RENDER_THROTTLE_MS = 100
|
||||
|
||||
@@ -106,57 +106,67 @@ export function useCollapsible(options: {
|
||||
measure?: () => number
|
||||
onOpen?: () => void
|
||||
}) {
|
||||
const reduce = useReducedMotion()
|
||||
let heightAnim: AnimationPlaybackControls | undefined
|
||||
let fadeAnim: AnimationPlaybackControls | undefined
|
||||
let gen = 0
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
options.open,
|
||||
(isOpen) => {
|
||||
const content = options.content()
|
||||
const body = options.body()
|
||||
if (!content || !body) return
|
||||
heightAnim?.stop()
|
||||
fadeAnim?.stop()
|
||||
const id = ++gen
|
||||
on(options.open, (isOpen) => {
|
||||
const content = options.content()
|
||||
const body = options.body()
|
||||
if (!content || !body) return
|
||||
heightAnim?.stop()
|
||||
fadeAnim?.stop()
|
||||
if (reduce()) {
|
||||
body.style.opacity = ""
|
||||
body.style.filter = ""
|
||||
if (isOpen) {
|
||||
content.style.display = ""
|
||||
content.style.height = "0px"
|
||||
body.style.opacity = "0"
|
||||
body.style.filter = "blur(2px)"
|
||||
fadeAnim = animate(body, { opacity: [0, 1], filter: ["blur(2px)", "blur(0px)"] }, COLLAPSIBLE_SPRING)
|
||||
queueMicrotask(() => {
|
||||
if (gen !== id) return
|
||||
const c = options.content()
|
||||
if (!c) return
|
||||
const h = options.measure?.() ?? Math.ceil(body.getBoundingClientRect().height)
|
||||
heightAnim = animate(c, { height: ["0px", `${h}px`] }, COLLAPSIBLE_SPRING)
|
||||
heightAnim.finished.then(
|
||||
() => {
|
||||
if (gen !== id) return
|
||||
c.style.height = "auto"
|
||||
options.onOpen?.()
|
||||
},
|
||||
() => {},
|
||||
)
|
||||
})
|
||||
content.style.height = "auto"
|
||||
options.onOpen?.()
|
||||
return
|
||||
}
|
||||
content.style.height = "0px"
|
||||
content.style.display = "none"
|
||||
return
|
||||
}
|
||||
const id = ++gen
|
||||
if (isOpen) {
|
||||
content.style.display = ""
|
||||
content.style.height = "0px"
|
||||
body.style.opacity = "0"
|
||||
body.style.filter = "blur(2px)"
|
||||
fadeAnim = animate(body, { opacity: [0, 1], filter: ["blur(2px)", "blur(0px)"] }, COLLAPSIBLE_SPRING)
|
||||
queueMicrotask(() => {
|
||||
if (gen !== id) return
|
||||
const c = options.content()
|
||||
if (!c) return
|
||||
const h = options.measure?.() ?? Math.ceil(body.getBoundingClientRect().height)
|
||||
heightAnim = animate(c, { height: ["0px", `${h}px`] }, COLLAPSIBLE_SPRING)
|
||||
heightAnim.finished.then(
|
||||
() => {
|
||||
if (gen !== id) return
|
||||
c.style.height = "auto"
|
||||
options.onOpen?.()
|
||||
},
|
||||
() => {},
|
||||
)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const h = content.getBoundingClientRect().height
|
||||
heightAnim = animate(content, { height: [`${h}px`, "0px"] }, COLLAPSIBLE_SPRING)
|
||||
fadeAnim = animate(body, { opacity: [1, 0], filter: ["blur(0px)", "blur(2px)"] }, COLLAPSIBLE_SPRING)
|
||||
heightAnim.finished.then(
|
||||
() => {
|
||||
if (gen !== id) return
|
||||
content.style.display = "none"
|
||||
},
|
||||
() => {},
|
||||
)
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
const h = content.getBoundingClientRect().height
|
||||
heightAnim = animate(content, { height: [`${h}px`, "0px"] }, COLLAPSIBLE_SPRING)
|
||||
fadeAnim = animate(body, { opacity: [1, 0], filter: ["blur(0px)", "blur(2px)"] }, COLLAPSIBLE_SPRING)
|
||||
heightAnim.finished.then(
|
||||
() => {
|
||||
if (gen !== id) return
|
||||
content.style.display = "none"
|
||||
},
|
||||
() => {},
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
onCleanup(() => {
|
||||
@@ -181,7 +191,7 @@ export function useRowWipe(opts: {
|
||||
ref: () => HTMLElement | undefined
|
||||
seen: Set<string>
|
||||
}) {
|
||||
const reduce = prefersReducedMotion
|
||||
const reduce = useReducedMotion()
|
||||
|
||||
createEffect(() => {
|
||||
const id = opts.id()
|
||||
@@ -265,13 +275,14 @@ export function useToolFade(
|
||||
const delay = options?.delay ?? 0
|
||||
const wipe = options?.wipe ?? false
|
||||
const active = options?.animate !== false
|
||||
const reduce = useReducedMotion()
|
||||
|
||||
onMount(() => {
|
||||
if (!active) return
|
||||
|
||||
const el = ref()
|
||||
if (!el || typeof window === "undefined") return
|
||||
if (prefersReducedMotion()) return
|
||||
if (reduce()) return
|
||||
|
||||
const mask =
|
||||
wipe &&
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
export * from "./use-filtered-list"
|
||||
export * from "./create-auto-scroll"
|
||||
export * from "./use-element-height"
|
||||
export * from "./use-reduced-motion"
|
||||
export * from "./use-page-visible"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { createEffect, createSignal, onCleanup, type Accessor } from "solid-js"
|
||||
|
||||
/**
|
||||
* Tracks an element's height via ResizeObserver.
|
||||
* Returns a reactive signal that updates whenever the element resizes.
|
||||
*/
|
||||
export function useElementHeight(
|
||||
ref: Accessor<HTMLElement | undefined> | (() => HTMLElement | undefined),
|
||||
initial = 0,
|
||||
): Accessor<number> {
|
||||
const [height, setHeight] = createSignal(initial)
|
||||
|
||||
createEffect(() => {
|
||||
const el = ref()
|
||||
if (!el) return
|
||||
setHeight(el.getBoundingClientRect().height)
|
||||
const observer = new ResizeObserver(() => {
|
||||
setHeight(el.getBoundingClientRect().height)
|
||||
})
|
||||
observer.observe(el)
|
||||
onCleanup(() => observer.disconnect())
|
||||
})
|
||||
|
||||
return height
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { createSignal } from "solid-js"
|
||||
|
||||
export const pageVisible = /* @__PURE__ */ (() => {
|
||||
const [visible, setVisible] = createSignal(true)
|
||||
if (typeof document !== "undefined") {
|
||||
const sync = () => setVisible(document.visibilityState !== "hidden")
|
||||
sync()
|
||||
document.addEventListener("visibilitychange", sync)
|
||||
}
|
||||
return visible
|
||||
})()
|
||||
@@ -1,9 +1,10 @@
|
||||
import { createSignal } from "solid-js"
|
||||
import { isHydrated } from "@solid-primitives/lifecycle"
|
||||
import { createMediaQuery } from "@solid-primitives/media"
|
||||
import { createHydratableSingletonRoot } from "@solid-primitives/rootless"
|
||||
|
||||
export const prefersReducedMotion = /* @__PURE__ */ (() => {
|
||||
if (typeof window === "undefined") return () => false
|
||||
const mql = window.matchMedia("(prefers-reduced-motion: reduce)")
|
||||
const [reduced, setReduced] = createSignal(mql.matches)
|
||||
mql.addEventListener("change", () => setReduced(mql.matches))
|
||||
return reduced
|
||||
})()
|
||||
const query = "(prefers-reduced-motion: reduce)"
|
||||
|
||||
export const useReducedMotion = createHydratableSingletonRoot(() => {
|
||||
const value = createMediaQuery(query)
|
||||
return () => !isHydrated() || value()
|
||||
})
|
||||
|
||||
@@ -85,214 +85,218 @@
|
||||
0 0 0 1px var(--border-weak-base, rgba(0, 0, 0, 0.07)), 0 36px 80px 0 rgba(0, 0, 0, 0.03),
|
||||
0 13.141px 29.201px 0 rgba(0, 0, 0, 0.04), 0 6.38px 14.177px 0 rgba(0, 0, 0, 0.05),
|
||||
0 3.127px 6.95px 0 rgba(0, 0, 0, 0.06), 0 1.237px 2.748px 0 rgba(0, 0, 0, 0.09);
|
||||
--shadow-sidebar-overlay:
|
||||
0 100px 80px 0 rgba(0, 0, 0, 0.29), 0 41.778px 33.422px 0 rgba(0, 0, 0, 0.21),
|
||||
0 22.336px 17.869px 0 rgba(0, 0, 0, 0.17), 0 12.522px 10.017px 0 rgba(0, 0, 0, 0.14),
|
||||
0 6.65px 5.32px 0 rgba(0, 0, 0, 0.12), 0 2.767px 2.214px 0 rgba(0, 0, 0, 0.08);
|
||||
|
||||
color-scheme: light;
|
||||
--text-mix-blend-mode: multiply;
|
||||
|
||||
/* OC-1 fallback variables (light) */
|
||||
--background-base: #f8f7f7;
|
||||
--background-weak: var(--smoke-light-3);
|
||||
--background-strong: var(--smoke-light-1);
|
||||
/* OC-2 fallback variables (light) */
|
||||
--background-base: #f8f8f8;
|
||||
--background-weak: #f3f3f3;
|
||||
--background-strong: #fcfcfc;
|
||||
--background-stronger: #fcfcfc;
|
||||
--surface-base: var(--smoke-light-alpha-2);
|
||||
--base: var(--smoke-light-alpha-2);
|
||||
--surface-base-hover: #0500000f;
|
||||
--surface-base-active: var(--smoke-light-alpha-3);
|
||||
--surface-base-interactive-active: var(--cobalt-light-alpha-3);
|
||||
--base2: var(--smoke-light-alpha-2);
|
||||
--base3: var(--smoke-light-alpha-2);
|
||||
--surface-inset-base: var(--smoke-light-alpha-2);
|
||||
--surface-inset-base-hover: var(--smoke-light-alpha-3);
|
||||
--surface-inset-strong: #1f000017;
|
||||
--surface-inset-strong-hover: #1f000017;
|
||||
--surface-raised-base: var(--smoke-light-alpha-1);
|
||||
--surface-float-base: var(--smoke-dark-1);
|
||||
--surface-float-base-hover: var(--smoke-dark-2);
|
||||
--surface-raised-base-hover: var(--smoke-light-alpha-2);
|
||||
--surface-raised-base-active: var(--smoke-light-alpha-3);
|
||||
--surface-raised-strong: var(--smoke-light-1);
|
||||
--surface-raised-strong-hover: var(--white);
|
||||
--surface-raised-stronger: var(--white);
|
||||
--surface-raised-stronger-hover: var(--white);
|
||||
--surface-weak: var(--smoke-light-alpha-3);
|
||||
--surface-weaker: var(--smoke-light-alpha-4);
|
||||
--surface-base: rgba(0, 0, 0, 0.031);
|
||||
--base: rgba(0, 0, 0, 0.034);
|
||||
--surface-base-hover: rgba(0, 0, 0, 0.059);
|
||||
--surface-base-active: rgba(0, 0, 0, 0.051);
|
||||
--surface-base-interactive-active: rgba(3, 76, 255, 0.09);
|
||||
--base2: rgba(0, 0, 0, 0.034);
|
||||
--base3: rgba(0, 0, 0, 0.034);
|
||||
--surface-inset-base: rgba(0, 0, 0, 0.034);
|
||||
--surface-inset-base-hover: rgba(0, 0, 0, 0.055);
|
||||
--surface-inset-strong: rgba(0, 0, 0, 0.09);
|
||||
--surface-inset-strong-hover: rgba(0, 0, 0, 0.09);
|
||||
--surface-raised-base: rgba(0, 0, 0, 0.031);
|
||||
--surface-float-base: #161616;
|
||||
--surface-float-base-hover: #1c1c1c;
|
||||
--surface-raised-base-hover: rgba(0, 0, 0, 0.051);
|
||||
--surface-raised-base-active: rgba(0, 0, 0, 0.09);
|
||||
--surface-raised-strong: #fcfcfc;
|
||||
--surface-raised-strong-hover: #ffffff;
|
||||
--surface-raised-stronger: #ffffff;
|
||||
--surface-raised-stronger-hover: #ffffff;
|
||||
--surface-weak: rgba(0, 0, 0, 0.051);
|
||||
--surface-weaker: rgba(0, 0, 0, 0.071);
|
||||
--surface-strong: #ffffff;
|
||||
--surface-stronger-non-alpha: var(--surface-raised-stronger-non-alpha);
|
||||
--surface-raised-stronger-non-alpha: var(--white);
|
||||
--surface-brand-base: var(--yuzu-light-9);
|
||||
--surface-brand-hover: var(--yuzu-light-10);
|
||||
--surface-interactive-base: var(--cobalt-light-3);
|
||||
--surface-interactive-hover: #e5f0ff;
|
||||
--surface-interactive-weak: var(--cobalt-light-2);
|
||||
--surface-interactive-weak-hover: var(--cobalt-light-3);
|
||||
--surface-success-base: var(--apple-light-3);
|
||||
--surface-success-weak: var(--apple-light-2);
|
||||
--surface-success-strong: var(--apple-light-9);
|
||||
--surface-warning-base: var(--solaris-light-3);
|
||||
--surface-warning-weak: var(--solaris-light-2);
|
||||
--surface-warning-strong: var(--solaris-light-9);
|
||||
--surface-critical-base: var(--ember-light-3);
|
||||
--surface-critical-weak: var(--ember-light-2);
|
||||
--surface-critical-strong: var(--ember-light-9);
|
||||
--surface-info-base: var(--lilac-light-3);
|
||||
--surface-info-weak: var(--lilac-light-2);
|
||||
--surface-info-strong: var(--lilac-light-9);
|
||||
--surface-raised-stronger-non-alpha: #ffffff;
|
||||
--surface-brand-base: #dcde8d;
|
||||
--surface-brand-hover: #d0d283;
|
||||
--surface-interactive-base: #ecf3ff;
|
||||
--surface-interactive-hover: #e0eaff;
|
||||
--surface-interactive-weak: #f7faff;
|
||||
--surface-interactive-weak-hover: #ecf3ff;
|
||||
--surface-success-base: #dbfed7;
|
||||
--surface-success-weak: #f0feee;
|
||||
--surface-success-strong: #12c905;
|
||||
--surface-warning-base: #fcf3cb;
|
||||
--surface-warning-weak: #fdfaec;
|
||||
--surface-warning-strong: #fbdd46;
|
||||
--surface-critical-base: #feefeb;
|
||||
--surface-critical-weak: #fff8f6;
|
||||
--surface-critical-strong: #fc533a;
|
||||
--surface-info-base: #fdecfe;
|
||||
--surface-info-weak: #fef7ff;
|
||||
--surface-info-strong: #a753ae;
|
||||
--surface-diff-unchanged-base: #ffffff00;
|
||||
--surface-diff-skip-base: var(--smoke-light-2);
|
||||
--surface-diff-hidden-base: var(--blue-light-3);
|
||||
--surface-diff-hidden-weak: var(--blue-light-2);
|
||||
--surface-diff-hidden-weaker: var(--blue-light-1);
|
||||
--surface-diff-hidden-strong: var(--blue-light-5);
|
||||
--surface-diff-hidden-stronger: var(--blue-light-9);
|
||||
--surface-diff-add-base: #dafbe0;
|
||||
--surface-diff-add-weak: var(--mint-light-2);
|
||||
--surface-diff-add-weaker: var(--mint-light-1);
|
||||
--surface-diff-add-strong: var(--mint-light-5);
|
||||
--surface-diff-add-stronger: var(--mint-light-9);
|
||||
--surface-diff-delete-base: var(--ember-light-3);
|
||||
--surface-diff-delete-weak: var(--ember-light-2);
|
||||
--surface-diff-delete-weaker: var(--ember-light-1);
|
||||
--surface-diff-delete-strong: var(--ember-light-6);
|
||||
--surface-diff-delete-stronger: var(--ember-light-9);
|
||||
--input-base: var(--smoke-light-1);
|
||||
--input-hover: var(--smoke-light-2);
|
||||
--input-active: var(--cobalt-light-1);
|
||||
--input-selected: var(--cobalt-light-4);
|
||||
--input-focus: var(--cobalt-light-1);
|
||||
--input-disabled: var(--smoke-light-4);
|
||||
--text-base: var(--smoke-light-11);
|
||||
--text-weak: var(--smoke-light-9);
|
||||
--text-weaker: var(--smoke-light-8);
|
||||
--text-strong: var(--smoke-light-12);
|
||||
--text-invert-base: var(--smoke-dark-alpha-11);
|
||||
--text-invert-weak: var(--smoke-dark-alpha-9);
|
||||
--text-invert-weaker: var(--smoke-dark-alpha-8);
|
||||
--text-invert-strong: var(--smoke-dark-alpha-12);
|
||||
--text-interactive-base: var(--cobalt-light-9);
|
||||
--text-on-brand-base: var(--smoke-light-alpha-11);
|
||||
--text-on-interactive-base: var(--smoke-light-1);
|
||||
--text-on-interactive-weak: var(--smoke-dark-alpha-11);
|
||||
--text-on-success-base: var(--apple-light-10);
|
||||
--text-on-critical-base: var(--ember-light-10);
|
||||
--text-on-critical-weak: var(--ember-light-8);
|
||||
--text-on-critical-strong: var(--ember-light-12);
|
||||
--text-on-warning-base: var(--smoke-dark-alpha-11);
|
||||
--text-on-info-base: var(--smoke-dark-alpha-11);
|
||||
--text-diff-add-base: var(--mint-light-11);
|
||||
--text-diff-delete-base: var(--ember-light-10);
|
||||
--text-diff-delete-strong: var(--ember-light-12);
|
||||
--text-diff-add-strong: var(--mint-light-12);
|
||||
--text-on-info-weak: var(--smoke-dark-alpha-9);
|
||||
--text-on-info-strong: var(--smoke-dark-alpha-12);
|
||||
--text-on-warning-weak: var(--smoke-dark-alpha-9);
|
||||
--text-on-warning-strong: var(--smoke-dark-alpha-12);
|
||||
--text-on-success-weak: var(--apple-light-6);
|
||||
--text-on-success-strong: var(--apple-light-12);
|
||||
--text-on-brand-weak: var(--smoke-light-alpha-9);
|
||||
--text-on-brand-weaker: var(--smoke-light-alpha-8);
|
||||
--text-on-brand-strong: var(--smoke-light-alpha-12);
|
||||
--button-primary-base: var(--smoke-light-12);
|
||||
--button-secondary-base: #fdfcfc;
|
||||
--button-secondary-hover: #faf9f9;
|
||||
--border-base: var(--smoke-light-alpha-7);
|
||||
--border-hover: var(--smoke-light-alpha-8);
|
||||
--border-active: var(--smoke-light-alpha-9);
|
||||
--border-selected: var(--cobalt-light-alpha-9);
|
||||
--border-disabled: var(--smoke-light-alpha-8);
|
||||
--border-focus: var(--smoke-light-alpha-9);
|
||||
--border-weak-base: var(--smoke-light-alpha-5);
|
||||
--border-strong-base: var(--smoke-light-alpha-7);
|
||||
--border-strong-hover: var(--smoke-light-alpha-8);
|
||||
--border-strong-active: var(--smoke-light-alpha-7);
|
||||
--border-strong-selected: var(--cobalt-light-alpha-6);
|
||||
--border-strong-disabled: var(--smoke-light-alpha-6);
|
||||
--border-strong-focus: var(--smoke-light-alpha-7);
|
||||
--border-weak-hover: var(--smoke-light-alpha-6);
|
||||
--border-weak-active: var(--smoke-light-alpha-7);
|
||||
--border-weak-selected: var(--cobalt-light-alpha-5);
|
||||
--border-weak-disabled: var(--smoke-light-alpha-6);
|
||||
--border-weak-focus: var(--smoke-light-alpha-7);
|
||||
--border-weaker-base: var(--smoke-light-alpha-3);
|
||||
--border-interactive-base: var(--cobalt-light-7);
|
||||
--border-interactive-hover: var(--cobalt-light-8);
|
||||
--border-interactive-active: var(--cobalt-light-9);
|
||||
--border-interactive-selected: var(--cobalt-light-9);
|
||||
--border-interactive-disabled: var(--smoke-light-8);
|
||||
--border-interactive-focus: var(--cobalt-light-9);
|
||||
--border-success-base: var(--apple-light-6);
|
||||
--border-success-hover: var(--apple-light-7);
|
||||
--border-success-selected: var(--apple-light-9);
|
||||
--border-warning-base: var(--solaris-light-6);
|
||||
--border-warning-hover: var(--solaris-light-7);
|
||||
--border-warning-selected: var(--solaris-light-9);
|
||||
--border-critical-base: var(--ember-light-6);
|
||||
--border-critical-hover: var(--ember-light-7);
|
||||
--border-critical-selected: var(--ember-light-9);
|
||||
--border-info-base: var(--lilac-light-6);
|
||||
--border-info-hover: var(--lilac-light-7);
|
||||
--border-info-selected: var(--lilac-light-9);
|
||||
--icon-base: var(--smoke-light-9);
|
||||
--icon-hover: var(--smoke-light-11);
|
||||
--icon-active: var(--smoke-light-12);
|
||||
--icon-selected: var(--smoke-light-12);
|
||||
--icon-disabled: var(--smoke-light-8);
|
||||
--icon-focus: var(--smoke-light-12);
|
||||
--surface-diff-skip-base: #f8f8f8;
|
||||
--surface-diff-hidden-base: #eaf4ff;
|
||||
--surface-diff-hidden-weak: #f6faff;
|
||||
--surface-diff-hidden-weaker: #fbfdff;
|
||||
--surface-diff-hidden-strong: #cae3ff;
|
||||
--surface-diff-hidden-stronger: #2090f5;
|
||||
--surface-diff-add-base: #e3fae1;
|
||||
--surface-diff-add-weak: #f4fcf3;
|
||||
--surface-diff-add-weaker: #fbfefb;
|
||||
--surface-diff-add-strong: #c2eebf;
|
||||
--surface-diff-add-stronger: #9ff29a;
|
||||
--surface-diff-delete-base: #feefeb;
|
||||
--surface-diff-delete-weak: #fff8f6;
|
||||
--surface-diff-delete-weaker: #fffcfb;
|
||||
--surface-diff-delete-strong: #fdc3b7;
|
||||
--surface-diff-delete-stronger: #fc533a;
|
||||
--input-base: #fcfcfc;
|
||||
--input-hover: #f8f8f8;
|
||||
--input-active: #fcfdff;
|
||||
--input-selected: #e0eaff;
|
||||
--input-focus: #fcfdff;
|
||||
--input-disabled: #ededed;
|
||||
--text-base: #6f6f6f;
|
||||
--text-weak: #8f8f8f;
|
||||
--text-weaker: #c7c7c7;
|
||||
--text-strong: #171717;
|
||||
--text-invert-base: #f8f8f8;
|
||||
--text-invert-weak: #f3f3f3;
|
||||
--text-invert-weaker: #ededed;
|
||||
--text-invert-strong: #fcfcfc;
|
||||
--text-interactive-base: #034cff;
|
||||
--text-on-brand-base: rgba(0, 0, 0, 0.574);
|
||||
--text-on-interactive-base: #fcfcfc;
|
||||
--text-on-interactive-weak: rgba(0, 0, 0, 0.574);
|
||||
--text-on-success-base: #2dba26;
|
||||
--text-on-critical-base: #ed4831;
|
||||
--text-on-critical-weak: #fe806a;
|
||||
--text-on-critical-strong: #601a0f;
|
||||
--text-on-warning-base: rgba(0, 0, 0, 0.574);
|
||||
--text-on-info-base: rgba(0, 0, 0, 0.574);
|
||||
--text-diff-add-base: #3a8437;
|
||||
--text-diff-delete-base: #ed4831;
|
||||
--text-diff-delete-strong: #601a0f;
|
||||
--text-diff-add-strong: #1d3e1c;
|
||||
--text-on-info-weak: rgba(0, 0, 0, 0.453);
|
||||
--text-on-info-strong: rgba(0, 0, 0, 0.915);
|
||||
--text-on-warning-weak: rgba(0, 0, 0, 0.453);
|
||||
--text-on-warning-strong: rgba(0, 0, 0, 0.915);
|
||||
--text-on-success-weak: #96ec8e;
|
||||
--text-on-success-strong: #044202;
|
||||
--text-on-brand-weak: rgba(0, 0, 0, 0.453);
|
||||
--text-on-brand-weaker: rgba(0, 0, 0, 0.232);
|
||||
--text-on-brand-strong: rgba(0, 0, 0, 0.915);
|
||||
--button-primary-base: #171717;
|
||||
--button-secondary-base: #fcfcfc;
|
||||
--button-secondary-hover: #f8f8f8;
|
||||
--button-ghost-hover: rgba(0, 0, 0, 0.031);
|
||||
--button-ghost-hover2: rgba(0, 0, 0, 0.051);
|
||||
--border-base: rgba(0, 0, 0, 0.162);
|
||||
--border-hover: rgba(0, 0, 0, 0.236);
|
||||
--border-active: rgba(0, 0, 0, 0.46);
|
||||
--border-selected: rgba(3, 76, 255, 0.99);
|
||||
--border-disabled: rgba(0, 0, 0, 0.236);
|
||||
--border-focus: rgba(0, 0, 0, 0.46);
|
||||
--border-weak-base: #e5e5e5;
|
||||
--border-strong-base: rgba(0, 0, 0, 0.151);
|
||||
--border-strong-hover: rgba(0, 0, 0, 0.232);
|
||||
--border-strong-active: rgba(0, 0, 0, 0.151);
|
||||
--border-strong-selected: rgba(3, 76, 255, 0.31);
|
||||
--border-strong-disabled: rgba(0, 0, 0, 0.118);
|
||||
--border-strong-focus: rgba(0, 0, 0, 0.151);
|
||||
--border-weak-hover: rgba(0, 0, 0, 0.118);
|
||||
--border-weak-active: rgba(0, 0, 0, 0.151);
|
||||
--border-weak-selected: rgba(3, 76, 255, 0.24);
|
||||
--border-weak-disabled: rgba(0, 0, 0, 0.118);
|
||||
--border-weak-focus: rgba(0, 0, 0, 0.151);
|
||||
--border-weaker-base: #f0f0f0;
|
||||
--border-weaker-hover: rgba(0, 0, 0, 0.075);
|
||||
--border-weaker-active: rgba(0, 0, 0, 0.118);
|
||||
--border-weaker-selected: rgba(3, 76, 255, 0.16);
|
||||
--border-weaker-disabled: rgba(0, 0, 0, 0.034);
|
||||
--border-weaker-focus: rgba(0, 0, 0, 0.118);
|
||||
--border-interactive-base: #a3c1fd;
|
||||
--border-interactive-hover: #7ea9ff;
|
||||
--border-interactive-active: #034cff;
|
||||
--border-interactive-selected: #034cff;
|
||||
--border-interactive-disabled: #c7c7c7;
|
||||
--border-interactive-focus: #034cff;
|
||||
--border-success-base: #96ec8e;
|
||||
--border-success-hover: #7add71;
|
||||
--border-success-selected: #12c905;
|
||||
--border-warning-base: #e8d479;
|
||||
--border-warning-hover: #d8c158;
|
||||
--border-warning-selected: #fbdd46;
|
||||
--border-critical-base: #fdc3b7;
|
||||
--border-critical-hover: #ffa796;
|
||||
--border-critical-selected: #fc533a;
|
||||
--border-info-base: #f4bdf8;
|
||||
--border-info-hover: #e6a8ea;
|
||||
--border-info-selected: #a753ae;
|
||||
--border-color: #ffffff;
|
||||
--icon-base: #8f8f8f;
|
||||
--icon-hover: #6f6f6f;
|
||||
--icon-active: #171717;
|
||||
--icon-selected: #171717;
|
||||
--icon-disabled: #c7c7c7;
|
||||
--icon-focus: #171717;
|
||||
--icon-invert-base: #ffffff;
|
||||
--icon-weak-base: var(--smoke-light-7);
|
||||
--icon-weak-hover: var(--smoke-light-8);
|
||||
--icon-weak-active: var(--smoke-light-9);
|
||||
--icon-weak-selected: var(--smoke-light-10);
|
||||
--icon-weak-disabled: var(--smoke-light-6);
|
||||
--icon-weak-focus: var(--smoke-light-9);
|
||||
--icon-strong-base: var(--smoke-light-12);
|
||||
--icon-weak-base: #dbdbdb;
|
||||
--icon-weak-hover: #c7c7c7;
|
||||
--icon-weak-active: #8f8f8f;
|
||||
--icon-weak-selected: #858585;
|
||||
--icon-weak-disabled: #e2e2e2;
|
||||
--icon-weak-focus: #8f8f8f;
|
||||
--icon-strong-base: #171717;
|
||||
--icon-strong-hover: #151313;
|
||||
--icon-strong-active: #020202;
|
||||
--icon-strong-selected: #020202;
|
||||
--icon-strong-disabled: var(--smoke-light-8);
|
||||
--icon-strong-disabled: #c7c7c7;
|
||||
--icon-strong-focus: #020202;
|
||||
--icon-brand-base: var(--smoke-light-12);
|
||||
--icon-interactive-base: var(--cobalt-light-9);
|
||||
--icon-success-base: var(--apple-light-7);
|
||||
--icon-success-hover: var(--apple-light-8);
|
||||
--icon-success-active: var(--apple-light-11);
|
||||
--icon-warning-base: var(--amber-light-9);
|
||||
--icon-warning-hover: var(--amber-light-8);
|
||||
--icon-warning-active: var(--amber-light-11);
|
||||
--icon-critical-base: var(--ember-light-10);
|
||||
--icon-critical-hover: var(--ember-light-11);
|
||||
--icon-critical-active: var(--ember-light-12);
|
||||
--icon-info-base: var(--lilac-light-7);
|
||||
--icon-info-hover: var(--lilac-light-8);
|
||||
--icon-info-active: var(--lilac-light-11);
|
||||
--icon-on-brand-base: var(--smoke-light-alpha-11);
|
||||
--icon-on-brand-hover: var(--smoke-light-alpha-12);
|
||||
--icon-on-brand-selected: var(--smoke-light-alpha-12);
|
||||
--icon-on-interactive-base: var(--smoke-light-1);
|
||||
--icon-agent-plan-base: var(--purple-light-9);
|
||||
--icon-agent-docs-base: var(--amber-light-9);
|
||||
--icon-agent-ask-base: var(--cyan-light-9);
|
||||
--icon-agent-build-base: var(--cobalt-light-9);
|
||||
--icon-on-success-base: var(--apple-light-alpha-9);
|
||||
--icon-on-success-hover: var(--apple-light-alpha-10);
|
||||
--icon-on-success-selected: var(--apple-light-alpha-11);
|
||||
--icon-on-warning-base: var(--amber-lightalpha-9);
|
||||
--icon-on-warning-hover: var(--amber-lightalpha-10);
|
||||
--icon-on-warning-selected: var(--amber-lightalpha-11);
|
||||
--icon-on-critical-base: var(--ember-light-alpha-9);
|
||||
--icon-on-critical-hover: var(--ember-light-alpha-10);
|
||||
--icon-on-critical-selected: var(--ember-light-alpha-11);
|
||||
--icon-on-info-base: var(--lilac-light-9);
|
||||
--icon-on-info-hover: var(--lilac-light-alpha-10);
|
||||
--icon-on-info-selected: var(--lilac-light-alpha-11);
|
||||
--icon-diff-add-base: var(--mint-light-11);
|
||||
--icon-diff-add-hover: var(--mint-light-12);
|
||||
--icon-diff-add-active: var(--mint-light-12);
|
||||
--icon-diff-delete-base: var(--ember-light-10);
|
||||
--icon-diff-delete-hover: var(--ember-light-11);
|
||||
--icon-brand-base: #171717;
|
||||
--icon-interactive-base: #034cff;
|
||||
--icon-success-base: #7add71;
|
||||
--icon-success-hover: #4cc944;
|
||||
--icon-success-active: #078901;
|
||||
--icon-warning-base: #ebb76e;
|
||||
--icon-warning-hover: #da9e40;
|
||||
--icon-warning-active: #95671b;
|
||||
--icon-critical-base: #ed4831;
|
||||
--icon-critical-hover: #ca2d17;
|
||||
--icon-critical-active: #601a0f;
|
||||
--icon-info-base: #e6a8ea;
|
||||
--icon-info-hover: #d58cda;
|
||||
--icon-info-active: #9b4da1;
|
||||
--icon-on-brand-base: rgba(0, 0, 0, 0.574);
|
||||
--icon-on-brand-hover: rgba(0, 0, 0, 0.915);
|
||||
--icon-on-brand-selected: rgba(0, 0, 0, 0.915);
|
||||
--icon-on-interactive-base: #fcfcfc;
|
||||
--icon-agent-plan-base: #a753ae;
|
||||
--icon-agent-docs-base: #fcb239;
|
||||
--icon-agent-ask-base: #2090f5;
|
||||
--icon-agent-build-base: #034cff;
|
||||
--icon-on-success-base: rgba(18, 201, 5, 0.9);
|
||||
--icon-on-success-hover: rgba(45, 186, 38, 0.9);
|
||||
--icon-on-success-selected: rgba(7, 137, 1, 0.9);
|
||||
--icon-on-warning-base: rgba(252, 178, 57, 0.9);
|
||||
--icon-on-warning-hover: rgba(239, 167, 46, 0.9);
|
||||
--icon-on-warning-selected: rgba(149, 103, 27, 0.9);
|
||||
--icon-on-critical-base: rgba(252, 83, 58, 0.9);
|
||||
--icon-on-critical-hover: rgba(237, 72, 49, 0.9);
|
||||
--icon-on-critical-selected: rgba(202, 45, 23, 0.9);
|
||||
--icon-on-info-base: #a753ae;
|
||||
--icon-on-info-hover: rgba(155, 73, 162, 0.9);
|
||||
--icon-on-info-selected: rgba(155, 77, 161, 0.9);
|
||||
--icon-diff-add-base: #3a8437;
|
||||
--icon-diff-add-hover: #1d3e1c;
|
||||
--icon-diff-add-active: #1d3e1c;
|
||||
--icon-diff-delete-base: #ed4831;
|
||||
--icon-diff-delete-hover: #ca2d17;
|
||||
--icon-diff-modified-base: #ff8c00;
|
||||
--syntax-comment: var(--text-weak);
|
||||
--syntax-regexp: var(--text-base);
|
||||
@@ -306,12 +310,12 @@
|
||||
--syntax-constant: #007b80;
|
||||
--syntax-punctuation: var(--text-base);
|
||||
--syntax-object: var(--text-strong);
|
||||
--syntax-success: var(--apple-light-10);
|
||||
--syntax-warning: var(--amber-light-10);
|
||||
--syntax-critical: var(--ember-light-10);
|
||||
--syntax-success: #2dba26;
|
||||
--syntax-warning: #efa72e;
|
||||
--syntax-critical: #ed4831;
|
||||
--syntax-info: #0092a8;
|
||||
--syntax-diff-add: var(--mint-light-11);
|
||||
--syntax-diff-delete: var(--ember-light-11);
|
||||
--syntax-diff-add: #3a8437;
|
||||
--syntax-diff-delete: #ca2d17;
|
||||
--syntax-diff-unknown: #ff0000;
|
||||
--markdown-heading: #d68c27;
|
||||
--markdown-text: #1a1a1a;
|
||||
@@ -327,9 +331,6 @@
|
||||
--markdown-image: #3b7dd8;
|
||||
--markdown-image-text: #318795;
|
||||
--markdown-code-block: #1a1a1a;
|
||||
--border-color: #ffffff;
|
||||
--button-ghost-hover: var(--smoke-light-alpha-2);
|
||||
--button-ghost-hover2: var(--smoke-light-alpha-3);
|
||||
--avatar-background-pink: #feeef8;
|
||||
--avatar-background-mint: #e1fbf4;
|
||||
--avatar-background-orange: #fff1e7;
|
||||
@@ -342,210 +343,220 @@
|
||||
--avatar-text-purple: #8445bc;
|
||||
--avatar-text-cyan: #0894b3;
|
||||
--avatar-text-lime: #5d770d;
|
||||
--text-stronger: #171717;
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
color-scheme: dark;
|
||||
--text-mix-blend-mode: plus-lighter;
|
||||
|
||||
/* OC-1 fallback variables (dark) */
|
||||
--background-base: var(--smoke-dark-1);
|
||||
--background-weak: #1c1717;
|
||||
--background-strong: #151313;
|
||||
--background-stronger: #191515;
|
||||
--surface-base: var(--smoke-dark-alpha-2);
|
||||
--base: var(--smoke-dark-alpha-2);
|
||||
--surface-base-hover: #e0b7b716;
|
||||
--surface-base-active: var(--smoke-dark-alpha-3);
|
||||
--surface-base-interactive-active: var(--cobalt-dark-alpha-2);
|
||||
--base2: var(--smoke-dark-alpha-2);
|
||||
--base3: var(--smoke-dark-alpha-2);
|
||||
--surface-inset-base: #0e0b0b7f;
|
||||
--surface-inset-base-hover: #0e0b0b7f;
|
||||
--surface-inset-strong: #060505cc;
|
||||
--surface-inset-strong-hover: #060505cc;
|
||||
--surface-raised-base: var(--smoke-dark-alpha-3);
|
||||
--surface-float-base: var(--smoke-dark-1);
|
||||
--surface-float-base-hover: var(--smoke-dark-2);
|
||||
--surface-raised-base-hover: var(--smoke-dark-alpha-4);
|
||||
--surface-raised-base-active: var(--smoke-dark-alpha-5);
|
||||
--surface-raised-strong: var(--smoke-dark-alpha-4);
|
||||
--surface-raised-strong-hover: var(--smoke-dark-alpha-6);
|
||||
--surface-raised-stronger: var(--smoke-dark-alpha-6);
|
||||
--surface-raised-stronger-hover: var(--smoke-dark-alpha-7);
|
||||
--surface-weak: var(--smoke-dark-alpha-4);
|
||||
--surface-weaker: var(--smoke-dark-alpha-5);
|
||||
--surface-strong: var(--smoke-dark-alpha-7);
|
||||
/* OC-2 fallback variables (dark) */
|
||||
--background-base: #101010;
|
||||
--background-weak: #1e1e1e;
|
||||
--background-strong: #121212;
|
||||
--background-stronger: #151515;
|
||||
--surface-base: rgba(255, 255, 255, 0.031);
|
||||
--base: rgba(255, 255, 255, 0.034);
|
||||
--surface-base-hover: rgba(255, 255, 255, 0.039);
|
||||
--surface-base-active: rgba(255, 255, 255, 0.059);
|
||||
--surface-base-interactive-active: rgba(3, 76, 255, 0.125);
|
||||
--base2: rgba(255, 255, 255, 0.034);
|
||||
--base3: rgba(255, 255, 255, 0.034);
|
||||
--surface-inset-base: rgba(0, 0, 0, 0.5);
|
||||
--surface-inset-base-hover: rgba(0, 0, 0, 0.5);
|
||||
--surface-inset-strong: rgba(0, 0, 0, 0.8);
|
||||
--surface-inset-strong-hover: rgba(0, 0, 0, 0.8);
|
||||
--surface-raised-base: rgba(255, 255, 255, 0.059);
|
||||
--surface-float-base: #161616;
|
||||
--surface-float-base-hover: #1c1c1c;
|
||||
--surface-raised-base-hover: rgba(255, 255, 255, 0.078);
|
||||
--surface-raised-base-active: rgba(255, 255, 255, 0.102);
|
||||
--surface-raised-strong: rgba(255, 255, 255, 0.078);
|
||||
--surface-raised-strong-hover: rgba(255, 255, 255, 0.129);
|
||||
--surface-raised-stronger: rgba(255, 255, 255, 0.129);
|
||||
--surface-raised-stronger-hover: rgba(255, 255, 255, 0.169);
|
||||
--surface-weak: rgba(255, 255, 255, 0.078);
|
||||
--surface-weaker: rgba(255, 255, 255, 0.102);
|
||||
--surface-strong: rgba(255, 255, 255, 0.169);
|
||||
--surface-stronger-non-alpha: var(--surface-raised-stronger-non-alpha);
|
||||
--surface-raised-stronger-non-alpha: var(--smoke-dark-3);
|
||||
--surface-brand-base: var(--yuzu-light-9);
|
||||
--surface-brand-hover: var(--yuzu-light-10);
|
||||
--surface-interactive-base: var(--cobalt-dark-3);
|
||||
--surface-interactive-hover: #0a1d4d;
|
||||
--surface-interactive-weak: var(--cobalt-dark-2);
|
||||
--surface-interactive-weak-hover: var(--cobalt-light-3);
|
||||
--surface-success-base: var(--apple-light-3);
|
||||
--surface-success-weak: var(--apple-light-2);
|
||||
--surface-success-strong: var(--apple-light-9);
|
||||
--surface-warning-base: var(--solaris-light-3);
|
||||
--surface-warning-weak: var(--solaris-light-2);
|
||||
--surface-warning-strong: var(--solaris-light-9);
|
||||
--surface-critical-base: var(--ember-dark-3);
|
||||
--surface-critical-weak: var(--ember-dark-2);
|
||||
--surface-critical-strong: var(--ember-dark-9);
|
||||
--surface-info-base: var(--lilac-light-3);
|
||||
--surface-info-weak: var(--lilac-light-2);
|
||||
--surface-info-strong: var(--lilac-light-9);
|
||||
--surface-diff-unchanged-base: var(--smoke-dark-1);
|
||||
--surface-diff-skip-base: var(--smoke-dark-alpha-1);
|
||||
--surface-diff-hidden-base: var(--blue-dark-2);
|
||||
--surface-diff-hidden-weak: var(--blue-dark-1);
|
||||
--surface-diff-hidden-weaker: var(--blue-dark-3);
|
||||
--surface-diff-hidden-strong: var(--blue-dark-5);
|
||||
--surface-diff-hidden-stronger: var(--blue-dark-11);
|
||||
--surface-diff-add-base: var(--mint-dark-3);
|
||||
--surface-diff-add-weak: var(--mint-dark-4);
|
||||
--surface-diff-add-weaker: var(--mint-dark-3);
|
||||
--surface-diff-add-strong: var(--mint-dark-5);
|
||||
--surface-diff-add-stronger: var(--mint-dark-11);
|
||||
--surface-diff-delete-base: var(--ember-dark-3);
|
||||
--surface-diff-delete-weak: var(--ember-dark-4);
|
||||
--surface-diff-delete-weaker: var(--ember-dark-3);
|
||||
--surface-diff-delete-strong: var(--ember-dark-5);
|
||||
--surface-diff-delete-stronger: var(--ember-dark-11);
|
||||
--input-base: var(--smoke-dark-2);
|
||||
--input-hover: var(--smoke-dark-2);
|
||||
--input-active: var(--cobalt-dark-1);
|
||||
--input-selected: var(--cobalt-dark-2);
|
||||
--input-focus: var(--cobalt-dark-1);
|
||||
--input-disabled: var(--smoke-dark-4);
|
||||
--text-base: var(--smoke-dark-alpha-11);
|
||||
--text-weak: var(--smoke-dark-alpha-9);
|
||||
--text-weaker: var(--smoke-dark-alpha-8);
|
||||
--text-strong: var(--smoke-dark-alpha-12);
|
||||
--text-invert-base: var(--smoke-dark-alpha-11);
|
||||
--text-invert-weak: var(--smoke-dark-alpha-9);
|
||||
--text-invert-weaker: var(--smoke-dark-alpha-8);
|
||||
--text-invert-strong: var(--smoke-dark-alpha-12);
|
||||
--text-interactive-base: var(--cobalt-dark-11);
|
||||
--text-on-brand-base: var(--smoke-dark-alpha-11);
|
||||
--text-on-interactive-base: var(--smoke-dark-12);
|
||||
--text-on-interactive-weak: var(--smoke-dark-alpha-11);
|
||||
--text-on-success-base: var(--apple-dark-9);
|
||||
--text-on-critical-base: var(--ember-dark-9);
|
||||
--text-on-critical-weak: var(--ember-dark-8);
|
||||
--text-on-critical-strong: var(--ember-dark-12);
|
||||
--text-on-warning-base: var(--smoke-dark-alpha-11);
|
||||
--text-on-info-base: var(--smoke-dark-alpha-11);
|
||||
--text-diff-add-base: var(--mint-dark-11);
|
||||
--text-diff-delete-base: var(--ember-dark-9);
|
||||
--text-diff-delete-strong: var(--ember-dark-12);
|
||||
--text-diff-add-strong: var(--mint-dark-8);
|
||||
--text-on-info-weak: var(--smoke-dark-alpha-9);
|
||||
--text-on-info-strong: var(--smoke-dark-alpha-12);
|
||||
--text-on-warning-weak: var(--smoke-dark-alpha-9);
|
||||
--text-on-warning-strong: var(--smoke-dark-alpha-12);
|
||||
--text-on-success-weak: var(--apple-dark-8);
|
||||
--text-on-success-strong: var(--apple-dark-12);
|
||||
--text-on-brand-weak: var(--smoke-dark-alpha-9);
|
||||
--text-on-brand-weaker: var(--smoke-dark-alpha-8);
|
||||
--text-on-brand-strong: var(--smoke-dark-alpha-12);
|
||||
--button-primary-base: var(--smoke-dark-12);
|
||||
--button-secondary-base: #231f1f;
|
||||
--button-secondary-hover: #2a2727;
|
||||
--border-base: var(--smoke-dark-alpha-7);
|
||||
--border-hover: var(--smoke-dark-alpha-8);
|
||||
--border-active: var(--smoke-dark-alpha-9);
|
||||
--border-selected: var(--cobalt-dark-alpha-11);
|
||||
--border-disabled: var(--smoke-dark-alpha-8);
|
||||
--border-focus: var(--smoke-dark-alpha-9);
|
||||
--border-weak-base: var(--smoke-dark-alpha-6);
|
||||
--border-strong-base: var(--smoke-dark-alpha-8);
|
||||
--border-strong-hover: var(--smoke-dark-alpha-7);
|
||||
--border-strong-active: var(--smoke-dark-alpha-8);
|
||||
--border-strong-selected: var(--cobalt-dark-alpha-6);
|
||||
--border-strong-disabled: var(--smoke-dark-alpha-6);
|
||||
--border-strong-focus: var(--smoke-dark-alpha-8);
|
||||
--border-weak-hover: var(--smoke-dark-alpha-7);
|
||||
--border-weak-active: var(--smoke-dark-alpha-8);
|
||||
--border-weak-selected: var(--cobalt-dark-alpha-6);
|
||||
--border-weak-disabled: var(--smoke-dark-alpha-6);
|
||||
--border-weak-focus: var(--smoke-dark-alpha-8);
|
||||
--border-interactive-base: var(--cobalt-light-7);
|
||||
--border-interactive-hover: var(--cobalt-light-8);
|
||||
--border-interactive-active: var(--cobalt-light-9);
|
||||
--border-interactive-selected: var(--cobalt-light-9);
|
||||
--border-interactive-disabled: var(--smoke-light-8);
|
||||
--border-interactive-focus: var(--cobalt-light-9);
|
||||
--border-success-base: var(--apple-light-6);
|
||||
--border-success-hover: var(--apple-light-7);
|
||||
--border-success-selected: var(--apple-light-9);
|
||||
--border-warning-base: var(--solaris-light-6);
|
||||
--border-warning-hover: var(--solaris-light-7);
|
||||
--border-warning-selected: var(--solaris-light-9);
|
||||
--border-critical-base: var(--ember-dark-5);
|
||||
--border-critical-hover: var(--ember-dark-7);
|
||||
--border-critical-selected: var(--ember-dark-9);
|
||||
--border-info-base: var(--lilac-light-6);
|
||||
--border-info-hover: var(--lilac-light-7);
|
||||
--border-info-selected: var(--lilac-light-9);
|
||||
--icon-base: var(--smoke-dark-9);
|
||||
--icon-hover: var(--smoke-dark-10);
|
||||
--icon-active: var(--smoke-dark-11);
|
||||
--icon-selected: var(--smoke-dark-12);
|
||||
--icon-disabled: var(--smoke-dark-7);
|
||||
--icon-focus: var(--smoke-dark-12);
|
||||
--icon-invert-base: var(--smoke-dark-1);
|
||||
--icon-weak-base: var(--smoke-dark-6);
|
||||
--icon-weak-hover: var(--smoke-light-7);
|
||||
--icon-weak-active: var(--smoke-light-8);
|
||||
--icon-weak-selected: var(--smoke-light-9);
|
||||
--icon-weak-disabled: var(--smoke-light-4);
|
||||
--icon-weak-focus: var(--smoke-light-9);
|
||||
--icon-strong-base: var(--smoke-dark-12);
|
||||
--surface-raised-stronger-non-alpha: #1c1c1c;
|
||||
--surface-brand-base: #fab283;
|
||||
--surface-brand-hover: #eda779;
|
||||
--surface-interactive-base: #091f52;
|
||||
--surface-interactive-hover: #091f52;
|
||||
--surface-interactive-weak: #0b1730;
|
||||
--surface-interactive-weak-hover: #ecf3ff;
|
||||
--surface-success-base: #062d04;
|
||||
--surface-success-weak: #0a1e08;
|
||||
--surface-success-strong: #12c905;
|
||||
--surface-warning-base: #fdf3cf;
|
||||
--surface-warning-weak: #fdfaed;
|
||||
--surface-warning-strong: #fcd53a;
|
||||
--surface-critical-base: #42120b;
|
||||
--surface-critical-weak: #28110c;
|
||||
--surface-critical-strong: #fc533a;
|
||||
--surface-info-base: #feecfe;
|
||||
--surface-info-weak: #fdf7fe;
|
||||
--surface-info-strong: #edb2f1;
|
||||
--surface-diff-unchanged-base: #161616;
|
||||
--surface-diff-skip-base: #00000000;
|
||||
--surface-diff-hidden-base: #0c1928;
|
||||
--surface-diff-hidden-weak: #09131d;
|
||||
--surface-diff-hidden-weaker: #082542;
|
||||
--surface-diff-hidden-strong: #073966;
|
||||
--surface-diff-hidden-stronger: #8ec2fc;
|
||||
--surface-diff-add-base: #1a2919;
|
||||
--surface-diff-add-weak: #1f351e;
|
||||
--surface-diff-add-weaker: #1a2919;
|
||||
--surface-diff-add-strong: #264024;
|
||||
--surface-diff-add-stronger: #9bcd97;
|
||||
--surface-diff-delete-base: #42120b;
|
||||
--surface-diff-delete-weak: #580f06;
|
||||
--surface-diff-delete-weaker: #42120b;
|
||||
--surface-diff-delete-strong: #6a1206;
|
||||
--surface-diff-delete-stronger: #faa494;
|
||||
--input-base: #1c1c1c;
|
||||
--input-hover: #1c1c1c;
|
||||
--input-active: #091123;
|
||||
--input-selected: #0b1730;
|
||||
--input-focus: #091123;
|
||||
--input-disabled: #282828;
|
||||
--text-base: rgba(255, 255, 255, 0.618);
|
||||
--text-weak: rgba(255, 255, 255, 0.422);
|
||||
--text-weaker: rgba(255, 255, 255, 0.284);
|
||||
--text-strong: rgba(255, 255, 255, 0.936);
|
||||
--text-invert-base: #a0a0a0;
|
||||
--text-invert-weak: #707070;
|
||||
--text-invert-weaker: #505050;
|
||||
--text-invert-strong: #ededed;
|
||||
--text-interactive-base: #9dbefe;
|
||||
--text-on-brand-base: rgba(255, 255, 255, 0.603);
|
||||
--text-on-interactive-base: #ededed;
|
||||
--text-on-interactive-weak: rgba(255, 255, 255, 0.603);
|
||||
--text-on-success-base: #12c905;
|
||||
--text-on-critical-base: #fc533a;
|
||||
--text-on-critical-weak: #b72d1a;
|
||||
--text-on-critical-strong: #ffe0da;
|
||||
--text-on-warning-base: rgba(255, 255, 255, 0.603);
|
||||
--text-on-info-base: rgba(255, 255, 255, 0.603);
|
||||
--text-diff-add-base: #9bcd97;
|
||||
--text-diff-delete-base: #fc533a;
|
||||
--text-diff-delete-strong: #ffe0da;
|
||||
--text-diff-add-strong: #4a7348;
|
||||
--text-on-info-weak: rgba(255, 255, 255, 0.404);
|
||||
--text-on-info-strong: rgba(255, 255, 255, 0.928);
|
||||
--text-on-warning-weak: rgba(255, 255, 255, 0.404);
|
||||
--text-on-warning-strong: rgba(255, 255, 255, 0.928);
|
||||
--text-on-success-weak: #127d0d;
|
||||
--text-on-success-strong: #bafdb3;
|
||||
--text-on-brand-weak: rgba(255, 255, 255, 0.404);
|
||||
--text-on-brand-weaker: rgba(255, 255, 255, 0.266);
|
||||
--text-on-brand-strong: rgba(255, 255, 255, 0.928);
|
||||
--button-primary-base: #ededed;
|
||||
--button-secondary-base: #1c1c1c;
|
||||
--button-secondary-hover: rgba(255, 255, 255, 0.039);
|
||||
--button-ghost-hover: rgba(255, 255, 255, 0.031);
|
||||
--button-ghost-hover2: rgba(255, 255, 255, 0.059);
|
||||
--border-base: rgba(255, 255, 255, 0.195);
|
||||
--border-hover: rgba(255, 255, 255, 0.284);
|
||||
--border-active: rgba(255, 255, 255, 0.418);
|
||||
--border-selected: #9dbefe;
|
||||
--border-disabled: rgba(255, 255, 255, 0.284);
|
||||
--border-focus: rgba(255, 255, 255, 0.418);
|
||||
--border-weak-base: #282828;
|
||||
--border-strong-base: rgba(255, 255, 255, 0.266);
|
||||
--border-strong-hover: rgba(255, 255, 255, 0.266);
|
||||
--border-strong-active: rgba(255, 255, 255, 0.266);
|
||||
--border-strong-selected: rgba(3, 76, 255, 0.62);
|
||||
--border-strong-disabled: rgba(255, 255, 255, 0.138);
|
||||
--border-strong-focus: rgba(255, 255, 255, 0.266);
|
||||
--border-weak-hover: rgba(255, 255, 255, 0.181);
|
||||
--border-weak-active: rgba(255, 255, 255, 0.266);
|
||||
--border-weak-selected: rgba(3, 76, 255, 0.62);
|
||||
--border-weak-disabled: rgba(255, 255, 255, 0.138);
|
||||
--border-weak-focus: rgba(255, 255, 255, 0.266);
|
||||
--border-weaker-base: #202020;
|
||||
--border-weaker-hover: rgba(255, 255, 255, 0.084);
|
||||
--border-weaker-active: rgba(255, 255, 255, 0.138);
|
||||
--border-weaker-selected: rgba(3, 76, 255, 0.32);
|
||||
--border-weaker-disabled: rgba(255, 255, 255, 0.034);
|
||||
--border-weaker-focus: rgba(255, 255, 255, 0.138);
|
||||
--border-interactive-base: #a3c1fd;
|
||||
--border-interactive-hover: #7ea9ff;
|
||||
--border-interactive-active: #034cff;
|
||||
--border-interactive-selected: #034cff;
|
||||
--border-interactive-disabled: #505050;
|
||||
--border-interactive-focus: #034cff;
|
||||
--border-success-base: #96ec8e;
|
||||
--border-success-hover: #7add71;
|
||||
--border-success-selected: #12c905;
|
||||
--border-warning-base: #e9d282;
|
||||
--border-warning-hover: #dac063;
|
||||
--border-warning-selected: #fcd53a;
|
||||
--border-critical-base: #6a1206;
|
||||
--border-critical-hover: #952414;
|
||||
--border-critical-selected: #fc533a;
|
||||
--border-info-base: #eac5ec;
|
||||
--border-info-hover: #dab1dd;
|
||||
--border-info-selected: #edb2f1;
|
||||
--border-color: #ffffff;
|
||||
--icon-base: #7e7e7e;
|
||||
--icon-hover: #a0a0a0;
|
||||
--icon-active: #ededed;
|
||||
--icon-selected: #ededed;
|
||||
--icon-disabled: #3e3e3e;
|
||||
--icon-focus: #ededed;
|
||||
--icon-invert-base: #161616;
|
||||
--icon-weak-base: #343434;
|
||||
--icon-weak-hover: #d9d9d9;
|
||||
--icon-weak-active: #c8c8c8;
|
||||
--icon-weak-selected: #707070;
|
||||
--icon-weak-disabled: #ededed;
|
||||
--icon-weak-focus: #707070;
|
||||
--icon-strong-base: #ededed;
|
||||
--icon-strong-hover: #f6f3f3;
|
||||
--icon-strong-active: #fcfcfc;
|
||||
--icon-strong-selected: #fdfcfc;
|
||||
--icon-strong-disabled: var(--smoke-dark-8);
|
||||
--icon-strong-disabled: #3e3e3e;
|
||||
--icon-strong-focus: #fdfcfc;
|
||||
--icon-brand-base: var(--white);
|
||||
--icon-interactive-base: var(--cobalt-dark-11);
|
||||
--icon-success-base: var(--apple-dark-7);
|
||||
--icon-success-hover: var(--apple-dark-8);
|
||||
--icon-success-active: var(--apple-dark-11);
|
||||
--icon-warning-base: var(--amber-dark-9);
|
||||
--icon-warning-hover: var(--amber-dark-8);
|
||||
--icon-warning-active: var(--amber-dark-11);
|
||||
--icon-critical-base: var(--ember-dark-9);
|
||||
--icon-critical-hover: var(--ember-dark-11);
|
||||
--icon-critical-active: var(--ember-dark-12);
|
||||
--icon-info-base: var(--lilac-dark-7);
|
||||
--icon-info-hover: var(--lilac-dark-8);
|
||||
--icon-info-active: var(--lilac-dark-11);
|
||||
--icon-on-brand-base: var(--smoke-light-alpha-11);
|
||||
--icon-on-brand-hover: var(--smoke-light-alpha-12);
|
||||
--icon-on-brand-selected: var(--smoke-light-alpha-12);
|
||||
--icon-on-interactive-base: var(--smoke-dark-12);
|
||||
--icon-agent-plan-base: var(--purple-dark-9);
|
||||
--icon-agent-docs-base: var(--amber-dark-9);
|
||||
--icon-agent-ask-base: var(--cyan-dark-9);
|
||||
--icon-agent-build-base: var(--cobalt-dark-11);
|
||||
--icon-on-success-base: var(--apple-dark-alpha-9);
|
||||
--icon-on-success-hover: var(--apple-dark-alpha-10);
|
||||
--icon-on-success-selected: var(--apple-dark-alpha-11);
|
||||
--icon-on-warning-base: var(--amber-darkalpha-9);
|
||||
--icon-on-warning-hover: var(--amber-darkalpha-10);
|
||||
--icon-on-warning-selected: var(--amber-darkalpha-11);
|
||||
--icon-on-critical-base: var(--ember-dark-alpha-9);
|
||||
--icon-on-critical-hover: var(--ember-dark-alpha-10);
|
||||
--icon-on-critical-selected: var(--ember-dark-alpha-11);
|
||||
--icon-on-info-base: var(--lilac-dark-9);
|
||||
--icon-on-info-hover: var(--lilac-dark-alpha-10);
|
||||
--icon-on-info-selected: var(--lilac-dark-alpha-11);
|
||||
--icon-diff-add-base: var(--mint-dark-11);
|
||||
--icon-diff-add-hover: var(--mint-dark-10);
|
||||
--icon-diff-add-active: var(--mint-dark-11);
|
||||
--icon-diff-delete-base: var(--ember-dark-9);
|
||||
--icon-diff-delete-hover: var(--ember-dark-10);
|
||||
--icon-brand-base: #ffffff;
|
||||
--icon-interactive-base: #034cff;
|
||||
--icon-success-base: #12c905;
|
||||
--icon-success-hover: #35c02d;
|
||||
--icon-success-active: #4de144;
|
||||
--icon-warning-base: #fbb73c;
|
||||
--icon-warning-hover: #885e08;
|
||||
--icon-warning-active: #f1b13f;
|
||||
--icon-critical-base: #fc533a;
|
||||
--icon-critical-hover: #faa494;
|
||||
--icon-critical-active: #ffe0da;
|
||||
--icon-info-base: #68446b;
|
||||
--icon-info-hover: #815484;
|
||||
--icon-info-active: #dfa7e3;
|
||||
--icon-on-brand-base: rgba(255, 255, 255, 0.603);
|
||||
--icon-on-brand-hover: rgba(255, 255, 255, 0.928);
|
||||
--icon-on-brand-selected: rgba(255, 255, 255, 0.928);
|
||||
--icon-on-interactive-base: #ededed;
|
||||
--icon-agent-plan-base: #edb2f1;
|
||||
--icon-agent-docs-base: #fbb73c;
|
||||
--icon-agent-ask-base: #2090f5;
|
||||
--icon-agent-build-base: #9dbefe;
|
||||
--icon-on-success-base: rgba(18, 201, 5, 0.9);
|
||||
--icon-on-success-hover: rgba(53, 192, 45, 0.9);
|
||||
--icon-on-success-selected: rgba(77, 225, 68, 0.9);
|
||||
--icon-on-warning-base: rgba(251, 183, 60, 0.9);
|
||||
--icon-on-warning-hover: rgba(245, 178, 56, 0.9);
|
||||
--icon-on-warning-selected: rgba(241, 177, 63, 0.9);
|
||||
--icon-on-critical-base: rgba(252, 83, 58, 0.9);
|
||||
--icon-on-critical-hover: rgba(245, 79, 54, 0.9);
|
||||
--icon-on-critical-selected: rgba(250, 164, 148, 0.9);
|
||||
--icon-on-info-base: #edb2f1;
|
||||
--icon-on-info-hover: rgba(231, 173, 235, 0.9);
|
||||
--icon-on-info-selected: rgba(223, 167, 227, 0.9);
|
||||
--icon-diff-add-base: #9bcd97;
|
||||
--icon-diff-add-hover: #c3f9bf;
|
||||
--icon-diff-add-active: #9bcd97;
|
||||
--icon-diff-delete-base: #fc533a;
|
||||
--icon-diff-delete-hover: #f54f36;
|
||||
--icon-diff-modified-base: #ffba92;
|
||||
--syntax-comment: var(--text-weak);
|
||||
--syntax-regexp: var(--text-base);
|
||||
@@ -559,12 +570,12 @@
|
||||
--syntax-constant: #93e9f6;
|
||||
--syntax-punctuation: var(--text-weak);
|
||||
--syntax-object: var(--text-strong);
|
||||
--syntax-success: var(--apple-dark-10);
|
||||
--syntax-warning: var(--amber-dark-10);
|
||||
--syntax-critical: var(--ember-dark-10);
|
||||
--syntax-success: #35c02d;
|
||||
--syntax-warning: #f5b238;
|
||||
--syntax-critical: #f54f36;
|
||||
--syntax-info: #93e9f6;
|
||||
--syntax-diff-add: var(--mint-dark-11);
|
||||
--syntax-diff-delete: var(--ember-dark-11);
|
||||
--syntax-diff-add: #9bcd97;
|
||||
--syntax-diff-delete: #faa494;
|
||||
--syntax-diff-unknown: #ff0000;
|
||||
--markdown-heading: #9d7cd8;
|
||||
--markdown-text: #eeeeee;
|
||||
@@ -580,10 +591,6 @@
|
||||
--markdown-image: #fab283;
|
||||
--markdown-image-text: #56b6c2;
|
||||
--markdown-code-block: #eeeeee;
|
||||
--border-color: #ffffff;
|
||||
--border-weaker-base: var(--smoke-dark-alpha-2);
|
||||
--button-ghost-hover: var(--smoke-dark-alpha-2);
|
||||
--button-ghost-hover2: var(--smoke-dark-alpha-3);
|
||||
--avatar-background-pink: #501b3f;
|
||||
--avatar-background-mint: #033a34;
|
||||
--avatar-background-orange: #5f2a06;
|
||||
@@ -596,5 +603,6 @@
|
||||
--avatar-text-purple: #9d5bd2;
|
||||
--avatar-text-cyan: #369eff;
|
||||
--avatar-text-lime: #c4f042;
|
||||
--text-stronger: rgba(255, 255, 255, 0.936);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
import type { HexColor, OklchColor } from "./types"
|
||||
|
||||
function clamp(v: number, min: number, max: number) {
|
||||
return Math.max(min, Math.min(max, v))
|
||||
}
|
||||
|
||||
function hue(v: number) {
|
||||
return ((v % 360) + 360) % 360
|
||||
}
|
||||
|
||||
export function hexToRgb(hex: HexColor): { r: number; g: number; b: number } {
|
||||
const h = hex.replace("#", "")
|
||||
const full =
|
||||
h.length === 3
|
||||
h.length === 3 || h.length === 4
|
||||
? h
|
||||
.split("")
|
||||
.map((c) => c + c)
|
||||
.join("")
|
||||
: h
|
||||
const rgb = full.length === 8 ? full.slice(0, 6) : full
|
||||
|
||||
const num = parseInt(full, 16)
|
||||
const num = parseInt(rgb, 16)
|
||||
return {
|
||||
r: ((num >> 16) & 255) / 255,
|
||||
g: ((num >> 8) & 255) / 255,
|
||||
@@ -20,7 +29,7 @@ export function hexToRgb(hex: HexColor): { r: number; g: number; b: number } {
|
||||
|
||||
export function rgbToHex(r: number, g: number, b: number): HexColor {
|
||||
const toHex = (v: number) => {
|
||||
const clamped = Math.max(0, Math.min(1, v))
|
||||
const clamped = clamp(v, 0, 1)
|
||||
const int = Math.round(clamped * 255)
|
||||
return int.toString(16).padStart(2, "0")
|
||||
}
|
||||
@@ -91,8 +100,33 @@ export function hexToOklch(hex: HexColor): OklchColor {
|
||||
return rgbToOklch(r, g, b)
|
||||
}
|
||||
|
||||
export function fitOklch(oklch: OklchColor): OklchColor {
|
||||
const base = {
|
||||
l: clamp(oklch.l, 0, 1),
|
||||
c: Math.max(0, oklch.c),
|
||||
h: hue(oklch.h),
|
||||
}
|
||||
|
||||
const rgb = oklchToRgb(base)
|
||||
if (rgb.r >= 0 && rgb.r <= 1 && rgb.g >= 0 && rgb.g <= 1 && rgb.b >= 0 && rgb.b <= 1) {
|
||||
return base
|
||||
}
|
||||
|
||||
let c = base.c
|
||||
for (let i = 0; i < 24; i++) {
|
||||
c *= 0.9
|
||||
const next = { ...base, c }
|
||||
const out = oklchToRgb(next)
|
||||
if (out.r >= 0 && out.r <= 1 && out.g >= 0 && out.g <= 1 && out.b >= 0 && out.b <= 1) {
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
return { ...base, c: 0 }
|
||||
}
|
||||
|
||||
export function oklchToHex(oklch: OklchColor): HexColor {
|
||||
const { r, g, b } = oklchToRgb(oklch)
|
||||
const { r, g, b } = oklchToRgb(fitOklch(oklch))
|
||||
return rgbToHex(r, g, b)
|
||||
}
|
||||
|
||||
@@ -101,12 +135,12 @@ export function generateScale(seed: HexColor, isDark: boolean): HexColor[] {
|
||||
const scale: HexColor[] = []
|
||||
|
||||
const lightSteps = isDark
|
||||
? [0.15, 0.18, 0.22, 0.26, 0.32, 0.38, 0.46, 0.56, base.l, base.l - 0.05, 0.75, 0.93]
|
||||
: [0.99, 0.97, 0.94, 0.9, 0.85, 0.79, 0.72, 0.64, base.l, base.l + 0.05, 0.45, 0.25]
|
||||
? [0.182, 0.21, 0.261, 0.302, 0.341, 0.387, 0.443, 0.514, base.l, Math.max(0, base.l - 0.017), 0.8, 0.93]
|
||||
: [0.993, 0.983, 0.962, 0.936, 0.906, 0.866, 0.811, 0.74, base.l, Math.max(0, base.l - 0.036), 0.548, 0.33]
|
||||
|
||||
const chromaMultipliers = isDark
|
||||
? [0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.85, 1, 1, 0.9, 0.6]
|
||||
: [0.1, 0.15, 0.25, 0.35, 0.45, 0.55, 0.7, 0.85, 1, 1, 0.95, 0.85]
|
||||
? [0.205, 0.275, 0.46, 0.62, 0.71, 0.79, 0.87, 0.97, 1.04, 1.03, 1, 0.58]
|
||||
: [0.045, 0.128, 0.34, 0.5, 0.61, 0.69, 0.77, 0.89, 1, 1, 0.97, 0.56]
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
scale.push(
|
||||
@@ -127,8 +161,8 @@ export function generateNeutralScale(seed: HexColor, isDark: boolean): HexColor[
|
||||
const neutralChroma = Math.min(base.c, 0.02)
|
||||
|
||||
const lightSteps = isDark
|
||||
? [0.13, 0.16, 0.2, 0.24, 0.28, 0.33, 0.4, 0.52, 0.58, 0.66, 0.82, 0.96]
|
||||
: [0.995, 0.98, 0.96, 0.94, 0.91, 0.88, 0.84, 0.78, 0.62, 0.56, 0.46, 0.2]
|
||||
? [0.2, 0.226, 0.256, 0.277, 0.301, 0.325, 0.364, 0.431, base.l, 0.593, 0.706, 0.946]
|
||||
: [0.991, 0.979, 0.964, 0.946, 0.931, 0.913, 0.891, 0.83, base.l, 0.617, 0.542, 0.205]
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
scale.push(
|
||||
@@ -164,19 +198,39 @@ export function generateAlphaScale(scale: HexColor[], isDark: boolean): HexColor
|
||||
export function mixColors(color1: HexColor, color2: HexColor, amount: number): HexColor {
|
||||
const c1 = hexToOklch(color1)
|
||||
const c2 = hexToOklch(color2)
|
||||
const delta = ((((c2.h - c1.h) % 360) + 540) % 360) - 180
|
||||
|
||||
return oklchToHex({
|
||||
l: c1.l + (c2.l - c1.l) * amount,
|
||||
c: c1.c + (c2.c - c1.c) * amount,
|
||||
h: c1.h + (c2.h - c1.h) * amount,
|
||||
h: c1.h + delta * amount,
|
||||
})
|
||||
}
|
||||
|
||||
export function shift(color: HexColor, value: { l?: number; c?: number; h?: number }): HexColor {
|
||||
const base = hexToOklch(color)
|
||||
return oklchToHex({
|
||||
l: base.l + (value.l ?? 0),
|
||||
c: base.c * (value.c ?? 1),
|
||||
h: base.h + (value.h ?? 0),
|
||||
})
|
||||
}
|
||||
|
||||
export function blend(color: HexColor, background: HexColor, alpha: number): HexColor {
|
||||
const fg = hexToRgb(color)
|
||||
const bg = hexToRgb(background)
|
||||
return rgbToHex(
|
||||
fg.r * alpha + bg.r * (1 - alpha),
|
||||
fg.g * alpha + bg.g * (1 - alpha),
|
||||
fg.b * alpha + bg.b * (1 - alpha),
|
||||
)
|
||||
}
|
||||
|
||||
export function lighten(color: HexColor, amount: number): HexColor {
|
||||
const oklch = hexToOklch(color)
|
||||
return oklchToHex({
|
||||
...oklch,
|
||||
l: Math.min(1, oklch.l + amount),
|
||||
l: clamp(oklch.l + amount, 0, 1),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -184,7 +238,7 @@ export function darken(color: HexColor, amount: number): HexColor {
|
||||
const oklch = hexToOklch(color)
|
||||
return oklchToHex({
|
||||
...oklch,
|
||||
l: Math.max(0, oklch.l - amount),
|
||||
l: clamp(oklch.l - amount, 0, 1),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ function applyThemeCss(theme: DesktopTheme, themeId: string, mode: "light" | "da
|
||||
const tokens = resolveThemeVariant(variant, isDark)
|
||||
const css = themeToCss(tokens)
|
||||
|
||||
if (themeId !== "oc-1") {
|
||||
if (themeId !== "oc-2") {
|
||||
try {
|
||||
localStorage.setItem(isDark ? STORAGE_KEYS.THEME_CSS_DARK : STORAGE_KEYS.THEME_CSS_LIGHT, css)
|
||||
} catch {}
|
||||
@@ -54,7 +54,7 @@ function applyThemeCss(theme: DesktopTheme, themeId: string, mode: "light" | "da
|
||||
}
|
||||
|
||||
function cacheThemeVariants(theme: DesktopTheme, themeId: string) {
|
||||
if (themeId === "oc-1") return
|
||||
if (themeId === "oc-2") return
|
||||
for (const mode of ["light", "dark"] as const) {
|
||||
const isDark = mode === "dark"
|
||||
const variant = isDark ? theme.dark : theme.light
|
||||
@@ -71,7 +71,7 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
|
||||
init: (props: { defaultTheme?: string }) => {
|
||||
const [store, setStore] = createStore({
|
||||
themes: DEFAULT_THEMES as Record<string, DesktopTheme>,
|
||||
themeId: props.defaultTheme ?? "oc-1",
|
||||
themeId: props.defaultTheme ?? "oc-2",
|
||||
colorScheme: "system" as ColorScheme,
|
||||
mode: getSystemMode(),
|
||||
previewThemeId: null as string | null,
|
||||
|
||||
@@ -34,8 +34,8 @@ export const gruvboxTheme = gruvboxThemeJson as DesktopTheme
|
||||
export const auraTheme = auraThemeJson as DesktopTheme
|
||||
|
||||
export const DEFAULT_THEMES: Record<string, DesktopTheme> = {
|
||||
"oc-1": oc1Theme,
|
||||
"oc-2": oc2Theme,
|
||||
"oc-1": oc1Theme,
|
||||
aura: auraTheme,
|
||||
ayu: ayuTheme,
|
||||
carbonfox: carbonfoxTheme,
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
},
|
||||
"ColorValue": {
|
||||
"type": "string",
|
||||
"pattern": "^(#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|var\(--[a-z0-9-]+\))$",
|
||||
"pattern": "^(#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|var\\(--[a-z0-9-]+\\))$",
|
||||
"description": "Either a hex color value (#rgb/#rgba/#rrggbb/#rrggbbaa) or a CSS variable reference"
|
||||
},
|
||||
"ThemeSeedColors": {
|
||||
"type": "object",
|
||||
"description": "The minimum set of colors needed to generate a theme",
|
||||
"description": "The legacy semantic seed set used to generate a theme",
|
||||
"additionalProperties": false,
|
||||
"required": ["neutral", "primary", "success", "warning", "error", "info", "interactive", "diffAdd", "diffDelete"],
|
||||
"properties": {
|
||||
"neutral": {
|
||||
@@ -82,14 +83,70 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ThemePaletteColors": {
|
||||
"type": "object",
|
||||
"description": "A compact semantic palette used to derive the full theme programmatically",
|
||||
"additionalProperties": false,
|
||||
"required": ["neutral", "primary", "success", "warning", "error", "info"],
|
||||
"properties": {
|
||||
"neutral": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Base neutral color for generating the gray scale"
|
||||
},
|
||||
"ink": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Optional foreground or chrome color used to derive text and border tones"
|
||||
},
|
||||
"primary": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Primary brand color used for brand surfaces and strong emphasis"
|
||||
},
|
||||
"success": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Success state color"
|
||||
},
|
||||
"warning": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Warning state color"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Error or critical state color"
|
||||
},
|
||||
"info": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Informational state color"
|
||||
},
|
||||
"accent": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Optional extra expressive accent for syntax and rich content"
|
||||
},
|
||||
"interactive": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Optional dedicated interactive color; falls back to primary"
|
||||
},
|
||||
"diffAdd": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Optional diff-add seed; falls back to a softened success color"
|
||||
},
|
||||
"diffDelete": {
|
||||
"$ref": "#/definitions/HexColor",
|
||||
"description": "Optional diff-delete seed; falls back to error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ThemeVariant": {
|
||||
"type": "object",
|
||||
"description": "A theme variant (light or dark) with seed colors and optional overrides",
|
||||
"required": ["seeds"],
|
||||
"description": "A theme variant (light or dark) with either a compact palette or legacy seeds and optional overrides",
|
||||
"oneOf": [{ "required": ["seeds"] }, { "required": ["palette"] }],
|
||||
"properties": {
|
||||
"seeds": {
|
||||
"$ref": "#/definitions/ThemeSeedColors",
|
||||
"description": "Seed colors used to generate the full palette"
|
||||
"description": "Legacy seed colors used to generate the full palette"
|
||||
},
|
||||
"palette": {
|
||||
"$ref": "#/definitions/ThemePaletteColors",
|
||||
"description": "Compact palette used to derive the full token set"
|
||||
},
|
||||
"overrides": {
|
||||
"type": "object",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export type {
|
||||
DesktopTheme,
|
||||
ThemePaletteColors,
|
||||
ThemeSeedColors,
|
||||
ThemeVariant,
|
||||
HexColor,
|
||||
@@ -19,7 +20,10 @@ export {
|
||||
generateScale,
|
||||
generateNeutralScale,
|
||||
generateAlphaScale,
|
||||
fitOklch,
|
||||
blend,
|
||||
mixColors,
|
||||
shift,
|
||||
lighten,
|
||||
darken,
|
||||
withAlpha,
|
||||
|
||||
@@ -27,7 +27,7 @@ export function applyTheme(theme: DesktopTheme, themeId?: string): void {
|
||||
}
|
||||
|
||||
function buildThemeCss(light: ResolvedTheme, dark: ResolvedTheme, themeId: string): string {
|
||||
const isDefaultTheme = themeId === "oc-1"
|
||||
const isDefaultTheme = themeId === "oc-2"
|
||||
const lightCss = themeToCss(light)
|
||||
const darkCss = themeToCss(dark)
|
||||
|
||||
|
||||
@@ -1,27 +1,131 @@
|
||||
import type { ColorValue, DesktopTheme, HexColor, ResolvedTheme, ThemeVariant } from "./types"
|
||||
import { generateNeutralScale, generateScale, hexToOklch, oklchToHex, withAlpha } from "./color"
|
||||
import { blend, generateNeutralScale, generateScale, hexToOklch, oklchToHex, shift, withAlpha } from "./color"
|
||||
|
||||
export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): ResolvedTheme {
|
||||
const { seeds, overrides = {} } = variant
|
||||
const colors = getColors(variant)
|
||||
const { overrides = {} } = variant
|
||||
|
||||
const neutral = generateNeutralScale(seeds.neutral, isDark)
|
||||
const primary = generateScale(seeds.primary, isDark)
|
||||
const success = generateScale(seeds.success, isDark)
|
||||
const warning = generateScale(seeds.warning, isDark)
|
||||
const error = generateScale(seeds.error, isDark)
|
||||
const info = generateScale(seeds.info, isDark)
|
||||
const interactive = generateScale(seeds.interactive, isDark)
|
||||
const diffAdd = generateScale(seeds.diffAdd, isDark)
|
||||
const diffDelete = generateScale(seeds.diffDelete, isDark)
|
||||
const neutral = generateNeutralScale(colors.neutral, isDark)
|
||||
const primary = generateScale(colors.primary, isDark)
|
||||
const accent = generateScale(colors.accent, isDark)
|
||||
const success = generateScale(colors.success, isDark)
|
||||
const warning = generateScale(colors.warning, isDark)
|
||||
const error = generateScale(colors.error, isDark)
|
||||
const info = generateScale(colors.info, isDark)
|
||||
const interactive = generateScale(colors.interactive, isDark)
|
||||
const hasInk = colors.compact && Boolean(colors.ink)
|
||||
const noInk = colors.compact && !hasInk
|
||||
const shadow = noInk && !isDark ? generateNeutralScale(colors.neutral, true) : neutral
|
||||
const amber = generateScale(
|
||||
shift(colors.warning, isDark ? { h: -16, l: -0.058, c: 1.14 } : { h: -22, l: -0.082, c: 0.94 }),
|
||||
isDark,
|
||||
)
|
||||
const blue = generateScale(shift(colors.interactive, { h: -12, l: 0.128, c: 1.12 }), isDark)
|
||||
const brandl = noInk && isDark ? generateScale(colors.primary, false) : primary
|
||||
const successl = noInk && isDark ? generateScale(colors.success, false) : success
|
||||
const warningl = noInk && isDark ? generateScale(colors.warning, false) : warning
|
||||
const infol = noInk && isDark ? generateScale(colors.info, false) : info
|
||||
const interl = noInk && isDark ? generateScale(colors.interactive, false) : interactive
|
||||
const diffAdd = generateScale(
|
||||
colors.diffAdd ??
|
||||
(noInk
|
||||
? shift(colors.success, { c: isDark ? 0.54 : 0.6, l: isDark ? 0.22 : 0.16 })
|
||||
: shift(colors.success, { c: isDark ? 0.7 : 0.55, l: isDark ? -0.18 : 0.14 })),
|
||||
isDark,
|
||||
)
|
||||
const diffDelete = generateScale(
|
||||
colors.diffDelete ??
|
||||
(noInk ? colors.error : shift(colors.error, { c: isDark ? 0.82 : 0.7, l: isDark ? -0.08 : 0.08 })),
|
||||
isDark,
|
||||
)
|
||||
const ink = colors.ink ?? colors.neutral
|
||||
const backgroundOverride = overrides["background-base"]
|
||||
const backgroundHex = getHex(backgroundOverride)
|
||||
const overlay = noInk || (Boolean(backgroundOverride) && !backgroundHex)
|
||||
const content = (seed: HexColor, scale: HexColor[]) => {
|
||||
const value = isDark ? seed : hexToOklch(seed).l > 0.82 ? scale[10] : seed
|
||||
return shift(value, { c: isDark ? 1.16 : 1.1 })
|
||||
}
|
||||
const modified = () => {
|
||||
if (!colors.compact) return isDark ? "#ffba92" : "#FF8C00"
|
||||
if (!hasInk) return isDark ? "#ffba92" : "#FF8C00"
|
||||
const warningHue = hexToOklch(colors.warning).h
|
||||
const deleteHue = hexToOklch(colors.diffDelete ?? colors.error).h
|
||||
const delta = Math.abs(((((deleteHue - warningHue) % 360) + 540) % 360) - 180)
|
||||
if (delta < 48) return isDark ? "#ffba92" : "#FF8C00"
|
||||
return content(colors.warning, warning)
|
||||
}
|
||||
const surface = (
|
||||
seed: HexColor,
|
||||
alpha: { base: number; weak: number; weaker: number; strong: number; stronger: number },
|
||||
) => {
|
||||
const base = alphaTone(seed, alpha.base)
|
||||
return {
|
||||
base,
|
||||
weak: alphaTone(seed, alpha.weak),
|
||||
weaker: alphaTone(seed, alpha.weaker),
|
||||
strong: alphaTone(seed, alpha.strong),
|
||||
stronger: alphaTone(seed, alpha.stronger),
|
||||
}
|
||||
}
|
||||
const compactBackground =
|
||||
colors.compact && !hasInk
|
||||
? isDark
|
||||
? {
|
||||
base: shift(blend(colors.neutral, "#000000", 0.145), { c: 0 }),
|
||||
weak: shift(blend(colors.neutral, "#000000", 0.27), { c: 0 }),
|
||||
strong: shift(blend(colors.neutral, "#000000", 0.165), { c: 0 }),
|
||||
stronger: shift(blend(colors.neutral, "#000000", 0.19), { c: 0 }),
|
||||
}
|
||||
: {
|
||||
base: blend(colors.neutral, "#ffffff", 0.066),
|
||||
weak: blend(colors.neutral, "#ffffff", 0.11),
|
||||
strong: blend(colors.neutral, "#ffffff", 0.024),
|
||||
stronger: blend(colors.neutral, "#ffffff", 0.024),
|
||||
}
|
||||
: undefined
|
||||
const compactInkBackground =
|
||||
colors.compact && hasInk && isDark
|
||||
? {
|
||||
base: neutral[2],
|
||||
weak: neutral[3],
|
||||
strong: neutral[1],
|
||||
stronger: neutral[2],
|
||||
}
|
||||
: undefined
|
||||
|
||||
const neutralAlpha = generateNeutralAlphaScale(neutral, isDark)
|
||||
const background = backgroundHex ?? compactInkBackground?.base ?? compactBackground?.base ?? neutral[0]
|
||||
const alphaTone = (color: HexColor, alpha: number) =>
|
||||
overlay ? (withAlpha(color, alpha) as ColorValue) : blend(color, background, alpha)
|
||||
const borderTone = (light: number, dark: number) =>
|
||||
alphaTone(
|
||||
ink,
|
||||
isDark ? Math.min(1, dark + 0.024 + (colors.compact && hasInk ? 0.08 : 0)) : Math.min(1, light + 0.024),
|
||||
)
|
||||
const diffHiddenSurface = noInk
|
||||
? {
|
||||
base: blue[isDark ? 1 : 2],
|
||||
weak: blue[isDark ? 0 : 1],
|
||||
weaker: blue[isDark ? 2 : 0],
|
||||
strong: blue[4],
|
||||
stronger: blue[isDark ? 10 : 8],
|
||||
}
|
||||
: surface(
|
||||
isDark ? shift(colors.interactive, { c: 0.55, l: 0 }) : shift(colors.interactive, { c: 0.45, l: 0.08 }),
|
||||
isDark
|
||||
? { base: 0.14, weak: 0.08, weaker: 0.18, strong: 0.26, stronger: 0.42 }
|
||||
: { base: 0.12, weak: 0.08, weaker: 0.16, strong: 0.24, stronger: 0.36 },
|
||||
)
|
||||
|
||||
const neutralAlpha = noInk ? generateNeutralOverlayScale(neutral, isDark) : generateNeutralAlphaScale(neutral, isDark)
|
||||
|
||||
const tokens: ResolvedTheme = {}
|
||||
|
||||
tokens["background-base"] = neutral[0]
|
||||
tokens["background-weak"] = neutral[2]
|
||||
tokens["background-strong"] = neutral[0]
|
||||
tokens["background-stronger"] = isDark ? neutral[1] : "#fcfcfc"
|
||||
tokens["background-base"] = compactInkBackground?.base ?? compactBackground?.base ?? neutral[0]
|
||||
tokens["background-weak"] = compactInkBackground?.weak ?? compactBackground?.weak ?? neutral[2]
|
||||
tokens["background-strong"] = compactInkBackground?.strong ?? compactBackground?.strong ?? neutral[0]
|
||||
tokens["background-stronger"] =
|
||||
compactInkBackground?.stronger ?? compactBackground?.stronger ?? (isDark ? neutral[1] : "#fcfcfc")
|
||||
|
||||
tokens["surface-base"] = neutralAlpha[1]
|
||||
tokens["base"] = neutralAlpha[1]
|
||||
@@ -37,8 +141,8 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
: (withAlpha(neutral[3], 0.09) as ColorValue)
|
||||
tokens["surface-inset-strong-hover"] = tokens["surface-inset-strong"]
|
||||
tokens["surface-raised-base"] = neutralAlpha[0]
|
||||
tokens["surface-float-base"] = isDark ? neutral[0] : neutral[11]
|
||||
tokens["surface-float-base-hover"] = isDark ? neutral[1] : neutral[10]
|
||||
tokens["surface-float-base"] = isDark ? neutral[0] : noInk ? shadow[0] : neutral[11]
|
||||
tokens["surface-float-base-hover"] = isDark ? neutral[1] : noInk ? shadow[1] : neutral[10]
|
||||
tokens["surface-raised-base-hover"] = neutralAlpha[1]
|
||||
tokens["surface-raised-base-active"] = neutralAlpha[2]
|
||||
tokens["surface-raised-strong"] = isDark ? neutralAlpha[3] : neutral[0]
|
||||
@@ -50,34 +154,34 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
tokens["surface-strong"] = isDark ? neutralAlpha[6] : "#ffffff"
|
||||
tokens["surface-raised-stronger-non-alpha"] = isDark ? neutral[2] : "#ffffff"
|
||||
|
||||
tokens["surface-brand-base"] = primary[8]
|
||||
tokens["surface-brand-hover"] = primary[9]
|
||||
tokens["surface-brand-base"] = brandl[8]
|
||||
tokens["surface-brand-hover"] = brandl[9]
|
||||
|
||||
tokens["surface-interactive-base"] = interactive[2]
|
||||
tokens["surface-interactive-hover"] = interactive[3]
|
||||
tokens["surface-interactive-weak"] = interactive[1]
|
||||
tokens["surface-interactive-weak-hover"] = interactive[2]
|
||||
tokens["surface-interactive-base"] = interactive[isDark ? 4 : 3]
|
||||
tokens["surface-interactive-hover"] = interactive[isDark ? 5 : 4]
|
||||
tokens["surface-interactive-weak"] = interactive[isDark ? 3 : 2]
|
||||
tokens["surface-interactive-weak-hover"] = noInk && isDark ? interl[4] : interactive[isDark ? 4 : 3]
|
||||
|
||||
tokens["surface-success-base"] = success[2]
|
||||
tokens["surface-success-weak"] = success[1]
|
||||
tokens["surface-success-strong"] = success[8]
|
||||
tokens["surface-warning-base"] = warning[2]
|
||||
tokens["surface-warning-weak"] = warning[1]
|
||||
tokens["surface-warning-strong"] = warning[8]
|
||||
tokens["surface-critical-base"] = error[2]
|
||||
tokens["surface-critical-weak"] = error[1]
|
||||
tokens["surface-critical-strong"] = error[8]
|
||||
tokens["surface-info-base"] = info[2]
|
||||
tokens["surface-info-weak"] = info[1]
|
||||
tokens["surface-info-strong"] = info[8]
|
||||
tokens["surface-success-base"] = success[isDark ? 4 : 3]
|
||||
tokens["surface-success-weak"] = success[isDark ? 3 : 2]
|
||||
tokens["surface-success-strong"] = success[9]
|
||||
tokens["surface-warning-base"] = (noInk && isDark ? warningl : warning)[isDark ? 4 : 3]
|
||||
tokens["surface-warning-weak"] = (noInk && isDark ? warningl : warning)[isDark ? 3 : 2]
|
||||
tokens["surface-warning-strong"] = (noInk && isDark ? warningl : warning)[9]
|
||||
tokens["surface-critical-base"] = error[isDark ? 4 : 3]
|
||||
tokens["surface-critical-weak"] = error[isDark ? 3 : 2]
|
||||
tokens["surface-critical-strong"] = error[9]
|
||||
tokens["surface-info-base"] = (noInk && isDark ? infol : info)[isDark ? 4 : 3]
|
||||
tokens["surface-info-weak"] = (noInk && isDark ? infol : info)[isDark ? 3 : 2]
|
||||
tokens["surface-info-strong"] = (noInk && isDark ? infol : info)[9]
|
||||
|
||||
tokens["surface-diff-unchanged-base"] = isDark ? neutral[0] : "#ffffff00"
|
||||
tokens["surface-diff-skip-base"] = isDark ? neutralAlpha[0] : neutral[1]
|
||||
tokens["surface-diff-hidden-base"] = interactive[isDark ? 1 : 2]
|
||||
tokens["surface-diff-hidden-weak"] = interactive[isDark ? 0 : 1]
|
||||
tokens["surface-diff-hidden-weaker"] = interactive[isDark ? 2 : 0]
|
||||
tokens["surface-diff-hidden-strong"] = interactive[4]
|
||||
tokens["surface-diff-hidden-stronger"] = interactive[isDark ? 10 : 8]
|
||||
tokens["surface-diff-hidden-base"] = diffHiddenSurface.base
|
||||
tokens["surface-diff-hidden-weak"] = diffHiddenSurface.weak
|
||||
tokens["surface-diff-hidden-weaker"] = diffHiddenSurface.weaker
|
||||
tokens["surface-diff-hidden-strong"] = diffHiddenSurface.strong
|
||||
tokens["surface-diff-hidden-stronger"] = diffHiddenSurface.stronger
|
||||
tokens["surface-diff-add-base"] = diffAdd[2]
|
||||
tokens["surface-diff-add-weak"] = diffAdd[isDark ? 3 : 1]
|
||||
tokens["surface-diff-add-weaker"] = diffAdd[isDark ? 2 : 0]
|
||||
@@ -96,10 +200,36 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
tokens["input-focus"] = interactive[0]
|
||||
tokens["input-disabled"] = neutral[3]
|
||||
|
||||
tokens["text-base"] = neutral[10]
|
||||
tokens["text-weak"] = neutral[8]
|
||||
tokens["text-weaker"] = neutral[7]
|
||||
tokens["text-strong"] = neutral[11]
|
||||
tokens["text-base"] = hasInk ? ink : noInk ? (isDark ? neutralAlpha[10] : neutral[10]) : neutral[10]
|
||||
tokens["text-weak"] = hasInk
|
||||
? shift(ink, { l: isDark ? -0.18 : 0.16, c: 0.88 })
|
||||
: noInk
|
||||
? isDark
|
||||
? neutralAlpha[8]
|
||||
: neutral[8]
|
||||
: neutral[8]
|
||||
tokens["text-weaker"] = hasInk
|
||||
? shift(ink, { l: isDark ? -0.3 : 0.26, c: isDark ? 0.74 : 0.68 })
|
||||
: noInk
|
||||
? isDark
|
||||
? neutralAlpha[7]
|
||||
: neutral[7]
|
||||
: neutral[7]
|
||||
tokens["text-strong"] = hasInk
|
||||
? isDark && colors.compact
|
||||
? blend("#ffffff", ink, 0.82)
|
||||
: shift(ink, { l: isDark ? 0.06 : -0.09, c: 1 })
|
||||
: noInk
|
||||
? isDark
|
||||
? neutralAlpha[11]
|
||||
: neutral[11]
|
||||
: neutral[11]
|
||||
if (noInk && isDark) {
|
||||
tokens["text-base"] = withAlpha("#ffffff", 0.618) as ColorValue
|
||||
tokens["text-weak"] = withAlpha("#ffffff", 0.422) as ColorValue
|
||||
tokens["text-weaker"] = withAlpha("#ffffff", 0.284) as ColorValue
|
||||
tokens["text-strong"] = withAlpha("#ffffff", 0.936) as ColorValue
|
||||
}
|
||||
tokens["text-invert-base"] = isDark ? neutral[10] : neutral[1]
|
||||
tokens["text-invert-weak"] = isDark ? neutral[8] : neutral[2]
|
||||
tokens["text-invert-weaker"] = isDark ? neutral[7] : neutral[3]
|
||||
@@ -128,79 +258,166 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
tokens["text-on-brand-weaker"] = neutralAlpha[7]
|
||||
tokens["text-on-brand-strong"] = neutralAlpha[11]
|
||||
|
||||
tokens["button-secondary-base"] = isDark ? neutral[2] : neutral[0]
|
||||
tokens["button-secondary-hover"] = isDark ? neutral[3] : neutral[1]
|
||||
tokens["button-primary-base"] = neutral[11]
|
||||
tokens["button-secondary-base"] = noInk ? (isDark ? neutral[1] : neutral[0]) : isDark ? neutral[2] : neutral[0]
|
||||
tokens["button-secondary-hover"] = noInk ? (isDark ? neutral[1] : neutral[1]) : isDark ? neutral[3] : neutral[1]
|
||||
tokens["button-ghost-hover"] = neutralAlpha[1]
|
||||
tokens["button-ghost-hover2"] = neutralAlpha[2]
|
||||
|
||||
tokens["border-base"] = neutralAlpha[6]
|
||||
tokens["border-hover"] = neutralAlpha[7]
|
||||
tokens["border-active"] = neutralAlpha[8]
|
||||
tokens["border-selected"] = withAlpha(interactive[8], isDark ? 0.9 : 0.99) as ColorValue
|
||||
tokens["border-disabled"] = neutralAlpha[7]
|
||||
tokens["border-focus"] = neutralAlpha[8]
|
||||
tokens["border-weak-base"] = neutralAlpha[isDark ? 5 : 4]
|
||||
tokens["border-strong-base"] = neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-strong-hover"] = neutralAlpha[7]
|
||||
tokens["border-strong-active"] = neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-strong-selected"] = withAlpha(interactive[5], 0.6) as ColorValue
|
||||
tokens["border-strong-disabled"] = neutralAlpha[5]
|
||||
tokens["border-strong-focus"] = neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-weak-hover"] = neutralAlpha[isDark ? 6 : 5]
|
||||
tokens["border-weak-active"] = neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-weak-selected"] = withAlpha(interactive[4], isDark ? 0.6 : 0.5) as ColorValue
|
||||
tokens["border-weak-disabled"] = neutralAlpha[5]
|
||||
tokens["border-weak-focus"] = neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-weaker-base"] = neutralAlpha[2]
|
||||
if (noInk) {
|
||||
const tone = (alpha: number) => alphaTone((isDark ? "#ffffff" : "#000000") as HexColor, alpha)
|
||||
if (isDark) {
|
||||
tokens["surface-base"] = tone(0.031)
|
||||
tokens["surface-base-hover"] = tone(0.039)
|
||||
tokens["surface-base-active"] = tone(0.059)
|
||||
tokens["surface-raised-base"] = tone(0.059)
|
||||
tokens["surface-raised-base-hover"] = tone(0.078)
|
||||
tokens["surface-raised-base-active"] = tone(0.102)
|
||||
tokens["surface-raised-strong"] = tone(0.078)
|
||||
tokens["surface-raised-strong-hover"] = tone(0.129)
|
||||
tokens["surface-raised-stronger"] = tone(0.129)
|
||||
tokens["surface-raised-stronger-hover"] = tone(0.169)
|
||||
tokens["surface-weak"] = tone(0.078)
|
||||
tokens["surface-weaker"] = tone(0.102)
|
||||
tokens["surface-strong"] = tone(0.169)
|
||||
tokens["surface-raised-stronger-non-alpha"] = neutral[1]
|
||||
tokens["surface-inset-base"] = withAlpha("#000000", 0.5) as ColorValue
|
||||
tokens["surface-inset-base-hover"] = tokens["surface-inset-base"]
|
||||
tokens["surface-inset-strong"] = withAlpha("#000000", 0.8) as ColorValue
|
||||
tokens["surface-inset-strong-hover"] = tokens["surface-inset-strong"]
|
||||
tokens["button-secondary-hover"] = tone(0.039)
|
||||
tokens["button-ghost-hover"] = tone(0.031)
|
||||
tokens["button-ghost-hover2"] = tone(0.059)
|
||||
tokens["input-base"] = neutral[1]
|
||||
tokens["input-hover"] = neutral[1]
|
||||
tokens["input-selected"] = interactive[1]
|
||||
tokens["surface-diff-skip-base"] = "#00000000"
|
||||
}
|
||||
|
||||
tokens["border-interactive-base"] = interactive[6]
|
||||
tokens["border-interactive-hover"] = interactive[7]
|
||||
tokens["border-interactive-active"] = interactive[8]
|
||||
tokens["border-interactive-selected"] = interactive[8]
|
||||
if (!isDark) {
|
||||
tokens["surface-base"] = tone(0.031)
|
||||
tokens["surface-base-hover"] = tone(0.059)
|
||||
tokens["surface-base-active"] = tone(0.051)
|
||||
tokens["surface-raised-base"] = tone(0.031)
|
||||
tokens["surface-raised-base-hover"] = tone(0.051)
|
||||
tokens["surface-raised-base-active"] = tone(0.09)
|
||||
tokens["surface-raised-strong"] = neutral[0]
|
||||
tokens["surface-raised-strong-hover"] = "#ffffff"
|
||||
tokens["surface-raised-stronger"] = "#ffffff"
|
||||
tokens["surface-raised-stronger-hover"] = "#ffffff"
|
||||
tokens["surface-weak"] = tone(0.051)
|
||||
tokens["surface-weaker"] = tone(0.071)
|
||||
tokens["surface-strong"] = "#ffffff"
|
||||
tokens["surface-raised-stronger-non-alpha"] = "#ffffff"
|
||||
tokens["surface-inset-strong"] = tone(0.09)
|
||||
tokens["surface-inset-strong-hover"] = tokens["surface-inset-strong"]
|
||||
tokens["button-secondary-hover"] = blend("#ffffff", background, 0.04)
|
||||
tokens["button-ghost-hover"] = tone(0.031)
|
||||
tokens["button-ghost-hover2"] = tone(0.051)
|
||||
tokens["input-base"] = neutral[0]
|
||||
tokens["input-hover"] = neutral[1]
|
||||
}
|
||||
|
||||
tokens["surface-base-interactive-active"] = withAlpha(colors.interactive, isDark ? 0.125 : 0.09) as ColorValue
|
||||
}
|
||||
|
||||
tokens["border-base"] = hasInk ? borderTone(0.22, 0.16) : neutralAlpha[6]
|
||||
tokens["border-hover"] = hasInk ? borderTone(0.28, 0.2) : neutralAlpha[7]
|
||||
tokens["border-active"] = hasInk ? borderTone(0.34, 0.24) : neutralAlpha[8]
|
||||
tokens["border-selected"] = noInk
|
||||
? isDark
|
||||
? interactive[10]
|
||||
: (withAlpha(colors.interactive, 0.99) as ColorValue)
|
||||
: (withAlpha(interactive[8], isDark ? 0.9 : 0.99) as ColorValue)
|
||||
tokens["border-disabled"] = hasInk ? borderTone(0.18, 0.12) : neutralAlpha[7]
|
||||
tokens["border-focus"] = hasInk ? borderTone(0.34, 0.24) : neutralAlpha[8]
|
||||
tokens["border-weak-base"] = hasInk
|
||||
? borderTone(0.1, 0.08)
|
||||
: noInk
|
||||
? isDark
|
||||
? neutral[3]
|
||||
: blend(neutral[4], neutral[5], 0.5)
|
||||
: neutralAlpha[isDark ? 5 : 4]
|
||||
tokens["border-strong-base"] = hasInk ? borderTone(0.34, 0.24) : neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-strong-hover"] = hasInk ? borderTone(0.4, 0.28) : neutralAlpha[7]
|
||||
tokens["border-strong-active"] = hasInk ? borderTone(0.46, 0.32) : neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-strong-selected"] = noInk
|
||||
? (withAlpha(colors.interactive, isDark ? 0.62 : 0.31) as ColorValue)
|
||||
: (withAlpha(interactive[5], 0.6) as ColorValue)
|
||||
tokens["border-strong-disabled"] = hasInk ? borderTone(0.14, 0.1) : neutralAlpha[5]
|
||||
tokens["border-strong-focus"] = hasInk ? borderTone(0.46, 0.32) : neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-weak-hover"] = hasInk ? borderTone(0.16, 0.12) : neutralAlpha[isDark ? 6 : 5]
|
||||
tokens["border-weak-active"] = hasInk ? borderTone(0.22, 0.16) : neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-weak-selected"] = noInk
|
||||
? (withAlpha(colors.interactive, isDark ? 0.62 : 0.24) as ColorValue)
|
||||
: (withAlpha(interactive[4], isDark ? 0.6 : 0.5) as ColorValue)
|
||||
tokens["border-weak-disabled"] = hasInk ? borderTone(0.08, 0.06) : neutralAlpha[5]
|
||||
tokens["border-weak-focus"] = hasInk ? borderTone(0.22, 0.16) : neutralAlpha[isDark ? 7 : 6]
|
||||
tokens["border-weaker-base"] = hasInk
|
||||
? borderTone(0.06, 0.04)
|
||||
: noInk
|
||||
? isDark
|
||||
? blend(neutral[1], neutral[2], 0.5)
|
||||
: blend(neutral[2], neutral[3], 0.5)
|
||||
: neutralAlpha[2]
|
||||
|
||||
if (noInk) {
|
||||
const line = (l: number, d: number) => alphaTone((isDark ? "#ffffff" : "#000000") as HexColor, isDark ? d : l)
|
||||
tokens["border-base"] = line(0.162, 0.195)
|
||||
tokens["border-hover"] = line(0.236, 0.284)
|
||||
tokens["border-active"] = line(0.46, 0.418)
|
||||
tokens["border-disabled"] = tokens["border-hover"]
|
||||
tokens["border-focus"] = tokens["border-active"]
|
||||
}
|
||||
|
||||
tokens["border-interactive-base"] = (noInk && isDark ? interl : interactive)[6]
|
||||
tokens["border-interactive-hover"] = (noInk && isDark ? interl : interactive)[7]
|
||||
tokens["border-interactive-active"] = (noInk && isDark ? interl : interactive)[8]
|
||||
tokens["border-interactive-selected"] = (noInk && isDark ? interl : interactive)[8]
|
||||
tokens["border-interactive-disabled"] = neutral[7]
|
||||
tokens["border-interactive-focus"] = interactive[8]
|
||||
tokens["border-interactive-focus"] = (noInk && isDark ? interl : interactive)[8]
|
||||
|
||||
tokens["border-success-base"] = success[5]
|
||||
tokens["border-success-hover"] = success[6]
|
||||
tokens["border-success-selected"] = success[8]
|
||||
tokens["border-warning-base"] = warning[5]
|
||||
tokens["border-warning-hover"] = warning[6]
|
||||
tokens["border-warning-selected"] = warning[8]
|
||||
tokens["border-success-base"] = (noInk && isDark ? successl : success)[5]
|
||||
tokens["border-success-hover"] = (noInk && isDark ? successl : success)[6]
|
||||
tokens["border-success-selected"] = (noInk && isDark ? successl : success)[8]
|
||||
tokens["border-warning-base"] = (noInk && isDark ? warningl : warning)[5]
|
||||
tokens["border-warning-hover"] = (noInk && isDark ? warningl : warning)[6]
|
||||
tokens["border-warning-selected"] = (noInk && isDark ? warningl : warning)[8]
|
||||
tokens["border-critical-base"] = error[isDark ? 4 : 5]
|
||||
tokens["border-critical-hover"] = error[6]
|
||||
tokens["border-critical-selected"] = error[8]
|
||||
tokens["border-info-base"] = info[5]
|
||||
tokens["border-info-hover"] = info[6]
|
||||
tokens["border-info-selected"] = info[8]
|
||||
tokens["border-info-base"] = (noInk && isDark ? infol : info)[5]
|
||||
tokens["border-info-hover"] = (noInk && isDark ? infol : info)[6]
|
||||
tokens["border-info-selected"] = (noInk && isDark ? infol : info)[8]
|
||||
tokens["border-color"] = "#ffffff"
|
||||
|
||||
tokens["icon-base"] = neutral[8]
|
||||
tokens["icon-hover"] = neutral[isDark ? 9 : 10]
|
||||
tokens["icon-active"] = neutral[isDark ? 10 : 11]
|
||||
tokens["icon-selected"] = neutral[11]
|
||||
tokens["icon-base"] = hasInk && !isDark ? tokens["text-weak"] : neutral[isDark ? 9 : 8]
|
||||
tokens["icon-hover"] = hasInk && !isDark ? tokens["text-base"] : neutral[10]
|
||||
tokens["icon-active"] = hasInk && !isDark ? tokens["text-strong"] : neutral[11]
|
||||
tokens["icon-selected"] = hasInk && !isDark ? tokens["text-strong"] : neutral[11]
|
||||
tokens["icon-disabled"] = neutral[isDark ? 6 : 7]
|
||||
tokens["icon-focus"] = neutral[11]
|
||||
tokens["icon-focus"] = hasInk && !isDark ? tokens["text-strong"] : neutral[11]
|
||||
tokens["icon-invert-base"] = isDark ? neutral[0] : "#ffffff"
|
||||
tokens["icon-weak-base"] = neutral[isDark ? 5 : 6]
|
||||
tokens["icon-weak-hover"] = neutral[6]
|
||||
tokens["icon-weak-active"] = neutral[7]
|
||||
tokens["icon-weak-selected"] = neutral[8]
|
||||
tokens["icon-weak-disabled"] = neutral[isDark ? 3 : 5]
|
||||
tokens["icon-weak-hover"] = noInk && isDark ? blend(neutral[11], neutral[10], 0.74) : neutral[isDark ? 11 : 7]
|
||||
tokens["icon-weak-active"] = noInk && isDark ? blend(neutral[11], neutral[10], 0.52) : neutral[8]
|
||||
tokens["icon-weak-selected"] = neutral[isDark ? 8 : 9]
|
||||
tokens["icon-weak-disabled"] = noInk && isDark ? neutral[11] : neutral[isDark ? 3 : 5]
|
||||
tokens["icon-weak-focus"] = neutral[8]
|
||||
tokens["icon-strong-base"] = neutral[11]
|
||||
tokens["icon-strong-hover"] = isDark ? "#f6f3f3" : "#151313"
|
||||
tokens["icon-strong-active"] = isDark ? "#fcfcfc" : "#020202"
|
||||
tokens["icon-strong-selected"] = isDark ? "#fdfcfc" : "#020202"
|
||||
tokens["icon-strong-disabled"] = neutral[7]
|
||||
tokens["icon-strong-disabled"] = noInk && isDark ? neutral[6] : neutral[7]
|
||||
tokens["icon-strong-focus"] = isDark ? "#fdfcfc" : "#020202"
|
||||
tokens["icon-brand-base"] = isDark ? "#ffffff" : neutral[11]
|
||||
tokens["icon-interactive-base"] = interactive[8]
|
||||
tokens["icon-success-base"] = success[isDark ? 6 : 6]
|
||||
tokens["icon-success-hover"] = success[7]
|
||||
tokens["icon-success-base"] = success[isDark ? 8 : 6]
|
||||
tokens["icon-success-hover"] = success[isDark ? 9 : 7]
|
||||
tokens["icon-success-active"] = success[10]
|
||||
tokens["icon-warning-base"] = warning[6]
|
||||
tokens["icon-warning-hover"] = warning[7]
|
||||
tokens["icon-warning-active"] = warning[10]
|
||||
tokens["icon-warning-base"] = amber[isDark ? 8 : 6]
|
||||
tokens["icon-warning-hover"] = amber[7]
|
||||
tokens["icon-warning-active"] = amber[10]
|
||||
tokens["icon-critical-base"] = error[isDark ? 8 : 9]
|
||||
tokens["icon-critical-hover"] = error[10]
|
||||
tokens["icon-critical-active"] = error[11]
|
||||
@@ -213,16 +430,16 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
tokens["icon-on-interactive-base"] = isDark ? neutral[11] : neutral[0]
|
||||
|
||||
tokens["icon-agent-plan-base"] = info[8]
|
||||
tokens["icon-agent-docs-base"] = warning[8]
|
||||
tokens["icon-agent-ask-base"] = interactive[8]
|
||||
tokens["icon-agent-docs-base"] = amber[8]
|
||||
tokens["icon-agent-ask-base"] = blue[8]
|
||||
tokens["icon-agent-build-base"] = interactive[isDark ? 10 : 8]
|
||||
|
||||
tokens["icon-on-success-base"] = withAlpha(success[8], 0.9) as ColorValue
|
||||
tokens["icon-on-success-hover"] = withAlpha(success[9], 0.9) as ColorValue
|
||||
tokens["icon-on-success-selected"] = withAlpha(success[10], 0.9) as ColorValue
|
||||
tokens["icon-on-warning-base"] = withAlpha(warning[8], 0.9) as ColorValue
|
||||
tokens["icon-on-warning-hover"] = withAlpha(warning[9], 0.9) as ColorValue
|
||||
tokens["icon-on-warning-selected"] = withAlpha(warning[10], 0.9) as ColorValue
|
||||
tokens["icon-on-warning-base"] = withAlpha(amber[8], 0.9) as ColorValue
|
||||
tokens["icon-on-warning-hover"] = withAlpha(amber[9], 0.9) as ColorValue
|
||||
tokens["icon-on-warning-selected"] = withAlpha(amber[10], 0.9) as ColorValue
|
||||
tokens["icon-on-critical-base"] = withAlpha(error[8], 0.9) as ColorValue
|
||||
tokens["icon-on-critical-hover"] = withAlpha(error[9], 0.9) as ColorValue
|
||||
tokens["icon-on-critical-selected"] = withAlpha(error[10], 0.9) as ColorValue
|
||||
@@ -235,42 +452,120 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
tokens["icon-diff-add-active"] = diffAdd[isDark ? 10 : 11]
|
||||
tokens["icon-diff-delete-base"] = diffDelete[isDark ? 8 : 9]
|
||||
tokens["icon-diff-delete-hover"] = diffDelete[isDark ? 9 : 10]
|
||||
tokens["icon-diff-modified-base"] = isDark ? "#ffba92" : "#FF8C00"
|
||||
tokens["icon-diff-modified-base"] = modified()
|
||||
|
||||
tokens["syntax-comment"] = "var(--text-weak)"
|
||||
tokens["syntax-regexp"] = "var(--text-base)"
|
||||
tokens["syntax-string"] = isDark ? "#00ceb9" : "#006656"
|
||||
tokens["syntax-keyword"] = "var(--text-weak)"
|
||||
tokens["syntax-primitive"] = isDark ? "#ffba92" : "#fb4804"
|
||||
tokens["syntax-operator"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-variable"] = "var(--text-strong)"
|
||||
tokens["syntax-property"] = isDark ? "#ff9ae2" : "#ed6dc8"
|
||||
tokens["syntax-type"] = isDark ? "#ecf58c" : "#596600"
|
||||
tokens["syntax-constant"] = isDark ? "#93e9f6" : "#007b80"
|
||||
tokens["syntax-punctuation"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-object"] = "var(--text-strong)"
|
||||
tokens["syntax-success"] = success[9]
|
||||
tokens["syntax-warning"] = warning[9]
|
||||
tokens["syntax-critical"] = error[isDark ? 9 : 9]
|
||||
tokens["syntax-info"] = isDark ? "#93e9f6" : "#0092a8"
|
||||
tokens["syntax-diff-add"] = diffAdd[10]
|
||||
tokens["syntax-diff-delete"] = diffDelete[10]
|
||||
tokens["syntax-diff-unknown"] = "#ff0000"
|
||||
if (colors.compact) {
|
||||
if (!hasInk) {
|
||||
tokens["syntax-comment"] = "var(--text-weak)"
|
||||
tokens["syntax-regexp"] = "var(--text-base)"
|
||||
tokens["syntax-string"] = isDark ? "#00ceb9" : "#006656"
|
||||
tokens["syntax-keyword"] = "var(--text-weak)"
|
||||
tokens["syntax-primitive"] = isDark ? "#ffba92" : "#fb4804"
|
||||
tokens["syntax-operator"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-variable"] = "var(--text-strong)"
|
||||
tokens["syntax-property"] = isDark ? "#ff9ae2" : "#ed6dc8"
|
||||
tokens["syntax-type"] = isDark ? "#ecf58c" : "#596600"
|
||||
tokens["syntax-constant"] = isDark ? "#93e9f6" : "#007b80"
|
||||
tokens["syntax-punctuation"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-object"] = "var(--text-strong)"
|
||||
tokens["syntax-success"] = success[9]
|
||||
tokens["syntax-warning"] = amber[9]
|
||||
tokens["syntax-critical"] = error[9]
|
||||
tokens["syntax-info"] = isDark ? "#93e9f6" : "#0092a8"
|
||||
tokens["syntax-diff-add"] = diffAdd[10]
|
||||
tokens["syntax-diff-delete"] = diffDelete[10]
|
||||
tokens["syntax-diff-unknown"] = "#ff0000"
|
||||
|
||||
tokens["markdown-heading"] = isDark ? "#9d7cd8" : "#d68c27"
|
||||
tokens["markdown-text"] = isDark ? "#eeeeee" : "#1a1a1a"
|
||||
tokens["markdown-link"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-link-text"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-code"] = isDark ? "#7fd88f" : "#3d9a57"
|
||||
tokens["markdown-block-quote"] = isDark ? "#e5c07b" : "#b0851f"
|
||||
tokens["markdown-emph"] = isDark ? "#e5c07b" : "#b0851f"
|
||||
tokens["markdown-strong"] = isDark ? "#f5a742" : "#d68c27"
|
||||
tokens["markdown-horizontal-rule"] = isDark ? "#808080" : "#8a8a8a"
|
||||
tokens["markdown-list-item"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-list-enumeration"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-image"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-image-text"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-code-block"] = isDark ? "#eeeeee" : "#1a1a1a"
|
||||
tokens["markdown-heading"] = isDark ? "#9d7cd8" : "#d68c27"
|
||||
tokens["markdown-text"] = isDark ? "#eeeeee" : "#1a1a1a"
|
||||
tokens["markdown-link"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-link-text"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-code"] = isDark ? "#7fd88f" : "#3d9a57"
|
||||
tokens["markdown-block-quote"] = isDark ? "#e5c07b" : "#b0851f"
|
||||
tokens["markdown-emph"] = isDark ? "#e5c07b" : "#b0851f"
|
||||
tokens["markdown-strong"] = isDark ? "#f5a742" : "#d68c27"
|
||||
tokens["markdown-horizontal-rule"] = isDark ? "#808080" : "#8a8a8a"
|
||||
tokens["markdown-list-item"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-list-enumeration"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-image"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-image-text"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-code-block"] = isDark ? "#eeeeee" : "#1a1a1a"
|
||||
}
|
||||
|
||||
if (hasInk) {
|
||||
tokens["syntax-comment"] = "var(--text-weak)"
|
||||
tokens["syntax-regexp"] = "var(--text-base)"
|
||||
tokens["syntax-string"] = content(colors.success, success)
|
||||
tokens["syntax-keyword"] = "var(--text-weak)"
|
||||
tokens["syntax-primitive"] = content(colors.accent, accent)
|
||||
tokens["syntax-operator"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-variable"] = "var(--text-strong)"
|
||||
tokens["syntax-property"] = content(colors.primary, primary)
|
||||
tokens["syntax-type"] = content(colors.warning, warning)
|
||||
tokens["syntax-constant"] = content(colors.info, info)
|
||||
tokens["syntax-punctuation"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-object"] = "var(--text-strong)"
|
||||
tokens["syntax-success"] = success[9]
|
||||
tokens["syntax-warning"] = amber[9]
|
||||
tokens["syntax-critical"] = error[9]
|
||||
tokens["syntax-info"] = content(colors.info, info)
|
||||
tokens["syntax-diff-add"] = diffAdd[10]
|
||||
tokens["syntax-diff-delete"] = diffDelete[10]
|
||||
tokens["syntax-diff-unknown"] = "#ff0000"
|
||||
|
||||
tokens["markdown-heading"] = content(colors.primary, primary)
|
||||
tokens["markdown-text"] = tokens["text-base"]
|
||||
tokens["markdown-link"] = content(colors.interactive, interactive)
|
||||
tokens["markdown-link-text"] = content(colors.info, info)
|
||||
tokens["markdown-code"] = content(colors.success, success)
|
||||
tokens["markdown-block-quote"] = content(colors.warning, warning)
|
||||
tokens["markdown-emph"] = content(colors.warning, warning)
|
||||
tokens["markdown-strong"] = content(colors.accent, accent)
|
||||
tokens["markdown-horizontal-rule"] = tokens["border-base"]
|
||||
tokens["markdown-list-item"] = content(colors.interactive, interactive)
|
||||
tokens["markdown-list-enumeration"] = content(colors.info, info)
|
||||
tokens["markdown-image"] = content(colors.interactive, interactive)
|
||||
tokens["markdown-image-text"] = content(colors.info, info)
|
||||
tokens["markdown-code-block"] = tokens["text-base"]
|
||||
}
|
||||
}
|
||||
|
||||
if (!colors.compact) {
|
||||
tokens["syntax-comment"] = "var(--text-weak)"
|
||||
tokens["syntax-regexp"] = "var(--text-base)"
|
||||
tokens["syntax-string"] = isDark ? "#00ceb9" : "#006656"
|
||||
tokens["syntax-keyword"] = "var(--text-weak)"
|
||||
tokens["syntax-primitive"] = isDark ? "#ffba92" : "#fb4804"
|
||||
tokens["syntax-operator"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-variable"] = "var(--text-strong)"
|
||||
tokens["syntax-property"] = isDark ? "#ff9ae2" : "#ed6dc8"
|
||||
tokens["syntax-type"] = isDark ? "#ecf58c" : "#596600"
|
||||
tokens["syntax-constant"] = isDark ? "#93e9f6" : "#007b80"
|
||||
tokens["syntax-punctuation"] = isDark ? "var(--text-weak)" : "var(--text-base)"
|
||||
tokens["syntax-object"] = "var(--text-strong)"
|
||||
tokens["syntax-success"] = success[9]
|
||||
tokens["syntax-warning"] = amber[9]
|
||||
tokens["syntax-critical"] = error[9]
|
||||
tokens["syntax-info"] = isDark ? "#93e9f6" : "#0092a8"
|
||||
tokens["syntax-diff-add"] = diffAdd[10]
|
||||
tokens["syntax-diff-delete"] = diffDelete[10]
|
||||
tokens["syntax-diff-unknown"] = "#ff0000"
|
||||
|
||||
tokens["markdown-heading"] = isDark ? "#9d7cd8" : "#d68c27"
|
||||
tokens["markdown-text"] = isDark ? "#eeeeee" : "#1a1a1a"
|
||||
tokens["markdown-link"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-link-text"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-code"] = isDark ? "#7fd88f" : "#3d9a57"
|
||||
tokens["markdown-block-quote"] = isDark ? "#e5c07b" : "#b0851f"
|
||||
tokens["markdown-emph"] = isDark ? "#e5c07b" : "#b0851f"
|
||||
tokens["markdown-strong"] = isDark ? "#f5a742" : "#d68c27"
|
||||
tokens["markdown-horizontal-rule"] = isDark ? "#808080" : "#8a8a8a"
|
||||
tokens["markdown-list-item"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-list-enumeration"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-image"] = isDark ? "#fab283" : "#3b7dd8"
|
||||
tokens["markdown-image-text"] = isDark ? "#56b6c2" : "#318795"
|
||||
tokens["markdown-code-block"] = isDark ? "#eeeeee" : "#1a1a1a"
|
||||
}
|
||||
|
||||
tokens["avatar-background-pink"] = isDark ? "#501b3f" : "#feeef8"
|
||||
tokens["avatar-background-mint"] = isDark ? "#033a34" : "#e1fbf4"
|
||||
@@ -289,13 +584,101 @@ export function resolveThemeVariant(variant: ThemeVariant, isDark: boolean): Res
|
||||
tokens[key] = value
|
||||
}
|
||||
|
||||
if (hasInk && "text-weak" in overrides && !("text-weaker" in overrides)) {
|
||||
const weak = tokens["text-weak"]
|
||||
if (weak.startsWith("#")) {
|
||||
tokens["text-weaker"] = shift(weak as HexColor, { l: isDark ? -0.12 : 0.12, c: 0.75 })
|
||||
} else {
|
||||
tokens["text-weaker"] = weak
|
||||
}
|
||||
}
|
||||
|
||||
if (colors.compact && hasInk) {
|
||||
if (!("markdown-text" in overrides)) {
|
||||
tokens["markdown-text"] = tokens["text-base"]
|
||||
}
|
||||
if (!("markdown-code-block" in overrides)) {
|
||||
tokens["markdown-code-block"] = tokens["text-base"]
|
||||
}
|
||||
}
|
||||
|
||||
if (!("text-stronger" in overrides)) {
|
||||
tokens["text-stronger"] = tokens["text-strong"]
|
||||
}
|
||||
|
||||
return tokens
|
||||
}
|
||||
|
||||
interface ThemeColors {
|
||||
compact: boolean
|
||||
neutral: HexColor
|
||||
ink?: HexColor
|
||||
primary: HexColor
|
||||
accent: HexColor
|
||||
success: HexColor
|
||||
warning: HexColor
|
||||
error: HexColor
|
||||
info: HexColor
|
||||
interactive: HexColor
|
||||
diffAdd?: HexColor
|
||||
diffDelete?: HexColor
|
||||
}
|
||||
|
||||
function getColors(variant: ThemeVariant): ThemeColors {
|
||||
const input = variant as { palette?: unknown; seeds?: unknown }
|
||||
if (input.palette && input.seeds) {
|
||||
throw new Error("Theme variant cannot define both `palette` and `seeds`")
|
||||
}
|
||||
|
||||
if (variant.palette) {
|
||||
return {
|
||||
compact: true,
|
||||
neutral: variant.palette.neutral,
|
||||
ink: variant.palette.ink,
|
||||
primary: variant.palette.primary,
|
||||
accent: variant.palette.accent ?? variant.palette.info,
|
||||
success: variant.palette.success,
|
||||
warning: variant.palette.warning,
|
||||
error: variant.palette.error,
|
||||
info: variant.palette.info,
|
||||
interactive: variant.palette.interactive ?? variant.palette.primary,
|
||||
diffAdd: variant.palette.diffAdd,
|
||||
diffDelete: variant.palette.diffDelete,
|
||||
}
|
||||
}
|
||||
|
||||
if (variant.seeds) {
|
||||
return {
|
||||
compact: false,
|
||||
neutral: variant.seeds.neutral,
|
||||
ink: undefined,
|
||||
primary: variant.seeds.primary,
|
||||
accent: variant.seeds.info,
|
||||
success: variant.seeds.success,
|
||||
warning: variant.seeds.warning,
|
||||
error: variant.seeds.error,
|
||||
info: variant.seeds.info,
|
||||
interactive: variant.seeds.interactive,
|
||||
diffAdd: variant.seeds.diffAdd,
|
||||
diffDelete: variant.seeds.diffDelete,
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Theme variant requires `palette` or `seeds`")
|
||||
}
|
||||
|
||||
function generateNeutralOverlayScale(neutralScale: HexColor[], isDark: boolean): ColorValue[] {
|
||||
const alphas = isDark
|
||||
? [0, 0.034, 0.063, 0.084, 0.109, 0.138, 0.181, 0.266, 0.404, 0.468, 0.603, 0.928]
|
||||
: [0.014, 0.034, 0.055, 0.075, 0.096, 0.118, 0.151, 0.232, 0.453, 0.492, 0.574, 0.915]
|
||||
const color = (isDark ? "#ffffff" : "#000000") as HexColor
|
||||
return alphas.map((alpha) => withAlpha(color, alpha) as ColorValue)
|
||||
}
|
||||
|
||||
function generateNeutralAlphaScale(neutralScale: HexColor[], isDark: boolean): HexColor[] {
|
||||
const alphas = isDark
|
||||
? [0.02, 0.04, 0.08, 0.12, 0.16, 0.2, 0.26, 0.36, 0.44, 0.52, 0.72, 0.94]
|
||||
: [0.01, 0.03, 0.06, 0.09, 0.12, 0.15, 0.2, 0.27, 0.46, 0.61, 0.5, 0.87]
|
||||
? [0.024, 0.048, 0.088, 0.128, 0.17, 0.215, 0.275, 0.38, 0.46, 0.54, 0.74, 0.95]
|
||||
: [0.014, 0.034, 0.066, 0.098, 0.128, 0.158, 0.208, 0.282, 0.47, 0.625, 0.515, 0.88]
|
||||
|
||||
return neutralScale.map((hex, i) => {
|
||||
const baseOklch = hexToOklch(hex)
|
||||
@@ -307,6 +690,11 @@ function generateNeutralAlphaScale(neutralScale: HexColor[], isDark: boolean): H
|
||||
})
|
||||
}
|
||||
|
||||
function getHex(value: ColorValue | undefined): HexColor | undefined {
|
||||
if (!value?.startsWith("#")) return
|
||||
return value as HexColor
|
||||
}
|
||||
|
||||
export function resolveTheme(theme: DesktopTheme): { light: ResolvedTheme; dark: ResolvedTheme } {
|
||||
return {
|
||||
light: resolveThemeVariant(theme.light, false),
|
||||
|
||||
@@ -3,129 +3,37 @@
|
||||
"name": "Aura",
|
||||
"id": "aura",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#f5f0ff",
|
||||
"ink": "#2d2640",
|
||||
"primary": "#a277ff",
|
||||
"accent": "#d94f4f",
|
||||
"success": "#40bf7a",
|
||||
"warning": "#d9a24a",
|
||||
"error": "#d94f4f",
|
||||
"info": "#5bb8d9",
|
||||
"interactive": "#a277ff",
|
||||
"diffAdd": "#b3e6cc",
|
||||
"diffDelete": "#f5b3b3"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f5f0ff",
|
||||
"background-weak": "#efe8fc",
|
||||
"background-strong": "#faf7ff",
|
||||
"background-stronger": "#fdfcff",
|
||||
"border-weak-base": "#e0d6f2",
|
||||
"border-weak-hover": "#d5c9eb",
|
||||
"border-weak-active": "#cbbee3",
|
||||
"border-weak-selected": "#c0b3dc",
|
||||
"border-weak-disabled": "#f9f6ff",
|
||||
"border-weak-focus": "#c5b8df",
|
||||
"border-base": "#b5a6d4",
|
||||
"border-hover": "#aa99cc",
|
||||
"border-active": "#9f8dc4",
|
||||
"border-selected": "#9480bc",
|
||||
"border-disabled": "#ede7f9",
|
||||
"border-focus": "#a593c8",
|
||||
"border-strong-base": "#8068a8",
|
||||
"border-strong-hover": "#735a9c",
|
||||
"border-strong-active": "#664d90",
|
||||
"border-strong-selected": "#5a4184",
|
||||
"border-strong-disabled": "#d4c8ed",
|
||||
"border-strong-focus": "#6d5396",
|
||||
"surface-diff-add-base": "#e8f5ed",
|
||||
"surface-diff-delete-base": "#fae8e8",
|
||||
"surface-diff-hidden-base": "#e8e4f5",
|
||||
"text-base": "#2d2640",
|
||||
"text-weak": "#5c5270",
|
||||
"text-strong": "#15101f",
|
||||
"syntax-string": "#40bf7a",
|
||||
"syntax-primitive": "#d94f4f",
|
||||
"syntax-property": "#a277ff",
|
||||
"syntax-type": "#d9a24a",
|
||||
"syntax-constant": "#5bb8d9",
|
||||
"syntax-info": "#5bb8d9",
|
||||
"markdown-heading": "#a277ff",
|
||||
"markdown-text": "#2d2640",
|
||||
"markdown-link": "#c17ac8",
|
||||
"markdown-link-text": "#a277ff",
|
||||
"markdown-code": "#40bf7a",
|
||||
"markdown-block-quote": "#6d6d6d",
|
||||
"markdown-emph": "#d9a24a",
|
||||
"markdown-strong": "#a277ff",
|
||||
"markdown-horizontal-rule": "#d4c8ed",
|
||||
"markdown-list-item": "#a277ff",
|
||||
"markdown-list-enumeration": "#a277ff",
|
||||
"markdown-image": "#c17ac8",
|
||||
"markdown-image-text": "#a277ff",
|
||||
"markdown-code-block": "#5bb8d9"
|
||||
"syntax-keyword": "#7b5ae0"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#15141b",
|
||||
"ink": "#edecee",
|
||||
"primary": "#a277ff",
|
||||
"accent": "#ff6767",
|
||||
"success": "#61ffca",
|
||||
"warning": "#ffca85",
|
||||
"error": "#ff6767",
|
||||
"info": "#82e2ff",
|
||||
"interactive": "#a277ff",
|
||||
"diffAdd": "#61ffca",
|
||||
"diffDelete": "#ff6767"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#15141b",
|
||||
"background-weak": "#1a1921",
|
||||
"background-strong": "#121118",
|
||||
"background-stronger": "#0f0e14",
|
||||
"border-weak-base": "#2d2b38",
|
||||
"border-weak-hover": "#332f42",
|
||||
"border-weak-active": "#38354c",
|
||||
"border-weak-selected": "#3e3a56",
|
||||
"border-weak-disabled": "#1a1921",
|
||||
"border-weak-focus": "#363350",
|
||||
"border-base": "#433f5a",
|
||||
"border-hover": "#4a4565",
|
||||
"border-active": "#514c70",
|
||||
"border-selected": "#58527b",
|
||||
"border-disabled": "#1f1e28",
|
||||
"border-focus": "#4e496c",
|
||||
"border-strong-base": "#635c8a",
|
||||
"border-strong-hover": "#6d6597",
|
||||
"border-strong-active": "#776fa4",
|
||||
"border-strong-selected": "#8179b1",
|
||||
"border-strong-disabled": "#2a283a",
|
||||
"border-strong-focus": "#716a9e",
|
||||
"surface-diff-add-base": "#162620",
|
||||
"surface-diff-delete-base": "#26161a",
|
||||
"surface-diff-hidden-base": "#1e1d2a",
|
||||
"text-base": "#edecee",
|
||||
"text-weak": "#6d6d6d",
|
||||
"text-strong": "#ffffff",
|
||||
"syntax-string": "#61ffca",
|
||||
"syntax-primitive": "#ff6767",
|
||||
"syntax-property": "#a277ff",
|
||||
"syntax-type": "#ffca85",
|
||||
"syntax-constant": "#82e2ff",
|
||||
"syntax-info": "#82e2ff",
|
||||
"markdown-heading": "#a277ff",
|
||||
"markdown-text": "#edecee",
|
||||
"markdown-link": "#f694ff",
|
||||
"markdown-link-text": "#a277ff",
|
||||
"markdown-code": "#61ffca",
|
||||
"markdown-block-quote": "#6d6d6d",
|
||||
"markdown-emph": "#ffca85",
|
||||
"markdown-strong": "#a277ff",
|
||||
"markdown-horizontal-rule": "#2d2b38",
|
||||
"markdown-list-item": "#a277ff",
|
||||
"markdown-list-enumeration": "#a277ff",
|
||||
"markdown-image": "#f694ff",
|
||||
"markdown-image-text": "#a277ff",
|
||||
"markdown-code-block": "#edecee"
|
||||
"syntax-keyword": "#a277ff"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,131 +3,37 @@
|
||||
"name": "Ayu",
|
||||
"id": "ayu",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#fdfaf4",
|
||||
"ink": "#4f5964",
|
||||
"primary": "#4aa8c8",
|
||||
"accent": "#ef7d71",
|
||||
"success": "#5fb978",
|
||||
"warning": "#ea9f41",
|
||||
"error": "#e6656a",
|
||||
"info": "#2f9bce",
|
||||
"interactive": "#4aa8c8",
|
||||
"diffAdd": "#b1d780",
|
||||
"diffDelete": "#e6656a"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#fdfaf4",
|
||||
"background-weak": "#fcf9f3",
|
||||
"background-strong": "#fbf8f2",
|
||||
"background-stronger": "#faf7f1",
|
||||
"surface-raised-base-hover": "#f4f0e9",
|
||||
"border-weak-base": "#e6ddcf",
|
||||
"border-weak-hover": "#dcd3c5",
|
||||
"border-weak-active": "#d1c9ba",
|
||||
"border-weak-selected": "#c6bfaf",
|
||||
"border-weak-disabled": "#f7f0e6",
|
||||
"border-weak-focus": "#cbc4b6",
|
||||
"border-base": "#bfb3a3",
|
||||
"border-hover": "#b4a898",
|
||||
"border-active": "#a99e8e",
|
||||
"border-selected": "#9e9383",
|
||||
"border-disabled": "#efe5d8",
|
||||
"border-focus": "#b09f8f",
|
||||
"border-strong-base": "#837765",
|
||||
"border-strong-hover": "#7a6f5f",
|
||||
"border-strong-active": "#716655",
|
||||
"border-strong-selected": "#685e4e",
|
||||
"border-strong-disabled": "#d8cabc",
|
||||
"border-strong-focus": "#766b5c",
|
||||
"surface-diff-add-base": "#eef5e4",
|
||||
"surface-diff-delete-base": "#fde5e5",
|
||||
"surface-diff-hidden-base": "#e3edf3",
|
||||
"text-base": "#4f5964",
|
||||
"text-weak": "#77818d",
|
||||
"text-strong": "#1b232b",
|
||||
"syntax-string": "#7fad00",
|
||||
"syntax-primitive": "#ef7d71",
|
||||
"syntax-property": "#4aa8c8",
|
||||
"syntax-type": "#ed982e",
|
||||
"syntax-constant": "#2f9bce",
|
||||
"syntax-info": "#2f9bce",
|
||||
"markdown-heading": "#4aa8c8",
|
||||
"markdown-text": "#4f5964",
|
||||
"markdown-link": "#4aa8c8",
|
||||
"markdown-link-text": "#2f9bce",
|
||||
"markdown-code": "#7fad00",
|
||||
"markdown-block-quote": "#ed982e",
|
||||
"markdown-emph": "#ed982e",
|
||||
"markdown-strong": "#f07f72",
|
||||
"markdown-horizontal-rule": "#d7cec0",
|
||||
"markdown-list-item": "#4aa8c8",
|
||||
"markdown-list-enumeration": "#2f9bce",
|
||||
"markdown-image": "#4aa8c8",
|
||||
"markdown-image-text": "#2f9bce",
|
||||
"markdown-code-block": "#4aa8c8"
|
||||
"syntax-keyword": "#ea9f41"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#0f1419",
|
||||
"ink": "#d6dae0",
|
||||
"primary": "#3fb7e3",
|
||||
"accent": "#f2856f",
|
||||
"success": "#78d05c",
|
||||
"warning": "#e4a75c",
|
||||
"error": "#f58572",
|
||||
"info": "#66c6f1",
|
||||
"interactive": "#3fb7e3",
|
||||
"diffAdd": "#59c57c",
|
||||
"diffDelete": "#f58572"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#0f1419",
|
||||
"background-weak": "#18222c",
|
||||
"background-strong": "#0b1015",
|
||||
"background-stronger": "#080c10",
|
||||
"surface-raised-base-hover": "#0f1419",
|
||||
"border-weak-base": "#2b3440",
|
||||
"border-weak-hover": "#323c49",
|
||||
"border-weak-active": "#394454",
|
||||
"border-weak-selected": "#415063",
|
||||
"border-weak-disabled": "#0a0e12",
|
||||
"border-weak-focus": "#374453",
|
||||
"border-base": "#475367",
|
||||
"border-hover": "#515f75",
|
||||
"border-active": "#5d6b83",
|
||||
"border-selected": "#687795",
|
||||
"border-disabled": "#11161d",
|
||||
"border-focus": "#56647c",
|
||||
"border-strong-base": "#73819b",
|
||||
"border-strong-hover": "#7f8da8",
|
||||
"border-strong-active": "#8b99b5",
|
||||
"border-strong-selected": "#98a6c3",
|
||||
"border-strong-disabled": "#1b222c",
|
||||
"border-strong-focus": "#8391ad",
|
||||
"surface-diff-add-base": "#132f27",
|
||||
"surface-diff-delete-base": "#361d20",
|
||||
"surface-diff-hidden-base": "#1b2632",
|
||||
"text-base": "#d6dae0",
|
||||
"text-weak": "#a3adba",
|
||||
"text-strong": "#fbfbfd",
|
||||
"syntax-string": "#b1c74a",
|
||||
"syntax-primitive": "#f2856f",
|
||||
"syntax-property": "#3fb7e3",
|
||||
"syntax-type": "#e4a75c",
|
||||
"syntax-constant": "#66c6f1",
|
||||
"syntax-info": "#66c6f1",
|
||||
"markdown-heading": "#3fb7e3",
|
||||
"markdown-text": "#d6dae0",
|
||||
"markdown-link": "#3fb7e3",
|
||||
"markdown-link-text": "#66c6f1",
|
||||
"markdown-code": "#b1c74a",
|
||||
"markdown-block-quote": "#e4a75c",
|
||||
"markdown-emph": "#e4a75c",
|
||||
"markdown-strong": "#f2856f",
|
||||
"markdown-horizontal-rule": "#2b3542",
|
||||
"markdown-list-item": "#3fb7e3",
|
||||
"markdown-list-enumeration": "#66c6f1",
|
||||
"markdown-image": "#3fb7e3",
|
||||
"markdown-image-text": "#66c6f1",
|
||||
"markdown-code-block": "#d6dae0"
|
||||
"syntax-keyword": "#ffad66"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
"name": "Carbonfox",
|
||||
"id": "carbonfox",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#8e8e8e",
|
||||
"ink": "#161616",
|
||||
"primary": "#0072c3",
|
||||
"accent": "#da1e28",
|
||||
"success": "#198038",
|
||||
"warning": "#f1c21b",
|
||||
"error": "#da1e28",
|
||||
@@ -15,44 +17,15 @@
|
||||
"diffDelete": "#da1e28"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#ffffff",
|
||||
"background-weak": "#f4f4f4",
|
||||
"background-strong": "#e8e8e8",
|
||||
"background-stronger": "#dcdcdc",
|
||||
"surface-raised-strong": "#ffffff",
|
||||
"surface-raised-stronger": "#ffffff",
|
||||
"surface-float-base": "#161616",
|
||||
"surface-float-base-hover": "#262626",
|
||||
"text-base": "#161616",
|
||||
"text-weak": "#525252",
|
||||
"text-strong": "#000000",
|
||||
"syntax-string": "#198038",
|
||||
"syntax-primitive": "#da1e28",
|
||||
"syntax-property": "#0043ce",
|
||||
"syntax-type": "#007d79",
|
||||
"syntax-constant": "#6929c4",
|
||||
"syntax-keyword": "#525252",
|
||||
"syntax-info": "#0043ce",
|
||||
"markdown-heading": "#0043ce",
|
||||
"markdown-text": "#161616",
|
||||
"markdown-link": "#0043ce",
|
||||
"markdown-link-text": "#0072c3",
|
||||
"markdown-code": "#198038",
|
||||
"markdown-block-quote": "#525252",
|
||||
"markdown-emph": "#6929c4",
|
||||
"markdown-strong": "#161616",
|
||||
"markdown-horizontal-rule": "#c6c6c6",
|
||||
"markdown-list-item": "#0072c3",
|
||||
"markdown-list-enumeration": "#0072c3",
|
||||
"markdown-image": "#0043ce",
|
||||
"markdown-image-text": "#0072c3",
|
||||
"markdown-code-block": "#393939"
|
||||
"syntax-keyword": "#8a3ffc"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#393939",
|
||||
"ink": "#f2f4f8",
|
||||
"primary": "#33b1ff",
|
||||
"accent": "#ff8389",
|
||||
"success": "#42be65",
|
||||
"warning": "#f1c21b",
|
||||
"error": "#ff8389",
|
||||
@@ -62,61 +35,7 @@
|
||||
"diffDelete": "#ff8389"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#161616",
|
||||
"background-weak": "#262626",
|
||||
"background-strong": "#0d0d0d",
|
||||
"background-stronger": "#000000",
|
||||
"surface-raised-base": "#1c1c1c",
|
||||
"surface-raised-base-hover": "#262626",
|
||||
"surface-raised-strong": "#262626",
|
||||
"surface-raised-strong-hover": "#303030",
|
||||
"surface-raised-stronger": "#303030",
|
||||
"surface-raised-stronger-hover": "#393939",
|
||||
"surface-raised-stronger-non-alpha": "#303030",
|
||||
"surface-float-base": "#0d0d0d",
|
||||
"surface-float-base-hover": "#1a1a1a",
|
||||
"surface-inset-base": "#0d0d0d",
|
||||
"surface-inset-strong": "#000000",
|
||||
"surface-base": "#1e1e1e",
|
||||
"surface-base-hover": "#262626",
|
||||
"surface-diff-add-base": "#0e3a22",
|
||||
"surface-diff-delete-base": "#4d1a1f",
|
||||
"input-base": "#262626",
|
||||
"input-hover": "#303030",
|
||||
"button-secondary-base": "#393939",
|
||||
"button-secondary-hover": "#4c4c4c",
|
||||
"border-weak-base": "#393939",
|
||||
"border-weak-hover": "#4c4c4c",
|
||||
"border-base": "#525252",
|
||||
"border-hover": "#636363",
|
||||
"border-strong-base": "#6f6f6f",
|
||||
"text-base": "#f2f4f8",
|
||||
"text-weak": "#8d8d8d",
|
||||
"text-weaker": "#6f6f6f",
|
||||
"text-strong": "#ffffff",
|
||||
"icon-base": "#8d8d8d",
|
||||
"icon-weak-base": "#6f6f6f",
|
||||
"syntax-string": "#42be65",
|
||||
"syntax-primitive": "#ff8389",
|
||||
"syntax-property": "#78a9ff",
|
||||
"syntax-type": "#08bdba",
|
||||
"syntax-constant": "#be95ff",
|
||||
"syntax-keyword": "#8d8d8d",
|
||||
"syntax-info": "#78a9ff",
|
||||
"markdown-heading": "#82cfff",
|
||||
"markdown-text": "#f2f4f8",
|
||||
"markdown-link": "#78a9ff",
|
||||
"markdown-link-text": "#33b1ff",
|
||||
"markdown-code": "#42be65",
|
||||
"markdown-block-quote": "#8d8d8d",
|
||||
"markdown-emph": "#be95ff",
|
||||
"markdown-strong": "#ffffff",
|
||||
"markdown-horizontal-rule": "#393939",
|
||||
"markdown-list-item": "#33b1ff",
|
||||
"markdown-list-enumeration": "#33b1ff",
|
||||
"markdown-image": "#78a9ff",
|
||||
"markdown-image-text": "#33b1ff",
|
||||
"markdown-code-block": "#c6c6c6"
|
||||
"syntax-keyword": "#be95ff"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,39 @@
|
||||
"name": "Catppuccin",
|
||||
"id": "catppuccin",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#f5e0dc",
|
||||
"ink": "#4c4f69",
|
||||
"primary": "#7287fd",
|
||||
"accent": "#d20f39",
|
||||
"success": "#40a02b",
|
||||
"warning": "#df8e1d",
|
||||
"error": "#d20f39",
|
||||
"info": "#04a5e5",
|
||||
"interactive": "#7287fd",
|
||||
"diffAdd": "#a6d189",
|
||||
"diffDelete": "#e78284"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f5e0dc",
|
||||
"background-weak": "#f2d8d4",
|
||||
"background-strong": "#f9e8e4",
|
||||
"background-stronger": "#fdeeee",
|
||||
"border-weak-base": "#e0cfd3",
|
||||
"border-weak-hover": "#d6c4c8",
|
||||
"border-weak-active": "#cdb9be",
|
||||
"border-weak-selected": "#c2aeb4",
|
||||
"border-weak-disabled": "#fbeff2",
|
||||
"border-weak-focus": "#c7b4ba",
|
||||
"border-base": "#bca6b2",
|
||||
"border-hover": "#b19ca8",
|
||||
"border-active": "#a6929e",
|
||||
"border-selected": "#9a8894",
|
||||
"border-disabled": "#f3e4e7",
|
||||
"border-focus": "#ab97a1",
|
||||
"border-strong-base": "#83677f",
|
||||
"border-strong-hover": "#775b73",
|
||||
"border-strong-active": "#6b5068",
|
||||
"border-strong-selected": "#5f465d",
|
||||
"border-strong-disabled": "#d9c5cf",
|
||||
"border-strong-focus": "#714f66",
|
||||
"surface-diff-add-base": "#edf5e6",
|
||||
"surface-diff-delete-base": "#fde1e3",
|
||||
"surface-diff-hidden-base": "#e4e2f6",
|
||||
"text-base": "#4c4f69",
|
||||
"text-weak": "#6c6f85",
|
||||
"text-strong": "#1f1f2a",
|
||||
"syntax-string": "#40a02b",
|
||||
"syntax-primitive": "#d20f39",
|
||||
"syntax-property": "#7287fd",
|
||||
"syntax-type": "#df8e1d",
|
||||
"syntax-constant": "#04a5e5",
|
||||
"syntax-info": "#04a5e5",
|
||||
"markdown-heading": "#7287fd",
|
||||
"markdown-text": "#4c4f69",
|
||||
"markdown-link": "#7287fd",
|
||||
"markdown-link-text": "#04a5e5",
|
||||
"markdown-code": "#40a02b",
|
||||
"markdown-block-quote": "#df8e1d",
|
||||
"markdown-emph": "#df8e1d",
|
||||
"markdown-strong": "#d20f39",
|
||||
"markdown-horizontal-rule": "#d4c5cf",
|
||||
"markdown-list-item": "#7287fd",
|
||||
"markdown-list-enumeration": "#04a5e5",
|
||||
"markdown-image": "#7287fd",
|
||||
"markdown-image-text": "#04a5e5",
|
||||
"markdown-code-block": "#7287fd"
|
||||
"syntax-keyword": "#8839ef",
|
||||
"syntax-primitive": "#fe640b"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#1e1e2e",
|
||||
"ink": "#cdd6f4",
|
||||
"primary": "#b4befe",
|
||||
"accent": "#f38ba8",
|
||||
"success": "#a6d189",
|
||||
"warning": "#f4b8e4",
|
||||
"error": "#f38ba8",
|
||||
"info": "#89dceb",
|
||||
"interactive": "#b4befe",
|
||||
"diffAdd": "#94e2d5",
|
||||
"diffDelete": "#f38ba8"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#1e1e2e",
|
||||
"background-weak": "#211f31",
|
||||
"background-strong": "#1c1c29",
|
||||
"background-stronger": "#191926",
|
||||
"border-weak-base": "#35324a",
|
||||
"border-weak-hover": "#393655",
|
||||
"border-weak-active": "#403c61",
|
||||
"border-weak-selected": "#47436d",
|
||||
"border-weak-disabled": "#141426",
|
||||
"border-weak-focus": "#3d3a63",
|
||||
"border-base": "#4a4763",
|
||||
"border-hover": "#524f70",
|
||||
"border-active": "#5a577d",
|
||||
"border-selected": "#625f8a",
|
||||
"border-disabled": "#1b1a2c",
|
||||
"border-focus": "#575379",
|
||||
"border-strong-base": "#6e6a8c",
|
||||
"border-strong-hover": "#787497",
|
||||
"border-strong-active": "#8380a2",
|
||||
"border-strong-selected": "#8d8bad",
|
||||
"border-strong-disabled": "#232237",
|
||||
"border-strong-focus": "#7b779b",
|
||||
"surface-diff-add-base": "#1d2c30",
|
||||
"surface-diff-delete-base": "#2c1f2a",
|
||||
"surface-diff-hidden-base": "#232538",
|
||||
"text-base": "#cdd6f4",
|
||||
"text-weak": "#a6adc8",
|
||||
"text-strong": "#f4f2ff",
|
||||
"syntax-string": "#a6e3a1",
|
||||
"syntax-primitive": "#f38ba8",
|
||||
"syntax-property": "#b4befe",
|
||||
"syntax-type": "#f9e2af",
|
||||
"syntax-constant": "#89dceb",
|
||||
"syntax-info": "#89dceb",
|
||||
"markdown-heading": "#b4befe",
|
||||
"markdown-text": "#cdd6f4",
|
||||
"markdown-link": "#b4befe",
|
||||
"markdown-link-text": "#89dceb",
|
||||
"markdown-code": "#a6e3a1",
|
||||
"markdown-block-quote": "#f9e2af",
|
||||
"markdown-emph": "#f9e2af",
|
||||
"markdown-strong": "#f38ba8",
|
||||
"markdown-horizontal-rule": "#2e2d45",
|
||||
"markdown-list-item": "#b4befe",
|
||||
"markdown-list-enumeration": "#89dceb",
|
||||
"markdown-image": "#b4befe",
|
||||
"markdown-image-text": "#89dceb",
|
||||
"markdown-code-block": "#cdd6f4"
|
||||
"syntax-keyword": "#cba6f7",
|
||||
"syntax-primitive": "#fab387"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,41 @@
|
||||
"name": "Dracula",
|
||||
"id": "dracula",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#f8f8f2",
|
||||
"ink": "#1f1f2f",
|
||||
"primary": "#7c6bf5",
|
||||
"accent": "#d16090",
|
||||
"success": "#2fbf71",
|
||||
"warning": "#f7a14d",
|
||||
"error": "#d9536f",
|
||||
"info": "#1d7fc5",
|
||||
"interactive": "#7c6bf5",
|
||||
"diffAdd": "#9fe3b3",
|
||||
"diffDelete": "#f8a1b8"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f8f8f2",
|
||||
"background-weak": "#f1f2ed",
|
||||
"background-strong": "#f6f6f1",
|
||||
"background-stronger": "#f2f2ec",
|
||||
"border-weak-base": "#e2e3da",
|
||||
"border-weak-hover": "#d8d9d0",
|
||||
"border-weak-active": "#cfd0c7",
|
||||
"border-weak-selected": "#c4c6bc",
|
||||
"border-weak-disabled": "#eceee3",
|
||||
"border-weak-focus": "#c9cabf",
|
||||
"border-base": "#c4c6ba",
|
||||
"border-hover": "#b8baae",
|
||||
"border-active": "#abada3",
|
||||
"border-selected": "#979a90",
|
||||
"border-disabled": "#e5e7dd",
|
||||
"border-focus": "#b0b2a7",
|
||||
"border-strong-base": "#9fa293",
|
||||
"border-strong-hover": "#8e9185",
|
||||
"border-strong-active": "#7e8176",
|
||||
"border-strong-selected": "#6f7268",
|
||||
"border-strong-disabled": "#c7c9be",
|
||||
"border-strong-focus": "#878b7f",
|
||||
"surface-diff-add-base": "#e4f5e6",
|
||||
"surface-diff-delete-base": "#fae4eb",
|
||||
"surface-diff-hidden-base": "#dedfe9",
|
||||
"text-base": "#1f1f2f",
|
||||
"text-weak": "#52526b",
|
||||
"text-strong": "#05040c",
|
||||
"syntax-string": "#2fbf71",
|
||||
"syntax-primitive": "#d16090",
|
||||
"syntax-property": "#7c6bf5",
|
||||
"syntax-type": "#f7a14d",
|
||||
"syntax-constant": "#1d7fc5",
|
||||
"syntax-info": "#1d7fc5",
|
||||
"markdown-heading": "#7c6bf5",
|
||||
"markdown-text": "#1f1f2f",
|
||||
"markdown-link": "#7c6bf5",
|
||||
"markdown-link-text": "#1d7fc5",
|
||||
"markdown-code": "#2fbf71",
|
||||
"markdown-block-quote": "#f7a14d",
|
||||
"markdown-emph": "#f7a14d",
|
||||
"markdown-strong": "#d16090",
|
||||
"markdown-horizontal-rule": "#c3c5d4",
|
||||
"markdown-list-item": "#7c6bf5",
|
||||
"markdown-list-enumeration": "#1d7fc5",
|
||||
"markdown-image": "#7c6bf5",
|
||||
"markdown-image-text": "#1d7fc5",
|
||||
"markdown-code-block": "#1d7fc5"
|
||||
"syntax-keyword": "#d16090",
|
||||
"syntax-string": "#596600",
|
||||
"syntax-primitive": "#7c6bf5"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#1d1e28",
|
||||
"ink": "#f8f8f2",
|
||||
"primary": "#bd93f9",
|
||||
"accent": "#ff79c6",
|
||||
"success": "#50fa7b",
|
||||
"warning": "#ffb86c",
|
||||
"error": "#ff5555",
|
||||
"info": "#8be9fd",
|
||||
"interactive": "#bd93f9",
|
||||
"diffAdd": "#2fb27d",
|
||||
"diffDelete": "#ff6b81"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#14151f",
|
||||
"background-weak": "#181926",
|
||||
"background-strong": "#161722",
|
||||
"background-stronger": "#191a26",
|
||||
"border-weak-base": "#2d2f3c",
|
||||
"border-weak-hover": "#303244",
|
||||
"border-weak-active": "#35364c",
|
||||
"border-weak-selected": "#3b3d55",
|
||||
"border-weak-disabled": "#1e1f2b",
|
||||
"border-weak-focus": "#383a50",
|
||||
"border-base": "#3f415a",
|
||||
"border-hover": "#464967",
|
||||
"border-active": "#4d5073",
|
||||
"border-selected": "#55587f",
|
||||
"border-disabled": "#272834",
|
||||
"border-focus": "#4a4d6d",
|
||||
"border-strong-base": "#606488",
|
||||
"border-strong-hover": "#6a6e96",
|
||||
"border-strong-active": "#7378a3",
|
||||
"border-strong-selected": "#7d82b1",
|
||||
"border-strong-disabled": "#343649",
|
||||
"border-strong-focus": "#6f739c",
|
||||
"surface-diff-add-base": "#1f2a2f",
|
||||
"surface-diff-delete-base": "#2d1f27",
|
||||
"surface-diff-hidden-base": "#24253a",
|
||||
"text-base": "#f8f8f2",
|
||||
"text-weak": "#b6b9e4",
|
||||
"text-strong": "#ffffff",
|
||||
"syntax-string": "#50fa7b",
|
||||
"syntax-primitive": "#ff79c6",
|
||||
"syntax-property": "#bd93f9",
|
||||
"syntax-type": "#ffb86c",
|
||||
"syntax-constant": "#8be9fd",
|
||||
"syntax-info": "#8be9fd",
|
||||
"markdown-heading": "#bd93f9",
|
||||
"markdown-text": "#f8f8f2",
|
||||
"markdown-link": "#bd93f9",
|
||||
"markdown-link-text": "#8be9fd",
|
||||
"markdown-code": "#50fa7b",
|
||||
"markdown-block-quote": "#ffb86c",
|
||||
"markdown-emph": "#ffb86c",
|
||||
"markdown-strong": "#ff79c6",
|
||||
"markdown-horizontal-rule": "#44475a",
|
||||
"markdown-list-item": "#bd93f9",
|
||||
"markdown-list-enumeration": "#8be9fd",
|
||||
"markdown-image": "#bd93f9",
|
||||
"markdown-image-text": "#8be9fd",
|
||||
"markdown-code-block": "#f8f8f2"
|
||||
"syntax-keyword": "#ff79c6",
|
||||
"syntax-string": "#f1fa8c",
|
||||
"syntax-primitive": "#bd93f9"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,130 +3,39 @@
|
||||
"name": "Gruvbox",
|
||||
"id": "gruvbox",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#fbf1c7",
|
||||
"ink": "#3c3836",
|
||||
"primary": "#076678",
|
||||
"accent": "#9d0006",
|
||||
"success": "#79740e",
|
||||
"warning": "#b57614",
|
||||
"error": "#9d0006",
|
||||
"info": "#8f3f71",
|
||||
"interactive": "#076678",
|
||||
"diffAdd": "#79740e",
|
||||
"diffDelete": "#9d0006"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#fbf1c7",
|
||||
"background-weak": "#f2e5bc",
|
||||
"background-strong": "#f9f5d7",
|
||||
"background-stronger": "#fdf9e8",
|
||||
"surface-raised-stronger-non-alpha": "#fbfaf5",
|
||||
"border-weak-base": "#d5c4a1",
|
||||
"border-weak-hover": "#c9b897",
|
||||
"border-weak-active": "#bdae93",
|
||||
"border-weak-selected": "#b0a285",
|
||||
"border-weak-disabled": "#f0e4b8",
|
||||
"border-weak-focus": "#c4b590",
|
||||
"border-base": "#bdae93",
|
||||
"border-hover": "#b0a285",
|
||||
"border-active": "#a89984",
|
||||
"border-selected": "#928374",
|
||||
"border-disabled": "#e5d9ad",
|
||||
"border-focus": "#a89984",
|
||||
"border-strong-base": "#7c6f64",
|
||||
"border-strong-hover": "#6e6259",
|
||||
"border-strong-active": "#665c54",
|
||||
"border-strong-selected": "#5a524b",
|
||||
"border-strong-disabled": "#c9bda1",
|
||||
"border-strong-focus": "#665c54",
|
||||
"surface-diff-add-base": "#dde3b1",
|
||||
"surface-diff-delete-base": "#e8c7c3",
|
||||
"surface-diff-hidden-base": "#ebdfb5",
|
||||
"text-base": "#3c3836",
|
||||
"text-weak": "#7c6f64",
|
||||
"text-strong": "#282828",
|
||||
"syntax-string": "#79740e",
|
||||
"syntax-primitive": "#9d0006",
|
||||
"syntax-property": "#076678",
|
||||
"syntax-type": "#b57614",
|
||||
"syntax-constant": "#8f3f71",
|
||||
"syntax-info": "#427b58",
|
||||
"markdown-heading": "#076678",
|
||||
"markdown-text": "#3c3836",
|
||||
"markdown-link": "#076678",
|
||||
"markdown-link-text": "#427b58",
|
||||
"markdown-code": "#79740e",
|
||||
"markdown-block-quote": "#928374",
|
||||
"markdown-emph": "#8f3f71",
|
||||
"markdown-strong": "#af3a03",
|
||||
"markdown-horizontal-rule": "#d5c4a1",
|
||||
"markdown-list-item": "#076678",
|
||||
"markdown-list-enumeration": "#427b58",
|
||||
"markdown-image": "#076678",
|
||||
"markdown-image-text": "#427b58",
|
||||
"markdown-code-block": "#3c3836"
|
||||
"syntax-keyword": "#9d0006",
|
||||
"syntax-primitive": "#8f3f71"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#282828",
|
||||
"ink": "#ebdbb2",
|
||||
"primary": "#83a598",
|
||||
"accent": "#fb4934",
|
||||
"success": "#b8bb26",
|
||||
"warning": "#fabd2f",
|
||||
"error": "#fb4934",
|
||||
"info": "#d3869b",
|
||||
"interactive": "#83a598",
|
||||
"diffAdd": "#b8bb26",
|
||||
"diffDelete": "#fb4934"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#282828",
|
||||
"background-weak": "#32302f",
|
||||
"background-strong": "#1d2021",
|
||||
"background-stronger": "#141617",
|
||||
"border-weak-base": "#504945",
|
||||
"border-weak-hover": "#5a524b",
|
||||
"border-weak-active": "#665c54",
|
||||
"border-weak-selected": "#70665d",
|
||||
"border-weak-disabled": "#1e1d1c",
|
||||
"border-weak-focus": "#5e5650",
|
||||
"border-base": "#665c54",
|
||||
"border-hover": "#70665d",
|
||||
"border-active": "#7c6f64",
|
||||
"border-selected": "#928374",
|
||||
"border-disabled": "#2a2827",
|
||||
"border-focus": "#7c6f64",
|
||||
"border-strong-base": "#928374",
|
||||
"border-strong-hover": "#9d8e7f",
|
||||
"border-strong-active": "#a89984",
|
||||
"border-strong-selected": "#b3a48f",
|
||||
"border-strong-disabled": "#3c3836",
|
||||
"border-strong-focus": "#a89984",
|
||||
"surface-diff-add-base": "#2a3325",
|
||||
"surface-diff-delete-base": "#3c2222",
|
||||
"surface-diff-hidden-base": "#32302f",
|
||||
"text-base": "#ebdbb2",
|
||||
"text-weak": "#a89984",
|
||||
"text-strong": "#fbf1c7",
|
||||
"syntax-string": "#b8bb26",
|
||||
"syntax-primitive": "#fb4934",
|
||||
"syntax-property": "#83a598",
|
||||
"syntax-type": "#fabd2f",
|
||||
"syntax-constant": "#d3869b",
|
||||
"syntax-info": "#8ec07c",
|
||||
"markdown-heading": "#83a598",
|
||||
"markdown-text": "#ebdbb2",
|
||||
"markdown-link": "#83a598",
|
||||
"markdown-link-text": "#8ec07c",
|
||||
"markdown-code": "#b8bb26",
|
||||
"markdown-block-quote": "#928374",
|
||||
"markdown-emph": "#d3869b",
|
||||
"markdown-strong": "#fe8019",
|
||||
"markdown-horizontal-rule": "#504945",
|
||||
"markdown-list-item": "#83a598",
|
||||
"markdown-list-enumeration": "#8ec07c",
|
||||
"markdown-image": "#83a598",
|
||||
"markdown-image-text": "#8ec07c",
|
||||
"markdown-code-block": "#ebdbb2"
|
||||
"syntax-keyword": "#fb4934",
|
||||
"syntax-primitive": "#d3869b"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,41 @@
|
||||
"name": "Monokai",
|
||||
"id": "monokai",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#fdf8ec",
|
||||
"ink": "#292318",
|
||||
"primary": "#bf7bff",
|
||||
"accent": "#d9487c",
|
||||
"success": "#4fb54b",
|
||||
"warning": "#f1a948",
|
||||
"error": "#e54b4b",
|
||||
"info": "#2d9ad7",
|
||||
"interactive": "#bf7bff",
|
||||
"diffAdd": "#bfe7a3",
|
||||
"diffDelete": "#f6a3ae"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#fdf8ec",
|
||||
"background-weak": "#f8f2e6",
|
||||
"background-strong": "#fbf5e8",
|
||||
"background-stronger": "#f7efdd",
|
||||
"border-weak-base": "#e9e0cf",
|
||||
"border-weak-hover": "#dfd5c3",
|
||||
"border-weak-active": "#d5cab7",
|
||||
"border-weak-selected": "#cabfad",
|
||||
"border-weak-disabled": "#f3ebdd",
|
||||
"border-weak-focus": "#d0c2b1",
|
||||
"border-base": "#c7b9a5",
|
||||
"border-hover": "#bcae98",
|
||||
"border-active": "#b0a28c",
|
||||
"border-selected": "#a49781",
|
||||
"border-disabled": "#efe5d6",
|
||||
"border-focus": "#b6a893",
|
||||
"border-strong-base": "#998b76",
|
||||
"border-strong-hover": "#8a7c67",
|
||||
"border-strong-active": "#7a6d58",
|
||||
"border-strong-selected": "#6c604c",
|
||||
"border-strong-disabled": "#d7cabc",
|
||||
"border-strong-focus": "#82745f",
|
||||
"surface-diff-add-base": "#e8f7e1",
|
||||
"surface-diff-delete-base": "#fde5e4",
|
||||
"surface-diff-hidden-base": "#e9e0d0",
|
||||
"text-base": "#292318",
|
||||
"text-weak": "#6d5c40",
|
||||
"text-strong": "#1c150c",
|
||||
"syntax-string": "#4fb54b",
|
||||
"syntax-primitive": "#d9487c",
|
||||
"syntax-property": "#bf7bff",
|
||||
"syntax-type": "#f1a948",
|
||||
"syntax-constant": "#2d9ad7",
|
||||
"syntax-info": "#2d9ad7",
|
||||
"markdown-heading": "#bf7bff",
|
||||
"markdown-text": "#292318",
|
||||
"markdown-link": "#bf7bff",
|
||||
"markdown-link-text": "#2d9ad7",
|
||||
"markdown-code": "#4fb54b",
|
||||
"markdown-block-quote": "#f1a948",
|
||||
"markdown-emph": "#f1a948",
|
||||
"markdown-strong": "#d9487c",
|
||||
"markdown-horizontal-rule": "#cdbdab",
|
||||
"markdown-list-item": "#bf7bff",
|
||||
"markdown-list-enumeration": "#2d9ad7",
|
||||
"markdown-image": "#bf7bff",
|
||||
"markdown-image-text": "#2d9ad7",
|
||||
"markdown-code-block": "#2d9ad7"
|
||||
"syntax-keyword": "#d9487c",
|
||||
"syntax-string": "#8a6500",
|
||||
"syntax-primitive": "#bf7bff"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#272822",
|
||||
"ink": "#f8f8f2",
|
||||
"primary": "#ae81ff",
|
||||
"accent": "#f92672",
|
||||
"success": "#a6e22e",
|
||||
"warning": "#fd971f",
|
||||
"error": "#f92672",
|
||||
"info": "#66d9ef",
|
||||
"interactive": "#ae81ff",
|
||||
"diffAdd": "#4d7f2a",
|
||||
"diffDelete": "#f4477c"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#23241e",
|
||||
"background-weak": "#27281f",
|
||||
"background-strong": "#25261f",
|
||||
"background-stronger": "#292a23",
|
||||
"border-weak-base": "#343528",
|
||||
"border-weak-hover": "#393a2d",
|
||||
"border-weak-active": "#3f4033",
|
||||
"border-weak-selected": "#454639",
|
||||
"border-weak-disabled": "#1d1e16",
|
||||
"border-weak-focus": "#414235",
|
||||
"border-base": "#494a3a",
|
||||
"border-hover": "#50523f",
|
||||
"border-active": "#585a45",
|
||||
"border-selected": "#60624b",
|
||||
"border-disabled": "#23241b",
|
||||
"border-focus": "#555741",
|
||||
"border-strong-base": "#6a6c55",
|
||||
"border-strong-hover": "#73755d",
|
||||
"border-strong-active": "#7d7f66",
|
||||
"border-strong-selected": "#878970",
|
||||
"border-strong-disabled": "#2c2d23",
|
||||
"border-strong-focus": "#7a7c63",
|
||||
"surface-diff-add-base": "#1e2a1d",
|
||||
"surface-diff-delete-base": "#301c24",
|
||||
"surface-diff-hidden-base": "#2f2f24",
|
||||
"text-base": "#f8f8f2",
|
||||
"text-weak": "#c5c5c0",
|
||||
"text-strong": "#ffffff",
|
||||
"syntax-string": "#a6e22e",
|
||||
"syntax-primitive": "#f92672",
|
||||
"syntax-property": "#ae81ff",
|
||||
"syntax-type": "#fd971f",
|
||||
"syntax-constant": "#66d9ef",
|
||||
"syntax-info": "#66d9ef",
|
||||
"markdown-heading": "#ae81ff",
|
||||
"markdown-text": "#f8f8f2",
|
||||
"markdown-link": "#ae81ff",
|
||||
"markdown-link-text": "#66d9ef",
|
||||
"markdown-code": "#a6e22e",
|
||||
"markdown-block-quote": "#fd971f",
|
||||
"markdown-emph": "#fd971f",
|
||||
"markdown-strong": "#f92672",
|
||||
"markdown-horizontal-rule": "#3b3c34",
|
||||
"markdown-list-item": "#ae81ff",
|
||||
"markdown-list-enumeration": "#66d9ef",
|
||||
"markdown-image": "#ae81ff",
|
||||
"markdown-image-text": "#66d9ef",
|
||||
"markdown-code-block": "#f8f8f2"
|
||||
"syntax-keyword": "#f92672",
|
||||
"syntax-string": "#e6db74",
|
||||
"syntax-primitive": "#ae81ff"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,40 @@
|
||||
"name": "Night Owl",
|
||||
"id": "nightowl",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#f0f0f0",
|
||||
"ink": "#403f53",
|
||||
"primary": "#4876d6",
|
||||
"accent": "#aa0982",
|
||||
"success": "#2aa298",
|
||||
"warning": "#c96765",
|
||||
"error": "#de3d3b",
|
||||
"info": "#4876d6",
|
||||
"interactive": "#4876d6",
|
||||
"diffAdd": "#2aa298",
|
||||
"diffDelete": "#de3d3b"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#fbfbfb",
|
||||
"background-weak": "#f0f0f0",
|
||||
"background-strong": "#ffffff",
|
||||
"background-stronger": "#ffffff",
|
||||
"border-weak-base": "#d9d9d9",
|
||||
"border-weak-hover": "#cccccc",
|
||||
"border-weak-active": "#bfbfbf",
|
||||
"border-weak-selected": "#4876d6",
|
||||
"border-weak-disabled": "#e6e6e6",
|
||||
"border-weak-focus": "#4876d6",
|
||||
"border-base": "#c0c0c0",
|
||||
"border-hover": "#b3b3b3",
|
||||
"border-active": "#a6a6a6",
|
||||
"border-selected": "#4876d6",
|
||||
"border-disabled": "#d9d9d9",
|
||||
"border-focus": "#4876d6",
|
||||
"border-strong-base": "#90a7b2",
|
||||
"border-strong-hover": "#7d9aa6",
|
||||
"border-strong-active": "#6a8d9a",
|
||||
"border-strong-selected": "#4876d6",
|
||||
"border-strong-disabled": "#c0c0c0",
|
||||
"border-strong-focus": "#4876d6",
|
||||
"surface-diff-add-base": "#eaf8f6",
|
||||
"surface-diff-delete-base": "#fbe9e9",
|
||||
"surface-diff-hidden-base": "#e8f0fc",
|
||||
"text-base": "#403f53",
|
||||
"text-weak": "#7a8181",
|
||||
"text-strong": "#1a1a1a",
|
||||
"syntax-string": "#c96765",
|
||||
"syntax-primitive": "#aa0982",
|
||||
"syntax-property": "#4876d6",
|
||||
"syntax-type": "#994cc3",
|
||||
"syntax-constant": "#2aa298",
|
||||
"syntax-info": "#4876d6",
|
||||
"markdown-heading": "#4876d6",
|
||||
"markdown-text": "#403f53",
|
||||
"markdown-link": "#4876d6",
|
||||
"markdown-link-text": "#2aa298",
|
||||
"markdown-code": "#2aa298",
|
||||
"markdown-block-quote": "#7a8181",
|
||||
"markdown-emph": "#994cc3",
|
||||
"markdown-strong": "#c96765",
|
||||
"markdown-horizontal-rule": "#90a7b2",
|
||||
"markdown-list-item": "#4876d6",
|
||||
"markdown-list-enumeration": "#2aa298",
|
||||
"markdown-image": "#4876d6",
|
||||
"markdown-image-text": "#2aa298",
|
||||
"markdown-code-block": "#403f53"
|
||||
"syntax-keyword": "#994cc3"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#011627",
|
||||
"ink": "#d6deeb",
|
||||
"primary": "#82aaff",
|
||||
"accent": "#f78c6c",
|
||||
"success": "#c5e478",
|
||||
"warning": "#ecc48d",
|
||||
"error": "#ef5350",
|
||||
"info": "#82aaff",
|
||||
"interactive": "#82aaff",
|
||||
"diffAdd": "#c5e478",
|
||||
"diffDelete": "#ef5350"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#011627",
|
||||
"background-weak": "#0b253a",
|
||||
"background-strong": "#001122",
|
||||
"background-stronger": "#000c17",
|
||||
"border-weak-base": "#1d3b53",
|
||||
"border-weak-hover": "#234561",
|
||||
"border-weak-active": "#2a506f",
|
||||
"border-weak-selected": "#82aaff",
|
||||
"border-weak-disabled": "#0f2132",
|
||||
"border-weak-focus": "#82aaff",
|
||||
"border-base": "#3a5a75",
|
||||
"border-hover": "#456785",
|
||||
"border-active": "#507494",
|
||||
"border-selected": "#82aaff",
|
||||
"border-disabled": "#1a3347",
|
||||
"border-focus": "#82aaff",
|
||||
"border-strong-base": "#5f7e97",
|
||||
"border-strong-hover": "#6e8da6",
|
||||
"border-strong-active": "#7d9cb5",
|
||||
"border-strong-selected": "#82aaff",
|
||||
"border-strong-disabled": "#2c4a63",
|
||||
"border-strong-focus": "#82aaff",
|
||||
"surface-diff-add-base": "#0a2e1a",
|
||||
"surface-diff-delete-base": "#2d1b1b",
|
||||
"surface-diff-hidden-base": "#0b253a",
|
||||
"text-base": "#d6deeb",
|
||||
"text-weak": "#5f7e97",
|
||||
"text-strong": "#ffffff",
|
||||
"syntax-comment": "#637777",
|
||||
"syntax-keyword": "#c792ea",
|
||||
"syntax-string": "#ecc48d",
|
||||
"syntax-primitive": "#f78c6c",
|
||||
"syntax-property": "#82aaff",
|
||||
"syntax-type": "#c5e478",
|
||||
"syntax-constant": "#7fdbca",
|
||||
"syntax-info": "#82aaff",
|
||||
"markdown-heading": "#82aaff",
|
||||
"markdown-text": "#d6deeb",
|
||||
"markdown-link": "#82aaff",
|
||||
"markdown-link-text": "#7fdbca",
|
||||
"markdown-code": "#c5e478",
|
||||
"markdown-block-quote": "#5f7e97",
|
||||
"markdown-emph": "#c792ea",
|
||||
"markdown-strong": "#ecc48d",
|
||||
"markdown-horizontal-rule": "#5f7e97",
|
||||
"markdown-list-item": "#82aaff",
|
||||
"markdown-list-enumeration": "#7fdbca",
|
||||
"markdown-image": "#82aaff",
|
||||
"markdown-image-text": "#7fdbca",
|
||||
"markdown-code-block": "#d6deeb"
|
||||
"syntax-primitive": "#f78c6c"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,40 @@
|
||||
"name": "Nord",
|
||||
"id": "nord",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#eceff4",
|
||||
"ink": "#2e3440",
|
||||
"primary": "#5e81ac",
|
||||
"accent": "#bf616a",
|
||||
"success": "#8fbcbb",
|
||||
"warning": "#d08770",
|
||||
"error": "#bf616a",
|
||||
"info": "#81a1c1",
|
||||
"interactive": "#5e81ac",
|
||||
"diffAdd": "#a3be8c",
|
||||
"diffDelete": "#bf616a"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#eceff4",
|
||||
"background-weak": "#e4e8f0",
|
||||
"background-strong": "#f1f3f8",
|
||||
"background-stronger": "#f6f8fc",
|
||||
"border-weak-base": "#d5dbe7",
|
||||
"border-weak-hover": "#c9d0de",
|
||||
"border-weak-active": "#bec5d4",
|
||||
"border-weak-selected": "#b2bacc",
|
||||
"border-weak-disabled": "#f0f3fa",
|
||||
"border-weak-focus": "#b9bfd0",
|
||||
"border-base": "#afb7cb",
|
||||
"border-hover": "#a3abc1",
|
||||
"border-active": "#979fb7",
|
||||
"border-selected": "#8b94ad",
|
||||
"border-disabled": "#e5e9f2",
|
||||
"border-focus": "#9ca4ba",
|
||||
"border-strong-base": "#757f97",
|
||||
"border-strong-hover": "#69718a",
|
||||
"border-strong-active": "#5d647d",
|
||||
"border-strong-selected": "#525970",
|
||||
"border-strong-disabled": "#c9cedc",
|
||||
"border-strong-focus": "#636c84",
|
||||
"surface-diff-add-base": "#e4f0e4",
|
||||
"surface-diff-delete-base": "#f4e1e4",
|
||||
"surface-diff-hidden-base": "#dfe6f2",
|
||||
"text-base": "#2e3440",
|
||||
"text-weak": "#4c566a",
|
||||
"text-strong": "#1f2530",
|
||||
"syntax-keyword": "#5e81ac",
|
||||
"syntax-string": "#a3be8c",
|
||||
"syntax-primitive": "#bf616a",
|
||||
"syntax-property": "#5e81ac",
|
||||
"syntax-type": "#d08770",
|
||||
"syntax-constant": "#81a1c1",
|
||||
"syntax-info": "#81a1c1",
|
||||
"markdown-heading": "#5e81ac",
|
||||
"markdown-text": "#2e3440",
|
||||
"markdown-link": "#5e81ac",
|
||||
"markdown-link-text": "#81a1c1",
|
||||
"markdown-code": "#a3be8c",
|
||||
"markdown-block-quote": "#d08770",
|
||||
"markdown-emph": "#d08770",
|
||||
"markdown-strong": "#bf616a",
|
||||
"markdown-horizontal-rule": "#cbd3e1",
|
||||
"markdown-list-item": "#5e81ac",
|
||||
"markdown-list-enumeration": "#81a1c1",
|
||||
"markdown-image": "#5e81ac",
|
||||
"markdown-image-text": "#81a1c1",
|
||||
"markdown-code-block": "#5e81ac"
|
||||
"syntax-primitive": "#b48ead"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#2e3440",
|
||||
"ink": "#e5e9f0",
|
||||
"primary": "#88c0d0",
|
||||
"accent": "#d57780",
|
||||
"success": "#a3be8c",
|
||||
"warning": "#d08770",
|
||||
"error": "#bf616a",
|
||||
"info": "#81a1c1",
|
||||
"interactive": "#88c0d0",
|
||||
"diffAdd": "#81a1c1",
|
||||
"diffDelete": "#bf616a"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#1f2430",
|
||||
"background-weak": "#222938",
|
||||
"background-strong": "#1c202a",
|
||||
"background-stronger": "#181c24",
|
||||
"border-weak-base": "#343a47",
|
||||
"border-weak-hover": "#383f50",
|
||||
"border-weak-active": "#3d4458",
|
||||
"border-weak-selected": "#434a62",
|
||||
"border-weak-disabled": "#151923",
|
||||
"border-weak-focus": "#3f4359",
|
||||
"border-base": "#4a5163",
|
||||
"border-hover": "#515870",
|
||||
"border-active": "#585f7c",
|
||||
"border-selected": "#606889",
|
||||
"border-disabled": "#1b202a",
|
||||
"border-focus": "#545b78",
|
||||
"border-strong-base": "#6a7492",
|
||||
"border-strong-hover": "#747e9f",
|
||||
"border-strong-active": "#7e88ac",
|
||||
"border-strong-selected": "#8993b9",
|
||||
"border-strong-disabled": "#232836",
|
||||
"border-strong-focus": "#76819f",
|
||||
"surface-diff-add-base": "#1f2e33",
|
||||
"surface-diff-delete-base": "#2e212a",
|
||||
"surface-diff-hidden-base": "#222b3a",
|
||||
"text-base": "#e5e9f0",
|
||||
"text-weak": "#a4adbf",
|
||||
"text-strong": "#f8fafc",
|
||||
"syntax-string": "#a3be8c",
|
||||
"syntax-primitive": "#d57780",
|
||||
"syntax-property": "#88c0d0",
|
||||
"syntax-type": "#eac196",
|
||||
"syntax-constant": "#81a1c1",
|
||||
"syntax-info": "#81a1c1",
|
||||
"markdown-heading": "#88c0d0",
|
||||
"markdown-text": "#e5e9f0",
|
||||
"markdown-link": "#88c0d0",
|
||||
"markdown-link-text": "#81a1c1",
|
||||
"markdown-code": "#a3be8c",
|
||||
"markdown-block-quote": "#d08770",
|
||||
"markdown-emph": "#d08770",
|
||||
"markdown-strong": "#bf616a",
|
||||
"markdown-horizontal-rule": "#2f384a",
|
||||
"markdown-list-item": "#88c0d0",
|
||||
"markdown-list-enumeration": "#81a1c1",
|
||||
"markdown-image": "#88c0d0",
|
||||
"markdown-image-text": "#81a1c1",
|
||||
"markdown-code-block": "#cbd3e1"
|
||||
"syntax-keyword": "#81a1c1",
|
||||
"syntax-primitive": "#b48ead"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
"name": "OC-1",
|
||||
"id": "oc-1",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#8e8b8b",
|
||||
"ink": "#656363",
|
||||
"primary": "#dcde8d",
|
||||
"accent": "#fb4804",
|
||||
"success": "#12c905",
|
||||
"warning": "#ffdc17",
|
||||
"error": "#fc533a",
|
||||
@@ -13,260 +15,14 @@
|
||||
"interactive": "#034cff",
|
||||
"diffAdd": "#9ff29a",
|
||||
"diffDelete": "#fc533a"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f8f7f7",
|
||||
"background-weak": "var(--smoke-light-3)",
|
||||
"background-strong": "var(--smoke-light-1)",
|
||||
"background-stronger": "#fcfcfc",
|
||||
"surface-base": "var(--smoke-light-alpha-2)",
|
||||
"base": "var(--smoke-light-alpha-2)",
|
||||
"surface-base-hover": "#0500000f",
|
||||
"surface-base-active": "var(--smoke-light-alpha-3)",
|
||||
"surface-base-interactive-active": "var(--cobalt-light-alpha-3)",
|
||||
"base2": "var(--smoke-light-alpha-2)",
|
||||
"base3": "var(--smoke-light-alpha-2)",
|
||||
"surface-inset-base": "var(--smoke-light-alpha-2)",
|
||||
"surface-inset-base-hover": "var(--smoke-light-alpha-3)",
|
||||
"surface-inset-strong": "#1f000017",
|
||||
"surface-inset-strong-hover": "#1f000017",
|
||||
"surface-raised-base": "var(--smoke-light-alpha-2)",
|
||||
"surface-float-base": "var(--smoke-dark-1)",
|
||||
"surface-float-base-hover": "var(--smoke-dark-2)",
|
||||
"surface-raised-base-hover": "var(--smoke-light-alpha-3)",
|
||||
"surface-raised-base-active": "var(--smoke-light-alpha-4)",
|
||||
"surface-raised-strong": "var(--smoke-light-1)",
|
||||
"surface-raised-strong-hover": "var(--white)",
|
||||
"surface-raised-stronger": "var(--white)",
|
||||
"surface-raised-stronger-hover": "var(--white)",
|
||||
"surface-weak": "var(--smoke-light-alpha-3)",
|
||||
"surface-weaker": "var(--smoke-light-alpha-4)",
|
||||
"surface-strong": "#ffffff",
|
||||
"surface-raised-stronger-non-alpha": "var(--white)",
|
||||
"surface-brand-base": "var(--yuzu-light-9)",
|
||||
"surface-brand-hover": "var(--yuzu-light-10)",
|
||||
"surface-interactive-base": "var(--cobalt-light-3)",
|
||||
"surface-interactive-hover": "#E5F0FF",
|
||||
"surface-interactive-weak": "var(--cobalt-light-2)",
|
||||
"surface-interactive-weak-hover": "var(--cobalt-light-3)",
|
||||
"surface-success-base": "var(--apple-light-3)",
|
||||
"surface-success-weak": "var(--apple-light-2)",
|
||||
"surface-success-strong": "var(--apple-light-9)",
|
||||
"surface-warning-base": "var(--solaris-light-3)",
|
||||
"surface-warning-weak": "var(--solaris-light-2)",
|
||||
"surface-warning-strong": "var(--solaris-light-9)",
|
||||
"surface-critical-base": "var(--ember-light-3)",
|
||||
"surface-critical-weak": "var(--ember-light-2)",
|
||||
"surface-critical-strong": "var(--ember-light-9)",
|
||||
"surface-info-base": "var(--lilac-light-3)",
|
||||
"surface-info-weak": "var(--lilac-light-2)",
|
||||
"surface-info-strong": "var(--lilac-light-9)",
|
||||
"surface-diff-unchanged-base": "#ffffff00",
|
||||
"surface-diff-skip-base": "var(--smoke-light-2)",
|
||||
"surface-diff-hidden-base": "var(--blue-light-3)",
|
||||
"surface-diff-hidden-weak": "var(--blue-light-2)",
|
||||
"surface-diff-hidden-weaker": "var(--blue-light-1)",
|
||||
"surface-diff-hidden-strong": "var(--blue-light-5)",
|
||||
"surface-diff-hidden-stronger": "var(--blue-light-9)",
|
||||
"surface-diff-add-base": "#dafbe0",
|
||||
"surface-diff-add-weak": "var(--mint-light-2)",
|
||||
"surface-diff-add-weaker": "var(--mint-light-1)",
|
||||
"surface-diff-add-strong": "var(--mint-light-5)",
|
||||
"surface-diff-add-stronger": "var(--mint-light-9)",
|
||||
"surface-diff-delete-base": "var(--ember-light-3)",
|
||||
"surface-diff-delete-weak": "var(--ember-light-2)",
|
||||
"surface-diff-delete-weaker": "var(--ember-light-1)",
|
||||
"surface-diff-delete-strong": "var(--ember-light-6)",
|
||||
"surface-diff-delete-stronger": "var(--ember-light-9)",
|
||||
"input-base": "var(--smoke-light-1)",
|
||||
"input-hover": "var(--smoke-light-2)",
|
||||
"input-active": "var(--cobalt-light-1)",
|
||||
"input-selected": "var(--cobalt-light-4)",
|
||||
"input-focus": "var(--cobalt-light-1)",
|
||||
"input-disabled": "var(--smoke-light-4)",
|
||||
"text-base": "var(--smoke-light-11)",
|
||||
"text-weak": "var(--smoke-light-9)",
|
||||
"text-weaker": "var(--smoke-light-8)",
|
||||
"text-strong": "var(--smoke-light-12)",
|
||||
"text-invert-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-invert-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-invert-weaker": "var(--smoke-dark-alpha-8)",
|
||||
"text-invert-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-interactive-base": "var(--cobalt-light-9)",
|
||||
"text-on-brand-base": "var(--smoke-light-alpha-11)",
|
||||
"text-on-interactive-base": "var(--smoke-light-1)",
|
||||
"text-on-interactive-weak": "var(--smoke-dark-alpha-11)",
|
||||
"text-on-success-base": "var(--apple-light-10)",
|
||||
"text-on-critical-base": "var(--ember-light-10)",
|
||||
"text-on-critical-weak": "var(--ember-light-8)",
|
||||
"text-on-critical-strong": "var(--ember-light-12)",
|
||||
"text-on-warning-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-on-info-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-diff-add-base": "var(--mint-light-11)",
|
||||
"text-diff-delete-base": "var(--ember-light-10)",
|
||||
"text-diff-delete-strong": "var(--ember-light-12)",
|
||||
"text-diff-add-strong": "var(--mint-light-12)",
|
||||
"text-on-info-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-on-info-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-on-warning-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-on-warning-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-on-success-weak": "var(--apple-light-6)",
|
||||
"text-on-success-strong": "var(--apple-light-12)",
|
||||
"text-on-brand-weak": "var(--smoke-light-alpha-9)",
|
||||
"text-on-brand-weaker": "var(--smoke-light-alpha-8)",
|
||||
"text-on-brand-strong": "var(--smoke-light-alpha-12)",
|
||||
"button-primary-base": "var(--smoke-light-12)",
|
||||
"button-secondary-base": "#fdfcfc",
|
||||
"button-secondary-hover": "#faf9f9",
|
||||
"border-base": "var(--smoke-light-alpha-7)",
|
||||
"border-hover": "var(--smoke-light-alpha-8)",
|
||||
"border-active": "var(--smoke-light-alpha-9)",
|
||||
"border-selected": "var(--cobalt-light-alpha-9)",
|
||||
"border-disabled": "var(--smoke-light-alpha-8)",
|
||||
"border-focus": "var(--smoke-light-alpha-9)",
|
||||
"border-weak-base": "var(--smoke-light-alpha-5)",
|
||||
"border-strong-base": "var(--smoke-light-alpha-7)",
|
||||
"border-strong-hover": "var(--smoke-light-alpha-8)",
|
||||
"border-strong-active": "var(--smoke-light-alpha-7)",
|
||||
"border-strong-selected": "var(--cobalt-light-alpha-6)",
|
||||
"border-strong-disabled": "var(--smoke-light-alpha-6)",
|
||||
"border-strong-focus": "var(--smoke-light-alpha-7)",
|
||||
"border-weak-hover": "var(--smoke-light-alpha-6)",
|
||||
"border-weak-active": "var(--smoke-light-alpha-7)",
|
||||
"border-weak-selected": "var(--cobalt-light-alpha-5)",
|
||||
"border-weak-disabled": "var(--smoke-light-alpha-6)",
|
||||
"border-weak-focus": "var(--smoke-light-alpha-7)",
|
||||
"border-interactive-base": "var(--cobalt-light-7)",
|
||||
"border-interactive-hover": "var(--cobalt-light-8)",
|
||||
"border-interactive-active": "var(--cobalt-light-9)",
|
||||
"border-interactive-selected": "var(--cobalt-light-9)",
|
||||
"border-interactive-disabled": "var(--smoke-light-8)",
|
||||
"border-interactive-focus": "var(--cobalt-light-9)",
|
||||
"border-success-base": "var(--apple-light-6)",
|
||||
"border-success-hover": "var(--apple-light-7)",
|
||||
"border-success-selected": "var(--apple-light-9)",
|
||||
"border-warning-base": "var(--solaris-light-6)",
|
||||
"border-warning-hover": "var(--solaris-light-7)",
|
||||
"border-warning-selected": "var(--solaris-light-9)",
|
||||
"border-critical-base": "var(--ember-light-6)",
|
||||
"border-critical-hover": "var(--ember-light-7)",
|
||||
"border-critical-selected": "var(--ember-light-9)",
|
||||
"border-info-base": "var(--lilac-light-6)",
|
||||
"border-info-hover": "var(--lilac-light-7)",
|
||||
"border-info-selected": "var(--lilac-light-9)",
|
||||
"icon-base": "var(--smoke-light-9)",
|
||||
"icon-hover": "var(--smoke-light-11)",
|
||||
"icon-active": "var(--smoke-light-12)",
|
||||
"icon-selected": "var(--smoke-light-12)",
|
||||
"icon-disabled": "var(--smoke-light-8)",
|
||||
"icon-focus": "var(--smoke-light-12)",
|
||||
"icon-invert-base": "#ffffff",
|
||||
"icon-weak-base": "var(--smoke-light-7)",
|
||||
"icon-weak-hover": "var(--smoke-light-8)",
|
||||
"icon-weak-active": "var(--smoke-light-9)",
|
||||
"icon-weak-selected": "var(--smoke-light-10)",
|
||||
"icon-weak-disabled": "var(--smoke-light-6)",
|
||||
"icon-weak-focus": "var(--smoke-light-9)",
|
||||
"icon-strong-base": "var(--smoke-light-12)",
|
||||
"icon-strong-hover": "#151313",
|
||||
"icon-strong-active": "#020202",
|
||||
"icon-strong-selected": "#020202",
|
||||
"icon-strong-disabled": "var(--smoke-light-8)",
|
||||
"icon-strong-focus": "#020202",
|
||||
"icon-brand-base": "var(--smoke-light-12)",
|
||||
"icon-interactive-base": "var(--cobalt-light-9)",
|
||||
"icon-success-base": "var(--apple-light-7)",
|
||||
"icon-success-hover": "var(--apple-light-8)",
|
||||
"icon-success-active": "var(--apple-light-11)",
|
||||
"icon-warning-base": "var(--amber-light-7)",
|
||||
"icon-warning-hover": "var(--amber-light-8)",
|
||||
"icon-warning-active": "var(--amber-light-11)",
|
||||
"icon-critical-base": "var(--ember-light-10)",
|
||||
"icon-critical-hover": "var(--ember-light-11)",
|
||||
"icon-critical-active": "var(--ember-light-12)",
|
||||
"icon-info-base": "var(--lilac-light-7)",
|
||||
"icon-info-hover": "var(--lilac-light-8)",
|
||||
"icon-info-active": "var(--lilac-light-11)",
|
||||
"icon-on-brand-base": "var(--smoke-light-alpha-11)",
|
||||
"icon-on-brand-hover": "var(--smoke-light-alpha-12)",
|
||||
"icon-on-brand-selected": "var(--smoke-light-alpha-12)",
|
||||
"icon-on-interactive-base": "var(--smoke-light-1)",
|
||||
"icon-agent-plan-base": "var(--purple-light-9)",
|
||||
"icon-agent-docs-base": "var(--amber-light-9)",
|
||||
"icon-agent-ask-base": "var(--cyan-light-9)",
|
||||
"icon-agent-build-base": "var(--cobalt-light-9)",
|
||||
"icon-on-success-base": "var(--apple-light-alpha-9)",
|
||||
"icon-on-success-hover": "var(--apple-light-alpha-10)",
|
||||
"icon-on-success-selected": "var(--apple-light-alpha-11)",
|
||||
"icon-on-warning-base": "var(--amber-lightalpha-9)",
|
||||
"icon-on-warning-hover": "var(--amber-lightalpha-10)",
|
||||
"icon-on-warning-selected": "var(--amber-lightalpha-11)",
|
||||
"icon-on-critical-base": "var(--ember-light-alpha-9)",
|
||||
"icon-on-critical-hover": "var(--ember-light-alpha-10)",
|
||||
"icon-on-critical-selected": "var(--ember-light-alpha-11)",
|
||||
"icon-on-info-base": "var(--lilac-light-9)",
|
||||
"icon-on-info-hover": "var(--lilac-light-alpha-10)",
|
||||
"icon-on-info-selected": "var(--lilac-light-alpha-11)",
|
||||
"icon-diff-add-base": "var(--mint-light-11)",
|
||||
"icon-diff-add-hover": "var(--mint-light-12)",
|
||||
"icon-diff-add-active": "var(--mint-light-12)",
|
||||
"icon-diff-delete-base": "var(--ember-light-10)",
|
||||
"icon-diff-delete-hover": "var(--ember-light-11)",
|
||||
"syntax-comment": "var(--text-weak)",
|
||||
"syntax-regexp": "var(--text-base)",
|
||||
"syntax-string": "#006656",
|
||||
"syntax-keyword": "var(--text-weak)",
|
||||
"syntax-primitive": "#fb4804",
|
||||
"syntax-operator": "var(--text-base)",
|
||||
"syntax-variable": "var(--text-strong)",
|
||||
"syntax-property": "#ed6dc8",
|
||||
"syntax-type": "#596600",
|
||||
"syntax-constant": "#007b80",
|
||||
"syntax-punctuation": "var(--text-base)",
|
||||
"syntax-object": "var(--text-strong)",
|
||||
"syntax-success": "var(--apple-light-10)",
|
||||
"syntax-warning": "var(--amber-light-10)",
|
||||
"syntax-critical": "var(--ember-light-10)",
|
||||
"syntax-info": "#0092a8",
|
||||
"syntax-diff-add": "var(--mint-light-11)",
|
||||
"syntax-diff-delete": "var(--ember-light-11)",
|
||||
"syntax-diff-unknown": "#ff0000",
|
||||
"markdown-heading": "#d68c27",
|
||||
"markdown-text": "#1a1a1a",
|
||||
"markdown-link": "#3b7dd8",
|
||||
"markdown-link-text": "#318795",
|
||||
"markdown-code": "#3d9a57",
|
||||
"markdown-block-quote": "#b0851f",
|
||||
"markdown-emph": "#b0851f",
|
||||
"markdown-strong": "#d68c27",
|
||||
"markdown-horizontal-rule": "#8a8a8a",
|
||||
"markdown-list-item": "#3b7dd8",
|
||||
"markdown-list-enumeration": "#318795",
|
||||
"markdown-image": "#3b7dd8",
|
||||
"markdown-image-text": "#318795",
|
||||
"markdown-code-block": "#1a1a1a",
|
||||
"border-color": "#ffffff",
|
||||
"border-weaker-base": "var(--smoke-light-alpha-3)",
|
||||
"button-ghost-hover": "var(--smoke-light-alpha-2)",
|
||||
"button-ghost-hover2": "var(--smoke-light-alpha-3)",
|
||||
"avatar-background-pink": "#feeef8",
|
||||
"avatar-background-mint": "#e1fbf4",
|
||||
"avatar-background-orange": "#fff1e7",
|
||||
"avatar-background-purple": "#f9f1fe",
|
||||
"avatar-background-cyan": "#e7f9fb",
|
||||
"avatar-background-lime": "#eefadc",
|
||||
"avatar-text-pink": "#cd1d8d",
|
||||
"avatar-text-mint": "#147d6f",
|
||||
"avatar-text-orange": "#ed5f00",
|
||||
"avatar-text-purple": "#8445bc",
|
||||
"avatar-text-cyan": "#0894b3",
|
||||
"avatar-text-lime": "#5d770d"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#716c6b",
|
||||
"ink": "#b7b1b1",
|
||||
"primary": "#fab283",
|
||||
"accent": "#ffba92",
|
||||
"success": "#12c905",
|
||||
"warning": "#fcd53a",
|
||||
"error": "#fc533a",
|
||||
@@ -274,254 +30,6 @@
|
||||
"interactive": "#034cff",
|
||||
"diffAdd": "#c8ffc4",
|
||||
"diffDelete": "#fc533a"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "var(--smoke-dark-1)",
|
||||
"background-weak": "#1c1717",
|
||||
"background-strong": "#151313",
|
||||
"background-stronger": "#191515",
|
||||
"surface-base": "var(--smoke-dark-alpha-2)",
|
||||
"base": "var(--smoke-dark-alpha-2)",
|
||||
"surface-base-hover": "#e0b7b716",
|
||||
"surface-base-active": "var(--smoke-dark-alpha-3)",
|
||||
"surface-base-interactive-active": "var(--cobalt-dark-alpha-2)",
|
||||
"base2": "var(--smoke-dark-alpha-2)",
|
||||
"base3": "var(--smoke-dark-alpha-2)",
|
||||
"surface-inset-base": "#0e0b0b7f",
|
||||
"surface-inset-base-hover": "#0e0b0b7f",
|
||||
"surface-inset-strong": "#060505cc",
|
||||
"surface-inset-strong-hover": "#060505cc",
|
||||
"surface-raised-base": "var(--smoke-dark-alpha-3)",
|
||||
"surface-float-base": "var(--smoke-dark-1)",
|
||||
"surface-float-base-hover": "var(--smoke-dark-2)",
|
||||
"surface-raised-base-hover": "var(--smoke-dark-alpha-4)",
|
||||
"surface-raised-base-active": "var(--smoke-dark-alpha-5)",
|
||||
"surface-raised-strong": "var(--smoke-dark-alpha-4)",
|
||||
"surface-raised-strong-hover": "var(--smoke-dark-alpha-6)",
|
||||
"surface-raised-stronger": "var(--smoke-dark-alpha-6)",
|
||||
"surface-raised-stronger-hover": "var(--smoke-dark-alpha-7)",
|
||||
"surface-weak": "var(--smoke-dark-alpha-4)",
|
||||
"surface-weaker": "var(--smoke-dark-alpha-5)",
|
||||
"surface-strong": "var(--smoke-dark-alpha-7)",
|
||||
"surface-raised-stronger-non-alpha": "var(--smoke-dark-3)",
|
||||
"surface-brand-base": "var(--yuzu-light-9)",
|
||||
"surface-brand-hover": "var(--yuzu-light-10)",
|
||||
"surface-interactive-base": "var(--cobalt-dark-3)",
|
||||
"surface-interactive-hover": "#0A1D4D",
|
||||
"surface-interactive-weak": "var(--cobalt-dark-2)",
|
||||
"surface-interactive-weak-hover": "var(--cobalt-light-3)",
|
||||
"surface-success-base": "var(--apple-dark-3)",
|
||||
"surface-success-weak": "var(--apple-dark-2)",
|
||||
"surface-success-strong": "var(--apple-dark-9)",
|
||||
"surface-warning-base": "var(--solaris-light-3)",
|
||||
"surface-warning-weak": "var(--solaris-light-2)",
|
||||
"surface-warning-strong": "var(--solaris-light-9)",
|
||||
"surface-critical-base": "var(--ember-dark-3)",
|
||||
"surface-critical-weak": "var(--ember-dark-2)",
|
||||
"surface-critical-strong": "var(--ember-dark-9)",
|
||||
"surface-info-base": "var(--lilac-light-3)",
|
||||
"surface-info-weak": "var(--lilac-light-2)",
|
||||
"surface-info-strong": "var(--lilac-light-9)",
|
||||
"surface-diff-unchanged-base": "var(--smoke-dark-1)",
|
||||
"surface-diff-skip-base": "var(--smoke-dark-alpha-1)",
|
||||
"surface-diff-hidden-base": "var(--blue-dark-2)",
|
||||
"surface-diff-hidden-weak": "var(--blue-dark-1)",
|
||||
"surface-diff-hidden-weaker": "var(--blue-dark-3)",
|
||||
"surface-diff-hidden-strong": "var(--blue-dark-5)",
|
||||
"surface-diff-hidden-stronger": "var(--blue-dark-11)",
|
||||
"surface-diff-add-base": "var(--mint-dark-3)",
|
||||
"surface-diff-add-weak": "var(--mint-dark-4)",
|
||||
"surface-diff-add-weaker": "var(--mint-dark-3)",
|
||||
"surface-diff-add-strong": "var(--mint-dark-5)",
|
||||
"surface-diff-add-stronger": "var(--mint-dark-11)",
|
||||
"surface-diff-delete-base": "var(--ember-dark-3)",
|
||||
"surface-diff-delete-weak": "var(--ember-dark-4)",
|
||||
"surface-diff-delete-weaker": "var(--ember-dark-3)",
|
||||
"surface-diff-delete-strong": "var(--ember-dark-5)",
|
||||
"surface-diff-delete-stronger": "var(--ember-dark-11)",
|
||||
"input-base": "var(--smoke-dark-2)",
|
||||
"input-hover": "var(--smoke-dark-2)",
|
||||
"input-active": "var(--cobalt-dark-1)",
|
||||
"input-selected": "var(--cobalt-dark-2)",
|
||||
"input-focus": "var(--cobalt-dark-1)",
|
||||
"input-disabled": "var(--smoke-dark-4)",
|
||||
"text-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-weaker": "var(--smoke-dark-alpha-8)",
|
||||
"text-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-invert-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-invert-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-invert-weaker": "var(--smoke-dark-alpha-8)",
|
||||
"text-invert-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-interactive-base": "var(--cobalt-dark-11)",
|
||||
"text-on-brand-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-on-interactive-base": "var(--smoke-dark-12)",
|
||||
"text-on-interactive-weak": "var(--smoke-dark-alpha-11)",
|
||||
"text-on-success-base": "var(--apple-dark-9)",
|
||||
"text-on-critical-base": "var(--ember-dark-9)",
|
||||
"text-on-critical-weak": "var(--ember-dark-8)",
|
||||
"text-on-critical-strong": "var(--ember-dark-12)",
|
||||
"text-on-warning-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-on-info-base": "var(--smoke-dark-alpha-11)",
|
||||
"text-diff-add-base": "var(--mint-dark-11)",
|
||||
"text-diff-delete-base": "var(--ember-dark-9)",
|
||||
"text-diff-delete-strong": "var(--ember-dark-12)",
|
||||
"text-diff-add-strong": "var(--mint-dark-8)",
|
||||
"text-on-info-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-on-info-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-on-warning-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-on-warning-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-on-success-weak": "var(--apple-dark-8)",
|
||||
"text-on-success-strong": "var(--apple-dark-12)",
|
||||
"text-on-brand-weak": "var(--smoke-dark-alpha-9)",
|
||||
"text-on-brand-weaker": "var(--smoke-dark-alpha-8)",
|
||||
"text-on-brand-strong": "var(--smoke-dark-alpha-12)",
|
||||
"button-primary-base": "var(--smoke-dark-12)",
|
||||
"button-secondary-base": "#231f1f",
|
||||
"button-secondary-hover": "#2a2727",
|
||||
"border-base": "var(--smoke-dark-alpha-7)",
|
||||
"border-hover": "var(--smoke-dark-alpha-8)",
|
||||
"border-active": "var(--smoke-dark-alpha-9)",
|
||||
"border-selected": "var(--cobalt-dark-alpha-11)",
|
||||
"border-disabled": "var(--smoke-dark-alpha-8)",
|
||||
"border-focus": "var(--smoke-dark-alpha-9)",
|
||||
"border-weak-base": "var(--smoke-dark-alpha-6)",
|
||||
"border-strong-base": "var(--smoke-dark-alpha-8)",
|
||||
"border-strong-hover": "var(--smoke-dark-alpha-7)",
|
||||
"border-strong-active": "var(--smoke-dark-alpha-8)",
|
||||
"border-strong-selected": "var(--cobalt-dark-alpha-6)",
|
||||
"border-strong-disabled": "var(--smoke-dark-alpha-6)",
|
||||
"border-strong-focus": "var(--smoke-dark-alpha-8)",
|
||||
"border-weak-hover": "var(--smoke-dark-alpha-7)",
|
||||
"border-weak-active": "var(--smoke-dark-alpha-8)",
|
||||
"border-weak-selected": "var(--cobalt-dark-alpha-6)",
|
||||
"border-weak-disabled": "var(--smoke-dark-alpha-6)",
|
||||
"border-weak-focus": "var(--smoke-dark-alpha-8)",
|
||||
"border-interactive-base": "var(--cobalt-light-7)",
|
||||
"border-interactive-hover": "var(--cobalt-light-8)",
|
||||
"border-interactive-active": "var(--cobalt-light-9)",
|
||||
"border-interactive-selected": "var(--cobalt-light-9)",
|
||||
"border-interactive-disabled": "var(--smoke-light-8)",
|
||||
"border-interactive-focus": "var(--cobalt-light-9)",
|
||||
"border-success-base": "var(--apple-light-6)",
|
||||
"border-success-hover": "var(--apple-light-7)",
|
||||
"border-success-selected": "var(--apple-light-9)",
|
||||
"border-warning-base": "var(--solaris-light-6)",
|
||||
"border-warning-hover": "var(--solaris-light-7)",
|
||||
"border-warning-selected": "var(--solaris-light-9)",
|
||||
"border-critical-base": "var(--ember-dark-5)",
|
||||
"border-critical-hover": "var(--ember-dark-7)",
|
||||
"border-critical-selected": "var(--ember-dark-9)",
|
||||
"border-info-base": "var(--lilac-light-6)",
|
||||
"border-info-hover": "var(--lilac-light-7)",
|
||||
"border-info-selected": "var(--lilac-light-9)",
|
||||
"icon-base": "var(--smoke-dark-9)",
|
||||
"icon-hover": "var(--smoke-dark-10)",
|
||||
"icon-active": "var(--smoke-dark-11)",
|
||||
"icon-selected": "var(--smoke-dark-12)",
|
||||
"icon-disabled": "var(--smoke-dark-7)",
|
||||
"icon-focus": "var(--smoke-dark-12)",
|
||||
"icon-invert-base": "var(--smoke-dark-1)",
|
||||
"icon-weak-base": "var(--smoke-dark-6)",
|
||||
"icon-weak-hover": "var(--smoke-light-7)",
|
||||
"icon-weak-active": "var(--smoke-light-8)",
|
||||
"icon-weak-selected": "var(--smoke-light-9)",
|
||||
"icon-weak-disabled": "var(--smoke-light-4)",
|
||||
"icon-weak-focus": "var(--smoke-light-9)",
|
||||
"icon-strong-base": "var(--smoke-dark-12)",
|
||||
"icon-strong-hover": "#f6f3f3",
|
||||
"icon-strong-active": "#fcfcfc",
|
||||
"icon-strong-selected": "#fdfcfc",
|
||||
"icon-strong-disabled": "var(--smoke-dark-8)",
|
||||
"icon-strong-focus": "#fdfcfc",
|
||||
"icon-brand-base": "var(--white)",
|
||||
"icon-interactive-base": "var(--cobalt-dark-11)",
|
||||
"icon-success-base": "var(--apple-dark-9)",
|
||||
"icon-success-hover": "var(--apple-dark-10)",
|
||||
"icon-success-active": "var(--apple-dark-11)",
|
||||
"icon-warning-base": "var(--amber-dark-9)",
|
||||
"icon-warning-hover": "var(--amber-dark-8)",
|
||||
"icon-warning-active": "var(--amber-dark-11)",
|
||||
"icon-critical-base": "var(--ember-dark-9)",
|
||||
"icon-critical-hover": "var(--ember-dark-11)",
|
||||
"icon-critical-active": "var(--ember-dark-12)",
|
||||
"icon-info-base": "var(--lilac-dark-7)",
|
||||
"icon-info-hover": "var(--lilac-dark-8)",
|
||||
"icon-info-active": "var(--lilac-dark-11)",
|
||||
"icon-on-brand-base": "var(--smoke-light-alpha-11)",
|
||||
"icon-on-brand-hover": "var(--smoke-light-alpha-12)",
|
||||
"icon-on-brand-selected": "var(--smoke-light-alpha-12)",
|
||||
"icon-on-interactive-base": "var(--smoke-dark-12)",
|
||||
"icon-agent-plan-base": "var(--purple-dark-9)",
|
||||
"icon-agent-docs-base": "var(--amber-dark-9)",
|
||||
"icon-agent-ask-base": "var(--cyan-dark-9)",
|
||||
"icon-agent-build-base": "var(--cobalt-dark-11)",
|
||||
"icon-on-success-base": "var(--apple-dark-alpha-9)",
|
||||
"icon-on-success-hover": "var(--apple-dark-alpha-10)",
|
||||
"icon-on-success-selected": "var(--apple-dark-alpha-11)",
|
||||
"icon-on-warning-base": "var(--amber-darkalpha-9)",
|
||||
"icon-on-warning-hover": "var(--amber-darkalpha-10)",
|
||||
"icon-on-warning-selected": "var(--amber-darkalpha-11)",
|
||||
"icon-on-critical-base": "var(--ember-dark-alpha-9)",
|
||||
"icon-on-critical-hover": "var(--ember-dark-alpha-10)",
|
||||
"icon-on-critical-selected": "var(--ember-dark-alpha-11)",
|
||||
"icon-on-info-base": "var(--lilac-dark-9)",
|
||||
"icon-on-info-hover": "var(--lilac-dark-alpha-10)",
|
||||
"icon-on-info-selected": "var(--lilac-dark-alpha-11)",
|
||||
"icon-diff-add-base": "var(--mint-dark-11)",
|
||||
"icon-diff-add-hover": "var(--mint-dark-10)",
|
||||
"icon-diff-add-active": "var(--mint-dark-11)",
|
||||
"icon-diff-delete-base": "var(--ember-dark-9)",
|
||||
"icon-diff-delete-hover": "var(--ember-dark-10)",
|
||||
"syntax-comment": "var(--text-weak)",
|
||||
"syntax-regexp": "var(--text-base)",
|
||||
"syntax-string": "#00ceb9",
|
||||
"syntax-keyword": "var(--text-weak)",
|
||||
"syntax-primitive": "#ffba92",
|
||||
"syntax-operator": "var(--text-weak)",
|
||||
"syntax-variable": "var(--text-strong)",
|
||||
"syntax-property": "#ff9ae2",
|
||||
"syntax-type": "#ecf58c",
|
||||
"syntax-constant": "#93e9f6",
|
||||
"syntax-punctuation": "var(--text-weak)",
|
||||
"syntax-object": "var(--text-strong)",
|
||||
"syntax-success": "var(--apple-dark-10)",
|
||||
"syntax-warning": "var(--amber-dark-10)",
|
||||
"syntax-critical": "var(--ember-dark-10)",
|
||||
"syntax-info": "#93e9f6",
|
||||
"syntax-diff-add": "var(--mint-dark-11)",
|
||||
"syntax-diff-delete": "var(--ember-dark-11)",
|
||||
"syntax-diff-unknown": "#ff0000",
|
||||
"markdown-heading": "#9d7cd8",
|
||||
"markdown-text": "#eeeeee",
|
||||
"markdown-link": "#fab283",
|
||||
"markdown-link-text": "#56b6c2",
|
||||
"markdown-code": "#7fd88f",
|
||||
"markdown-block-quote": "#e5c07b",
|
||||
"markdown-emph": "#e5c07b",
|
||||
"markdown-strong": "#f5a742",
|
||||
"markdown-horizontal-rule": "#808080",
|
||||
"markdown-list-item": "#fab283",
|
||||
"markdown-list-enumeration": "#56b6c2",
|
||||
"markdown-image": "#fab283",
|
||||
"markdown-image-text": "#56b6c2",
|
||||
"markdown-code-block": "#eeeeee",
|
||||
"border-color": "#ffffff",
|
||||
"border-weaker-base": "var(--smoke-dark-alpha-3)",
|
||||
"button-ghost-hover": "var(--smoke-dark-alpha-2)",
|
||||
"button-ghost-hover2": "var(--smoke-dark-alpha-3)",
|
||||
"avatar-background-pink": "#501b3f",
|
||||
"avatar-background-mint": "#033a34",
|
||||
"avatar-background-orange": "#5f2a06",
|
||||
"avatar-background-purple": "#432155",
|
||||
"avatar-background-cyan": "#0f3058",
|
||||
"avatar-background-lime": "#2b3711",
|
||||
"avatar-text-pink": "#e34ba9",
|
||||
"avatar-text-mint": "#95f3d9",
|
||||
"avatar-text-orange": "#ff802b",
|
||||
"avatar-text-purple": "#9d5bd2",
|
||||
"avatar-text-cyan": "#369eff",
|
||||
"avatar-text-lime": "#c4f042"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "OC-2",
|
||||
"id": "oc-2",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#8f8f8f",
|
||||
"primary": "#dcde8d",
|
||||
"success": "#12c905",
|
||||
@@ -13,258 +13,10 @@
|
||||
"interactive": "#034cff",
|
||||
"diffAdd": "#9ff29a",
|
||||
"diffDelete": "#fc533a"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f8f8f8",
|
||||
"background-weak": "#f3f3f3",
|
||||
"background-strong": "#fcfcfc",
|
||||
"background-stronger": "#fcfcfc",
|
||||
"surface-base": "#00000008",
|
||||
"base": "#00000008",
|
||||
"surface-base-hover": "#0000000f",
|
||||
"surface-base-active": "#0000000d",
|
||||
"surface-base-interactive-active": "var(--cobalt-light-alpha-3)",
|
||||
"base2": "#00000008",
|
||||
"base3": "#00000008",
|
||||
"surface-inset-base": "#00000008",
|
||||
"surface-inset-base-hover": "#0000000d",
|
||||
"surface-inset-strong": "#00000017",
|
||||
"surface-inset-strong-hover": "#00000017",
|
||||
"surface-raised-base": "#00000008",
|
||||
"surface-float-base": "#161616",
|
||||
"surface-float-base-hover": "#1c1c1c",
|
||||
"surface-raised-base-hover": "#0000000d",
|
||||
"surface-raised-base-active": "#00000017",
|
||||
"surface-raised-strong": "#fcfcfc",
|
||||
"surface-raised-strong-hover": "var(--white)",
|
||||
"surface-raised-stronger": "var(--white)",
|
||||
"surface-raised-stronger-hover": "var(--white)",
|
||||
"surface-weak": "#0000000d",
|
||||
"surface-weaker": "#00000012",
|
||||
"surface-strong": "#ffffff",
|
||||
"surface-raised-stronger-non-alpha": "var(--white)",
|
||||
"surface-brand-base": "var(--yuzu-light-9)",
|
||||
"surface-brand-hover": "var(--yuzu-light-10)",
|
||||
"surface-interactive-base": "var(--cobalt-light-3)",
|
||||
"surface-interactive-hover": "#E5F0FF",
|
||||
"surface-interactive-weak": "var(--cobalt-light-2)",
|
||||
"surface-interactive-weak-hover": "var(--cobalt-light-3)",
|
||||
"surface-success-base": "var(--apple-light-3)",
|
||||
"surface-success-weak": "var(--apple-light-2)",
|
||||
"surface-success-strong": "var(--apple-light-9)",
|
||||
"surface-warning-base": "var(--solaris-light-3)",
|
||||
"surface-warning-weak": "var(--solaris-light-2)",
|
||||
"surface-warning-strong": "var(--solaris-light-9)",
|
||||
"surface-critical-base": "var(--ember-light-3)",
|
||||
"surface-critical-weak": "var(--ember-light-2)",
|
||||
"surface-critical-strong": "var(--ember-light-9)",
|
||||
"surface-info-base": "var(--lilac-light-3)",
|
||||
"surface-info-weak": "var(--lilac-light-2)",
|
||||
"surface-info-strong": "var(--lilac-light-9)",
|
||||
"surface-diff-unchanged-base": "#ffffff00",
|
||||
"surface-diff-skip-base": "#f8f8f8",
|
||||
"surface-diff-hidden-base": "var(--blue-light-3)",
|
||||
"surface-diff-hidden-weak": "var(--blue-light-2)",
|
||||
"surface-diff-hidden-weaker": "var(--blue-light-1)",
|
||||
"surface-diff-hidden-strong": "var(--blue-light-5)",
|
||||
"surface-diff-hidden-stronger": "var(--blue-light-9)",
|
||||
"surface-diff-add-base": "#dafbe0",
|
||||
"surface-diff-add-weak": "var(--mint-light-2)",
|
||||
"surface-diff-add-weaker": "var(--mint-light-1)",
|
||||
"surface-diff-add-strong": "var(--mint-light-5)",
|
||||
"surface-diff-add-stronger": "var(--mint-light-9)",
|
||||
"surface-diff-delete-base": "var(--ember-light-3)",
|
||||
"surface-diff-delete-weak": "var(--ember-light-2)",
|
||||
"surface-diff-delete-weaker": "var(--ember-light-1)",
|
||||
"surface-diff-delete-strong": "var(--ember-light-6)",
|
||||
"surface-diff-delete-stronger": "var(--ember-light-9)",
|
||||
"input-base": "#fcfcfc",
|
||||
"input-hover": "#f8f8f8",
|
||||
"input-active": "var(--cobalt-light-1)",
|
||||
"input-selected": "var(--cobalt-light-4)",
|
||||
"input-focus": "var(--cobalt-light-1)",
|
||||
"input-disabled": "#ededed",
|
||||
"text-base": "#6f6f6f",
|
||||
"text-weak": "#8f8f8f",
|
||||
"text-weaker": "#c7c7c7",
|
||||
"text-strong": "#171717",
|
||||
"text-invert-base": "#ffffff96",
|
||||
"text-invert-weak": "#ffffff63",
|
||||
"text-invert-weaker": "#ffffff40",
|
||||
"text-invert-strong": "#ffffffeb",
|
||||
"text-interactive-base": "var(--cobalt-light-9)",
|
||||
"text-on-brand-base": "#0000008f",
|
||||
"text-on-interactive-base": "#fcfcfc",
|
||||
"text-on-interactive-weak": "#ffffff96",
|
||||
"text-on-success-base": "var(--apple-light-10)",
|
||||
"text-on-critical-base": "var(--ember-light-10)",
|
||||
"text-on-critical-weak": "var(--ember-light-8)",
|
||||
"text-on-critical-strong": "var(--ember-light-12)",
|
||||
"text-on-warning-base": "#ffffff96",
|
||||
"text-on-info-base": "#ffffff96",
|
||||
"text-diff-add-base": "var(--mint-light-11)",
|
||||
"text-diff-delete-base": "var(--ember-light-10)",
|
||||
"text-diff-delete-strong": "var(--ember-light-12)",
|
||||
"text-diff-add-strong": "var(--mint-light-12)",
|
||||
"text-on-info-weak": "#ffffff63",
|
||||
"text-on-info-strong": "#ffffffeb",
|
||||
"text-on-warning-weak": "#ffffff63",
|
||||
"text-on-warning-strong": "#ffffffeb",
|
||||
"text-on-success-weak": "var(--apple-light-6)",
|
||||
"text-on-success-strong": "var(--apple-light-12)",
|
||||
"text-on-brand-weak": "#00000070",
|
||||
"text-on-brand-weaker": "#00000038",
|
||||
"text-on-brand-strong": "#000000e8",
|
||||
"button-primary-base": "#171717",
|
||||
"button-secondary-base": "#fcfcfc",
|
||||
"button-secondary-hover": "FFFFFF0A",
|
||||
"border-base": "#00000024",
|
||||
"border-hover": "#00000038",
|
||||
"border-active": "#00000070",
|
||||
"border-selected": "var(--cobalt-light-alpha-9)",
|
||||
"border-disabled": "#00000038",
|
||||
"border-focus": "#00000070",
|
||||
"border-weak-base": "#e5e5e5",
|
||||
"border-strong-base": "#00000024",
|
||||
"border-strong-hover": "#00000038",
|
||||
"border-strong-active": "#00000024",
|
||||
"border-strong-selected": "var(--cobalt-light-alpha-6)",
|
||||
"border-strong-disabled": "#0000001c",
|
||||
"border-strong-focus": "#00000024",
|
||||
"border-weak-hover": "#0000001c",
|
||||
"border-weak-active": "#00000024",
|
||||
"border-weak-selected": "var(--cobalt-light-alpha-5)",
|
||||
"border-weak-disabled": "#0000001c",
|
||||
"border-weak-focus": "#00000024",
|
||||
"border-interactive-base": "var(--cobalt-light-7)",
|
||||
"border-interactive-hover": "var(--cobalt-light-8)",
|
||||
"border-interactive-active": "var(--cobalt-light-9)",
|
||||
"border-interactive-selected": "var(--cobalt-light-9)",
|
||||
"border-interactive-disabled": "#c7c7c7",
|
||||
"border-interactive-focus": "var(--cobalt-light-9)",
|
||||
"border-success-base": "var(--apple-light-6)",
|
||||
"border-success-hover": "var(--apple-light-7)",
|
||||
"border-success-selected": "var(--apple-light-9)",
|
||||
"border-warning-base": "var(--solaris-light-6)",
|
||||
"border-warning-hover": "var(--solaris-light-7)",
|
||||
"border-warning-selected": "var(--solaris-light-9)",
|
||||
"border-critical-base": "var(--ember-light-6)",
|
||||
"border-critical-hover": "var(--ember-light-7)",
|
||||
"border-critical-selected": "var(--ember-light-9)",
|
||||
"border-info-base": "var(--lilac-light-6)",
|
||||
"border-info-hover": "var(--lilac-light-7)",
|
||||
"border-info-selected": "var(--lilac-light-9)",
|
||||
"icon-base": "#8f8f8f",
|
||||
"icon-hover": "#6f6f6f",
|
||||
"icon-active": "#171717",
|
||||
"icon-selected": "#171717",
|
||||
"icon-disabled": "#c7c7c7",
|
||||
"icon-focus": "#171717",
|
||||
"icon-invert-base": "#ffffff",
|
||||
"icon-weak-base": "#dbdbdb",
|
||||
"icon-weak-hover": "#c7c7c7",
|
||||
"icon-weak-active": "#8f8f8f",
|
||||
"icon-weak-selected": "#858585",
|
||||
"icon-weak-disabled": "#e2e2e2",
|
||||
"icon-weak-focus": "#8f8f8f",
|
||||
"icon-strong-base": "#171717",
|
||||
"icon-strong-hover": "#151515",
|
||||
"icon-strong-active": "#020202",
|
||||
"icon-strong-selected": "#020202",
|
||||
"icon-strong-disabled": "#e2e2e2",
|
||||
"icon-strong-focus": "#020202",
|
||||
"icon-brand-base": "#171717",
|
||||
"icon-interactive-base": "var(--cobalt-light-9)",
|
||||
"icon-success-base": "var(--apple-light-7)",
|
||||
"icon-success-hover": "var(--apple-light-8)",
|
||||
"icon-success-active": "var(--apple-light-11)",
|
||||
"icon-warning-base": "var(--amber-light-7)",
|
||||
"icon-warning-hover": "var(--amber-light-8)",
|
||||
"icon-warning-active": "var(--amber-light-11)",
|
||||
"icon-critical-base": "var(--ember-light-10)",
|
||||
"icon-critical-hover": "var(--ember-light-11)",
|
||||
"icon-critical-active": "var(--ember-light-12)",
|
||||
"icon-info-base": "var(--lilac-light-7)",
|
||||
"icon-info-hover": "var(--lilac-light-8)",
|
||||
"icon-info-active": "var(--lilac-light-11)",
|
||||
"icon-on-brand-base": "#0000008f",
|
||||
"icon-on-brand-hover": "#000000e8",
|
||||
"icon-on-brand-selected": "#000000e8",
|
||||
"icon-on-interactive-base": "#fcfcfc",
|
||||
"icon-agent-plan-base": "var(--purple-light-9)",
|
||||
"icon-agent-docs-base": "var(--amber-light-9)",
|
||||
"icon-agent-ask-base": "var(--cyan-light-9)",
|
||||
"icon-agent-build-base": "var(--cobalt-light-9)",
|
||||
"icon-on-success-base": "var(--apple-light-alpha-9)",
|
||||
"icon-on-success-hover": "var(--apple-light-alpha-10)",
|
||||
"icon-on-success-selected": "var(--apple-light-alpha-11)",
|
||||
"icon-on-warning-base": "var(--amber-lightalpha-9)",
|
||||
"icon-on-warning-hover": "var(--amber-lightalpha-10)",
|
||||
"icon-on-warning-selected": "var(--amber-lightalpha-11)",
|
||||
"icon-on-critical-base": "var(--ember-light-alpha-9)",
|
||||
"icon-on-critical-hover": "var(--ember-light-alpha-10)",
|
||||
"icon-on-critical-selected": "var(--ember-light-alpha-11)",
|
||||
"icon-on-info-base": "var(--lilac-light-9)",
|
||||
"icon-on-info-hover": "var(--lilac-light-alpha-10)",
|
||||
"icon-on-info-selected": "var(--lilac-light-alpha-11)",
|
||||
"icon-diff-add-base": "var(--mint-light-11)",
|
||||
"icon-diff-add-hover": "var(--mint-light-12)",
|
||||
"icon-diff-add-active": "var(--mint-light-12)",
|
||||
"icon-diff-delete-base": "var(--ember-light-10)",
|
||||
"icon-diff-delete-hover": "var(--ember-light-11)",
|
||||
"syntax-comment": "var(--text-weak)",
|
||||
"syntax-regexp": "var(--text-base)",
|
||||
"syntax-string": "#006656",
|
||||
"syntax-keyword": "var(--text-weak)",
|
||||
"syntax-primitive": "#fb4804",
|
||||
"syntax-operator": "var(--text-base)",
|
||||
"syntax-variable": "var(--text-strong)",
|
||||
"syntax-property": "#ed6dc8",
|
||||
"syntax-type": "#596600",
|
||||
"syntax-constant": "#007b80",
|
||||
"syntax-punctuation": "var(--text-base)",
|
||||
"syntax-object": "var(--text-strong)",
|
||||
"syntax-success": "var(--apple-light-10)",
|
||||
"syntax-warning": "var(--amber-light-10)",
|
||||
"syntax-critical": "var(--ember-light-10)",
|
||||
"syntax-info": "#0092a8",
|
||||
"syntax-diff-add": "var(--mint-light-11)",
|
||||
"syntax-diff-delete": "var(--ember-light-11)",
|
||||
"syntax-diff-unknown": "#ff0000",
|
||||
"markdown-heading": "#d68c27",
|
||||
"markdown-text": "#1a1a1a",
|
||||
"markdown-link": "#3b7dd8",
|
||||
"markdown-link-text": "#318795",
|
||||
"markdown-code": "#3d9a57",
|
||||
"markdown-block-quote": "#b0851f",
|
||||
"markdown-emph": "#b0851f",
|
||||
"markdown-strong": "#d68c27",
|
||||
"markdown-horizontal-rule": "#8a8a8a",
|
||||
"markdown-list-item": "#3b7dd8",
|
||||
"markdown-list-enumeration": "#318795",
|
||||
"markdown-image": "#3b7dd8",
|
||||
"markdown-image-text": "#318795",
|
||||
"markdown-code-block": "#1a1a1a",
|
||||
"border-color": "#ffffff",
|
||||
"border-weaker-base": "#efefef",
|
||||
"button-ghost-hover": "#00000008",
|
||||
"button-ghost-hover2": "#0000000d",
|
||||
"avatar-background-pink": "#feeef8",
|
||||
"avatar-background-mint": "#e1fbf4",
|
||||
"avatar-background-orange": "#fff1e7",
|
||||
"avatar-background-purple": "#f9f1fe",
|
||||
"avatar-background-cyan": "#e7f9fb",
|
||||
"avatar-background-lime": "#eefadc",
|
||||
"avatar-text-pink": "#cd1d8d",
|
||||
"avatar-text-mint": "#147d6f",
|
||||
"avatar-text-orange": "#ed5f00",
|
||||
"avatar-text-purple": "#8445bc",
|
||||
"avatar-text-cyan": "#0894b3",
|
||||
"avatar-text-lime": "#5d770d"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#707070",
|
||||
"primary": "#fab283",
|
||||
"success": "#12c905",
|
||||
@@ -274,249 +26,6 @@
|
||||
"interactive": "#034cff",
|
||||
"diffAdd": "#c8ffc4",
|
||||
"diffDelete": "#fc533a"
|
||||
},
|
||||
"overrides": {
|
||||
"base": "#ffffff08",
|
||||
"base2": "#ffffff08",
|
||||
"base3": "#ffffff08",
|
||||
"background-base": "#101010",
|
||||
"background-weak": "#1E1E1E",
|
||||
"background-strong": "#121212",
|
||||
"background-stronger": "#151515",
|
||||
"surface-base": "#ffffff08",
|
||||
"surface-base-hover": "#FFFFFF0A",
|
||||
"surface-base-active": "#ffffff0f",
|
||||
"surface-base-interactive-active": "var(--cobalt-dark-alpha-2)",
|
||||
"surface-inset-base": "#0000007f",
|
||||
"surface-inset-base-hover": "#0000007f",
|
||||
"surface-inset-strong": "#000000cc",
|
||||
"surface-inset-strong-hover": "#000000cc",
|
||||
"surface-raised-base": "#ffffff0f",
|
||||
"surface-float-base": "#161616",
|
||||
"surface-float-base-hover": "#1c1c1c",
|
||||
"surface-raised-base-hover": "#ffffff14",
|
||||
"surface-raised-base-active": "#ffffff1a",
|
||||
"surface-raised-strong": "#ffffff14",
|
||||
"surface-raised-strong-hover": "#ffffff21",
|
||||
"surface-raised-stronger": "#ffffff21",
|
||||
"surface-raised-stronger-hover": "#ffffff2b",
|
||||
"surface-weak": "#ffffff14",
|
||||
"surface-weaker": "#ffffff1a",
|
||||
"surface-strong": "#ffffff2b",
|
||||
"surface-raised-stronger-non-alpha": "#1B1B1B",
|
||||
"surface-brand-base": "var(--yuzu-light-9)",
|
||||
"surface-brand-hover": "var(--yuzu-light-10)",
|
||||
"surface-interactive-base": "var(--cobalt-dark-3)",
|
||||
"surface-interactive-hover": "#0A1D4D",
|
||||
"surface-interactive-weak": "var(--cobalt-dark-2)",
|
||||
"surface-interactive-weak-hover": "var(--cobalt-light-3)",
|
||||
"surface-success-base": "var(--apple-dark-3)",
|
||||
"surface-success-weak": "var(--apple-dark-2)",
|
||||
"surface-success-strong": "var(--apple-dark-9)",
|
||||
"surface-warning-base": "var(--solaris-light-3)",
|
||||
"surface-warning-weak": "var(--solaris-light-2)",
|
||||
"surface-warning-strong": "var(--solaris-light-9)",
|
||||
"surface-critical-base": "var(--ember-dark-3)",
|
||||
"surface-critical-weak": "var(--ember-dark-2)",
|
||||
"surface-critical-strong": "var(--ember-dark-9)",
|
||||
"surface-info-base": "var(--lilac-light-3)",
|
||||
"surface-info-weak": "var(--lilac-light-2)",
|
||||
"surface-info-strong": "var(--lilac-light-9)",
|
||||
"surface-diff-unchanged-base": "#161616",
|
||||
"surface-diff-skip-base": "#00000000",
|
||||
"surface-diff-hidden-base": "var(--blue-dark-2)",
|
||||
"surface-diff-hidden-weak": "var(--blue-dark-1)",
|
||||
"surface-diff-hidden-weaker": "var(--blue-dark-3)",
|
||||
"surface-diff-hidden-strong": "var(--blue-dark-5)",
|
||||
"surface-diff-hidden-stronger": "var(--blue-dark-11)",
|
||||
"surface-diff-add-base": "var(--mint-dark-3)",
|
||||
"surface-diff-add-weak": "var(--mint-dark-4)",
|
||||
"surface-diff-add-weaker": "var(--mint-dark-3)",
|
||||
"surface-diff-add-strong": "var(--mint-dark-5)",
|
||||
"surface-diff-add-stronger": "var(--mint-dark-11)",
|
||||
"surface-diff-delete-base": "var(--ember-dark-3)",
|
||||
"surface-diff-delete-weak": "var(--ember-dark-4)",
|
||||
"surface-diff-delete-weaker": "var(--ember-dark-3)",
|
||||
"surface-diff-delete-strong": "var(--ember-dark-5)",
|
||||
"surface-diff-delete-stronger": "var(--ember-dark-11)",
|
||||
"input-base": "#1c1c1c",
|
||||
"input-hover": "#1c1c1c",
|
||||
"input-active": "var(--cobalt-dark-1)",
|
||||
"input-selected": "var(--cobalt-dark-2)",
|
||||
"input-focus": "var(--cobalt-dark-1)",
|
||||
"input-disabled": "#282828",
|
||||
"text-base": "#ffffff96",
|
||||
"text-weak": "#ffffff63",
|
||||
"text-weaker": "#ffffff40",
|
||||
"text-strong": "#ffffffeb",
|
||||
"text-invert-base": "#ffffff96",
|
||||
"text-invert-weak": "#ffffff63",
|
||||
"text-invert-weaker": "#ffffff40",
|
||||
"text-invert-strong": "#ffffffeb",
|
||||
"text-interactive-base": "var(--cobalt-dark-11)",
|
||||
"text-on-brand-base": "#ffffff96",
|
||||
"text-on-interactive-base": "#ededed",
|
||||
"text-on-interactive-weak": "#ffffff96",
|
||||
"text-on-success-base": "var(--apple-dark-9)",
|
||||
"text-on-critical-base": "var(--ember-dark-9)",
|
||||
"text-on-critical-weak": "var(--ember-dark-8)",
|
||||
"text-on-critical-strong": "var(--ember-dark-12)",
|
||||
"text-on-warning-base": "#ffffff96",
|
||||
"text-on-info-base": "#ffffff96",
|
||||
"text-diff-add-base": "var(--mint-dark-11)",
|
||||
"text-diff-delete-base": "var(--ember-dark-9)",
|
||||
"text-diff-delete-strong": "var(--ember-dark-12)",
|
||||
"text-diff-add-strong": "var(--mint-dark-8)",
|
||||
"text-on-info-weak": "#ffffff63",
|
||||
"text-on-info-strong": "#ffffffeb",
|
||||
"text-on-warning-weak": "#ffffff63",
|
||||
"text-on-warning-strong": "#ffffffeb",
|
||||
"text-on-success-weak": "var(--apple-dark-8)",
|
||||
"text-on-success-strong": "var(--apple-dark-12)",
|
||||
"text-on-brand-weak": "#ffffff63",
|
||||
"text-on-brand-weaker": "#ffffff40",
|
||||
"text-on-brand-strong": "#ffffffeb",
|
||||
"button-primary-base": "#ededed",
|
||||
"button-secondary-base": "#1c1c1c",
|
||||
"button-secondary-hover": "#FFFFFF0A",
|
||||
"border-base": "#ffffff2b",
|
||||
"border-hover": "#ffffff40",
|
||||
"border-active": "#ffffff63",
|
||||
"border-selected": "var(--cobalt-dark-alpha-11)",
|
||||
"border-disabled": "#ffffff40",
|
||||
"border-focus": "#ffffff63",
|
||||
"border-weak-base": "#282828",
|
||||
"border-weak-hover": "#ffffff2b",
|
||||
"border-weak-active": "#ffffff40",
|
||||
"border-weak-selected": "var(--cobalt-dark-alpha-6)",
|
||||
"border-weak-disabled": "#ffffff21",
|
||||
"border-weak-focus": "#ffffff40",
|
||||
"border-strong-base": "#ffffff40",
|
||||
"border-interactive-base": "var(--cobalt-light-7)",
|
||||
"border-interactive-hover": "var(--cobalt-light-8)",
|
||||
"border-interactive-active": "var(--cobalt-light-9)",
|
||||
"border-interactive-selected": "var(--cobalt-light-9)",
|
||||
"border-interactive-disabled": "#c7c7c7",
|
||||
"border-interactive-focus": "var(--cobalt-light-9)",
|
||||
"border-success-base": "var(--apple-light-6)",
|
||||
"border-success-hover": "var(--apple-light-7)",
|
||||
"border-success-selected": "var(--apple-light-9)",
|
||||
"border-warning-base": "var(--solaris-light-6)",
|
||||
"border-warning-hover": "var(--solaris-light-7)",
|
||||
"border-warning-selected": "var(--solaris-light-9)",
|
||||
"border-critical-base": "var(--ember-dark-5)",
|
||||
"border-critical-hover": "var(--ember-dark-7)",
|
||||
"border-critical-selected": "var(--ember-dark-9)",
|
||||
"border-info-base": "var(--lilac-light-6)",
|
||||
"border-info-hover": "var(--lilac-light-7)",
|
||||
"border-info-selected": "var(--lilac-light-9)",
|
||||
"icon-base": "#7e7e7e",
|
||||
"icon-hover": "#a0a0a0",
|
||||
"icon-active": "#ededed",
|
||||
"icon-selected": "#ededed",
|
||||
"icon-disabled": "#505050",
|
||||
"icon-focus": "#ededed",
|
||||
"icon-invert-base": "#161616",
|
||||
"icon-weak-base": "#343434",
|
||||
"icon-weak-hover": "#dbdbdb",
|
||||
"icon-weak-active": "#c7c7c7",
|
||||
"icon-weak-selected": "#8f8f8f",
|
||||
"icon-weak-disabled": "#ededed",
|
||||
"icon-weak-focus": "#8f8f8f",
|
||||
"icon-strong-base": "#ededed",
|
||||
"icon-strong-hover": "#F3F3F3",
|
||||
"icon-strong-active": "#EBEBEB",
|
||||
"icon-strong-selected": "#FCFCFC",
|
||||
"icon-strong-disabled": "#3e3e3e",
|
||||
"icon-strong-focus": "#FCFCFC",
|
||||
"icon-brand-base": "var(--white)",
|
||||
"icon-interactive-base": "var(--cobalt-dark-11)",
|
||||
"icon-success-base": "var(--apple-dark-9)",
|
||||
"icon-success-hover": "var(--apple-dark-10)",
|
||||
"icon-success-active": "var(--apple-dark-11)",
|
||||
"icon-warning-base": "var(--amber-dark-9)",
|
||||
"icon-warning-hover": "var(--amber-dark-8)",
|
||||
"icon-warning-active": "var(--amber-dark-11)",
|
||||
"icon-critical-base": "var(--ember-dark-9)",
|
||||
"icon-critical-hover": "var(--ember-dark-11)",
|
||||
"icon-critical-active": "var(--ember-dark-12)",
|
||||
"icon-info-base": "var(--lilac-dark-7)",
|
||||
"icon-info-hover": "var(--lilac-dark-8)",
|
||||
"icon-info-active": "var(--lilac-dark-11)",
|
||||
"icon-on-brand-base": "#0000008f",
|
||||
"icon-on-brand-hover": "#000000e8",
|
||||
"icon-on-brand-selected": "#000000e8",
|
||||
"icon-on-interactive-base": "#ededed",
|
||||
"icon-agent-plan-base": "var(--purple-dark-9)",
|
||||
"icon-agent-docs-base": "var(--amber-dark-9)",
|
||||
"icon-agent-ask-base": "var(--cyan-dark-9)",
|
||||
"icon-agent-build-base": "var(--cobalt-dark-11)",
|
||||
"icon-on-success-base": "var(--apple-dark-alpha-9)",
|
||||
"icon-on-success-hover": "var(--apple-dark-alpha-10)",
|
||||
"icon-on-success-selected": "var(--apple-dark-alpha-11)",
|
||||
"icon-on-warning-base": "var(--amber-darkalpha-9)",
|
||||
"icon-on-warning-hover": "var(--amber-darkalpha-10)",
|
||||
"icon-on-warning-selected": "var(--amber-darkalpha-11)",
|
||||
"icon-on-critical-base": "var(--ember-dark-alpha-9)",
|
||||
"icon-on-critical-hover": "var(--ember-dark-alpha-10)",
|
||||
"icon-on-critical-selected": "var(--ember-dark-alpha-11)",
|
||||
"icon-on-info-base": "var(--lilac-dark-9)",
|
||||
"icon-on-info-hover": "var(--lilac-dark-alpha-10)",
|
||||
"icon-on-info-selected": "var(--lilac-dark-alpha-11)",
|
||||
"icon-diff-add-base": "var(--mint-dark-11)",
|
||||
"icon-diff-add-hover": "var(--mint-dark-10)",
|
||||
"icon-diff-add-active": "var(--mint-dark-11)",
|
||||
"icon-diff-delete-base": "var(--ember-dark-9)",
|
||||
"icon-diff-delete-hover": "var(--ember-dark-10)",
|
||||
"syntax-comment": "var(--text-weak)",
|
||||
"syntax-regexp": "var(--text-base)",
|
||||
"syntax-string": "#00ceb9",
|
||||
"syntax-keyword": "var(--text-weak)",
|
||||
"syntax-primitive": "#ffba92",
|
||||
"syntax-operator": "var(--text-weak)",
|
||||
"syntax-variable": "var(--text-strong)",
|
||||
"syntax-property": "#ff9ae2",
|
||||
"syntax-type": "#ecf58c",
|
||||
"syntax-constant": "#93e9f6",
|
||||
"syntax-punctuation": "var(--text-weak)",
|
||||
"syntax-object": "var(--text-strong)",
|
||||
"syntax-success": "var(--apple-dark-10)",
|
||||
"syntax-warning": "var(--amber-dark-10)",
|
||||
"syntax-critical": "var(--ember-dark-10)",
|
||||
"syntax-info": "#93e9f6",
|
||||
"syntax-diff-add": "var(--mint-dark-11)",
|
||||
"syntax-diff-delete": "var(--ember-dark-11)",
|
||||
"syntax-diff-unknown": "#ff0000",
|
||||
"markdown-heading": "#9d7cd8",
|
||||
"markdown-text": "#eeeeee",
|
||||
"markdown-link": "#fab283",
|
||||
"markdown-link-text": "#56b6c2",
|
||||
"markdown-code": "#7fd88f",
|
||||
"markdown-block-quote": "#e5c07b",
|
||||
"markdown-emph": "#e5c07b",
|
||||
"markdown-strong": "#f5a742",
|
||||
"markdown-horizontal-rule": "#808080",
|
||||
"markdown-list-item": "#fab283",
|
||||
"markdown-list-enumeration": "#56b6c2",
|
||||
"markdown-image": "#fab283",
|
||||
"markdown-image-text": "#56b6c2",
|
||||
"markdown-code-block": "#eeeeee",
|
||||
"border-color": "#ffffff",
|
||||
"border-weaker-base": "#1e1e1e",
|
||||
"button-ghost-hover": "#ffffff08",
|
||||
"button-ghost-hover2": "#ffffff0f",
|
||||
"avatar-background-pink": "#501b3f",
|
||||
"avatar-background-mint": "#033a34",
|
||||
"avatar-background-orange": "#5f2a06",
|
||||
"avatar-background-purple": "#432155",
|
||||
"avatar-background-cyan": "#0f3058",
|
||||
"avatar-background-lime": "#2b3711",
|
||||
"avatar-text-pink": "#e34ba9",
|
||||
"avatar-text-mint": "#95f3d9",
|
||||
"avatar-text-orange": "#ff802b",
|
||||
"avatar-text-purple": "#9d5bd2",
|
||||
"avatar-text-cyan": "#369eff",
|
||||
"avatar-text-lime": "#c4f042"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,39 @@
|
||||
"name": "One Dark Pro",
|
||||
"id": "onedarkpro",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#f5f6f8",
|
||||
"ink": "#2b303b",
|
||||
"primary": "#528bff",
|
||||
"accent": "#d85462",
|
||||
"success": "#4fa66d",
|
||||
"warning": "#d19a66",
|
||||
"error": "#e06c75",
|
||||
"info": "#61afef",
|
||||
"interactive": "#528bff",
|
||||
"diffAdd": "#c2ebcf",
|
||||
"diffDelete": "#f7c1c5"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f5f6f8",
|
||||
"background-weak": "#eef0f4",
|
||||
"background-strong": "#fafbfc",
|
||||
"background-stronger": "#ffffff",
|
||||
"border-weak-base": "#dee2eb",
|
||||
"border-weak-hover": "#d4d9e3",
|
||||
"border-weak-active": "#caced6",
|
||||
"border-weak-selected": "#bec4d0",
|
||||
"border-weak-disabled": "#f4f6fb",
|
||||
"border-weak-focus": "#c4cada",
|
||||
"border-base": "#b5bccd",
|
||||
"border-hover": "#aab1c2",
|
||||
"border-active": "#a0a7b8",
|
||||
"border-selected": "#959cae",
|
||||
"border-disabled": "#eceef4",
|
||||
"border-focus": "#a6adbf",
|
||||
"border-strong-base": "#747c92",
|
||||
"border-strong-hover": "#6a7287",
|
||||
"border-strong-active": "#60687c",
|
||||
"border-strong-selected": "#565e71",
|
||||
"border-strong-disabled": "#cbd0dd",
|
||||
"border-strong-focus": "#666d82",
|
||||
"surface-diff-add-base": "#e5f4ea",
|
||||
"surface-diff-delete-base": "#fde7ea",
|
||||
"surface-diff-hidden-base": "#e4e8f4",
|
||||
"text-base": "#2b303b",
|
||||
"text-weak": "#6b717f",
|
||||
"text-strong": "#0e1118",
|
||||
"syntax-string": "#4fa66d",
|
||||
"syntax-primitive": "#d85462",
|
||||
"syntax-property": "#528bff",
|
||||
"syntax-type": "#d19a66",
|
||||
"syntax-constant": "#61afef",
|
||||
"syntax-info": "#61afef",
|
||||
"markdown-heading": "#528bff",
|
||||
"markdown-text": "#2b303b",
|
||||
"markdown-link": "#528bff",
|
||||
"markdown-link-text": "#61afef",
|
||||
"markdown-code": "#4fa66d",
|
||||
"markdown-block-quote": "#d19a66",
|
||||
"markdown-emph": "#d19a66",
|
||||
"markdown-strong": "#d85462",
|
||||
"markdown-horizontal-rule": "#d3d7e4",
|
||||
"markdown-list-item": "#528bff",
|
||||
"markdown-list-enumeration": "#61afef",
|
||||
"markdown-image": "#528bff",
|
||||
"markdown-image-text": "#61afef",
|
||||
"markdown-code-block": "#528bff"
|
||||
"syntax-keyword": "#a626a4",
|
||||
"syntax-primitive": "#986801"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#1e222a",
|
||||
"ink": "#abb2bf",
|
||||
"primary": "#61afef",
|
||||
"accent": "#e06c75",
|
||||
"success": "#98c379",
|
||||
"warning": "#e5c07b",
|
||||
"error": "#e06c75",
|
||||
"info": "#56b6c2",
|
||||
"interactive": "#61afef",
|
||||
"diffAdd": "#4b815a",
|
||||
"diffDelete": "#b2555f"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#1e222a",
|
||||
"background-weak": "#212631",
|
||||
"background-strong": "#1b1f27",
|
||||
"background-stronger": "#171b23",
|
||||
"border-weak-base": "#323848",
|
||||
"border-weak-hover": "#363d52",
|
||||
"border-weak-active": "#3c435c",
|
||||
"border-weak-selected": "#424967",
|
||||
"border-weak-disabled": "#141720",
|
||||
"border-weak-focus": "#3f4560",
|
||||
"border-base": "#4a5164",
|
||||
"border-hover": "#515871",
|
||||
"border-active": "#585f7e",
|
||||
"border-selected": "#60688a",
|
||||
"border-disabled": "#1a1e27",
|
||||
"border-focus": "#555c79",
|
||||
"border-strong-base": "#6a7390",
|
||||
"border-strong-hover": "#737c9d",
|
||||
"border-strong-active": "#7d87ab",
|
||||
"border-strong-selected": "#8791b8",
|
||||
"border-strong-disabled": "#212533",
|
||||
"border-strong-focus": "#7680a2",
|
||||
"surface-diff-add-base": "#1c2a26",
|
||||
"surface-diff-delete-base": "#2a1c22",
|
||||
"surface-diff-hidden-base": "#232836",
|
||||
"text-base": "#abb2bf",
|
||||
"text-weak": "#818899",
|
||||
"text-strong": "#f6f7fb",
|
||||
"syntax-string": "#98c379",
|
||||
"syntax-primitive": "#e06c75",
|
||||
"syntax-property": "#61afef",
|
||||
"syntax-type": "#e5c07b",
|
||||
"syntax-constant": "#56b6c2",
|
||||
"syntax-info": "#56b6c2",
|
||||
"markdown-heading": "#61afef",
|
||||
"markdown-text": "#abb2bf",
|
||||
"markdown-link": "#61afef",
|
||||
"markdown-link-text": "#56b6c2",
|
||||
"markdown-code": "#98c379",
|
||||
"markdown-block-quote": "#e5c07b",
|
||||
"markdown-emph": "#e5c07b",
|
||||
"markdown-strong": "#e06c75",
|
||||
"markdown-horizontal-rule": "#2d3444",
|
||||
"markdown-list-item": "#61afef",
|
||||
"markdown-list-enumeration": "#56b6c2",
|
||||
"markdown-image": "#61afef",
|
||||
"markdown-image-text": "#56b6c2",
|
||||
"markdown-code-block": "#abb2bf"
|
||||
"syntax-keyword": "#c678dd",
|
||||
"syntax-primitive": "#d19a66"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,37 @@
|
||||
"name": "Shades of Purple",
|
||||
"id": "shadesofpurple",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#f7ebff",
|
||||
"ink": "#3b2c59",
|
||||
"primary": "#7a5af8",
|
||||
"accent": "#ff6bd5",
|
||||
"success": "#3dd598",
|
||||
"warning": "#f7c948",
|
||||
"error": "#ff6bd5",
|
||||
"info": "#62d4ff",
|
||||
"interactive": "#7a5af8",
|
||||
"diffAdd": "#c8f8da",
|
||||
"diffDelete": "#ffc3ef"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#f7ebff",
|
||||
"background-weak": "#f2e2ff",
|
||||
"background-strong": "#fbf2ff",
|
||||
"background-stronger": "#fff7ff",
|
||||
"border-weak-base": "#e5d3ff",
|
||||
"border-weak-hover": "#dac8f5",
|
||||
"border-weak-active": "#d1bdeb",
|
||||
"border-weak-selected": "#c6b3e1",
|
||||
"border-weak-disabled": "#fcf6ff",
|
||||
"border-weak-focus": "#ccb9e7",
|
||||
"border-base": "#baa4d5",
|
||||
"border-hover": "#b098cb",
|
||||
"border-active": "#a68dc2",
|
||||
"border-selected": "#9b82b8",
|
||||
"border-disabled": "#f1e7ff",
|
||||
"border-focus": "#a692c6",
|
||||
"border-strong-base": "#8769a9",
|
||||
"border-strong-hover": "#7b5c9d",
|
||||
"border-strong-active": "#704f91",
|
||||
"border-strong-selected": "#664587",
|
||||
"border-strong-disabled": "#d8c4f0",
|
||||
"border-strong-focus": "#755495",
|
||||
"surface-diff-add-base": "#edf8f1",
|
||||
"surface-diff-delete-base": "#ffe4f4",
|
||||
"surface-diff-hidden-base": "#e9e4ff",
|
||||
"text-base": "#3b2c59",
|
||||
"text-weak": "#6c568f",
|
||||
"text-strong": "#1c1033",
|
||||
"syntax-string": "#3dd598",
|
||||
"syntax-primitive": "#ff6bd5",
|
||||
"syntax-property": "#7a5af8",
|
||||
"syntax-type": "#f7c948",
|
||||
"syntax-constant": "#62d4ff",
|
||||
"syntax-info": "#62d4ff",
|
||||
"markdown-heading": "#7a5af8",
|
||||
"markdown-text": "#3b2c59",
|
||||
"markdown-link": "#7a5af8",
|
||||
"markdown-link-text": "#62d4ff",
|
||||
"markdown-code": "#3dd598",
|
||||
"markdown-block-quote": "#f7c948",
|
||||
"markdown-emph": "#f7c948",
|
||||
"markdown-strong": "#ff6bd5",
|
||||
"markdown-horizontal-rule": "#decbed",
|
||||
"markdown-list-item": "#7a5af8",
|
||||
"markdown-list-enumeration": "#62d4ff",
|
||||
"markdown-image": "#7a5af8",
|
||||
"markdown-image-text": "#62d4ff",
|
||||
"markdown-code-block": "#7a5af8"
|
||||
"syntax-keyword": "#ff6bd5"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#1a102b",
|
||||
"ink": "#f5f0ff",
|
||||
"primary": "#c792ff",
|
||||
"accent": "#ff7ac6",
|
||||
"success": "#7be0b0",
|
||||
"warning": "#ffd580",
|
||||
"error": "#ff7ac6",
|
||||
"info": "#7dd4ff",
|
||||
"interactive": "#c792ff",
|
||||
"diffAdd": "#53c39f",
|
||||
"diffDelete": "#d85aa0"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#1a102b",
|
||||
"background-weak": "#1f1434",
|
||||
"background-strong": "#1c122f",
|
||||
"background-stronger": "#170e26",
|
||||
"border-weak-base": "#352552",
|
||||
"border-weak-hover": "#3a2a5d",
|
||||
"border-weak-active": "#402f68",
|
||||
"border-weak-selected": "#463674",
|
||||
"border-weak-disabled": "#10091b",
|
||||
"border-weak-focus": "#3d2d65",
|
||||
"border-base": "#4d3a73",
|
||||
"border-hover": "#553f7f",
|
||||
"border-active": "#5d468c",
|
||||
"border-selected": "#654c99",
|
||||
"border-disabled": "#150d21",
|
||||
"border-focus": "#594283",
|
||||
"border-strong-base": "#7659b0",
|
||||
"border-strong-hover": "#8262be",
|
||||
"border-strong-active": "#8e6ccc",
|
||||
"border-strong-selected": "#9a77da",
|
||||
"border-strong-disabled": "#1c122c",
|
||||
"border-strong-focus": "#8666c4",
|
||||
"surface-diff-add-base": "#142c27",
|
||||
"surface-diff-delete-base": "#2d1424",
|
||||
"surface-diff-hidden-base": "#231737",
|
||||
"text-base": "#f5f0ff",
|
||||
"text-weak": "#c9b6ff",
|
||||
"text-strong": "#ffffff",
|
||||
"syntax-string": "#7be0b0",
|
||||
"syntax-primitive": "#ff7ac6",
|
||||
"syntax-property": "#c792ff",
|
||||
"syntax-type": "#ffd580",
|
||||
"syntax-constant": "#7dd4ff",
|
||||
"syntax-info": "#7dd4ff",
|
||||
"markdown-heading": "#c792ff",
|
||||
"markdown-text": "#f5f0ff",
|
||||
"markdown-link": "#c792ff",
|
||||
"markdown-link-text": "#7dd4ff",
|
||||
"markdown-code": "#7be0b0",
|
||||
"markdown-block-quote": "#ffd580",
|
||||
"markdown-emph": "#ffd580",
|
||||
"markdown-strong": "#ff7ac6",
|
||||
"markdown-horizontal-rule": "#2d1d41",
|
||||
"markdown-list-item": "#c792ff",
|
||||
"markdown-list-enumeration": "#7dd4ff",
|
||||
"markdown-image": "#c792ff",
|
||||
"markdown-image-text": "#7dd4ff",
|
||||
"markdown-code-block": "#f5f0ff"
|
||||
"syntax-keyword": "#ff7ac6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,39 @@
|
||||
"name": "Solarized",
|
||||
"id": "solarized",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#fdf6e3",
|
||||
"ink": "#586e75",
|
||||
"primary": "#268bd2",
|
||||
"accent": "#d33682",
|
||||
"success": "#859900",
|
||||
"warning": "#b58900",
|
||||
"error": "#dc322f",
|
||||
"info": "#2aa198",
|
||||
"interactive": "#268bd2",
|
||||
"diffAdd": "#c6dc7a",
|
||||
"diffDelete": "#f2a1a1"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#fdf6e3",
|
||||
"background-weak": "#f6efda",
|
||||
"background-strong": "#faf3dc",
|
||||
"background-stronger": "#f6edd4",
|
||||
"border-weak-base": "#e3e0cd",
|
||||
"border-weak-hover": "#d9d4c2",
|
||||
"border-weak-active": "#cfcab7",
|
||||
"border-weak-selected": "#c5c0ad",
|
||||
"border-weak-disabled": "#f2edda",
|
||||
"border-weak-focus": "#cbc6b2",
|
||||
"border-base": "#bcb5a0",
|
||||
"border-hover": "#b1aa96",
|
||||
"border-active": "#a59f8c",
|
||||
"border-selected": "#999382",
|
||||
"border-disabled": "#ede7d4",
|
||||
"border-focus": "#aca58f",
|
||||
"border-strong-base": "#8c8572",
|
||||
"border-strong-hover": "#7f7866",
|
||||
"border-strong-active": "#716b5b",
|
||||
"border-strong-selected": "#645f50",
|
||||
"border-strong-disabled": "#d5cdb8",
|
||||
"border-strong-focus": "#78715f",
|
||||
"surface-diff-add-base": "#eef5d6",
|
||||
"surface-diff-delete-base": "#fde4dd",
|
||||
"surface-diff-hidden-base": "#e3ecf3",
|
||||
"text-base": "#586e75",
|
||||
"text-weak": "#7a8c8e",
|
||||
"text-strong": "#073642",
|
||||
"syntax-string": "#859900",
|
||||
"syntax-primitive": "#d33682",
|
||||
"syntax-property": "#268bd2",
|
||||
"syntax-type": "#b58900",
|
||||
"syntax-constant": "#2aa198",
|
||||
"syntax-info": "#2aa198",
|
||||
"markdown-heading": "#268bd2",
|
||||
"markdown-text": "#586e75",
|
||||
"markdown-link": "#268bd2",
|
||||
"markdown-link-text": "#2aa198",
|
||||
"markdown-code": "#859900",
|
||||
"markdown-block-quote": "#b58900",
|
||||
"markdown-emph": "#b58900",
|
||||
"markdown-strong": "#d33682",
|
||||
"markdown-horizontal-rule": "#cfd1bf",
|
||||
"markdown-list-item": "#268bd2",
|
||||
"markdown-list-enumeration": "#2aa198",
|
||||
"markdown-image": "#268bd2",
|
||||
"markdown-image-text": "#2aa198",
|
||||
"markdown-code-block": "#2aa198"
|
||||
"syntax-keyword": "#859900",
|
||||
"syntax-string": "#2aa198"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#002b36",
|
||||
"ink": "#93a1a1",
|
||||
"primary": "#6c71c4",
|
||||
"accent": "#d33682",
|
||||
"success": "#859900",
|
||||
"warning": "#b58900",
|
||||
"error": "#dc322f",
|
||||
"info": "#2aa198",
|
||||
"interactive": "#6c71c4",
|
||||
"diffAdd": "#4c7654",
|
||||
"diffDelete": "#c34b4b"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#001f27",
|
||||
"background-weak": "#022733",
|
||||
"background-strong": "#01222b",
|
||||
"background-stronger": "#032830",
|
||||
"border-weak-base": "#20373f",
|
||||
"border-weak-hover": "#243e47",
|
||||
"border-weak-active": "#28434f",
|
||||
"border-weak-selected": "#2d4958",
|
||||
"border-weak-disabled": "#0f2026",
|
||||
"border-weak-focus": "#2a4552",
|
||||
"border-base": "#31505b",
|
||||
"border-hover": "#365765",
|
||||
"border-active": "#3c5e70",
|
||||
"border-selected": "#42657a",
|
||||
"border-disabled": "#13272e",
|
||||
"border-focus": "#3a5a6b",
|
||||
"border-strong-base": "#4a7887",
|
||||
"border-strong-hover": "#528294",
|
||||
"border-strong-active": "#5a8ca1",
|
||||
"border-strong-selected": "#6396ae",
|
||||
"border-strong-disabled": "#1b323b",
|
||||
"border-strong-focus": "#56879a",
|
||||
"surface-diff-add-base": "#0f2f29",
|
||||
"surface-diff-delete-base": "#321c1c",
|
||||
"surface-diff-hidden-base": "#0f3844",
|
||||
"text-base": "#93a1a1",
|
||||
"text-weak": "#6c7f80",
|
||||
"text-strong": "#fdf6e3",
|
||||
"syntax-string": "#859900",
|
||||
"syntax-primitive": "#d33682",
|
||||
"syntax-property": "#6c71c4",
|
||||
"syntax-type": "#b58900",
|
||||
"syntax-constant": "#2aa198",
|
||||
"syntax-info": "#2aa198",
|
||||
"markdown-heading": "#6c71c4",
|
||||
"markdown-text": "#93a1a1",
|
||||
"markdown-link": "#6c71c4",
|
||||
"markdown-link-text": "#2aa198",
|
||||
"markdown-code": "#859900",
|
||||
"markdown-block-quote": "#b58900",
|
||||
"markdown-emph": "#b58900",
|
||||
"markdown-strong": "#d33682",
|
||||
"markdown-horizontal-rule": "#0e3b46",
|
||||
"markdown-list-item": "#6c71c4",
|
||||
"markdown-list-enumeration": "#2aa198",
|
||||
"markdown-image": "#6c71c4",
|
||||
"markdown-image-text": "#2aa198",
|
||||
"markdown-code-block": "#93a1a1"
|
||||
"syntax-keyword": "#859900",
|
||||
"syntax-string": "#2aa198"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,153 +3,37 @@
|
||||
"name": "Tokyonight",
|
||||
"id": "tokyonight",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#e1e2e7",
|
||||
"ink": "#273153",
|
||||
"primary": "#2e7de9",
|
||||
"accent": "#b15c00",
|
||||
"success": "#587539",
|
||||
"warning": "#8c6c3e",
|
||||
"error": "#c94060",
|
||||
"info": "#007197",
|
||||
"interactive": "#2e7de9",
|
||||
"diffAdd": "#4f8f7b",
|
||||
"diffDelete": "#d05f7c"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#e1e2e7",
|
||||
"background-weak": "#dee0ea",
|
||||
"background-strong": "#e5e6ee",
|
||||
"background-stronger": "#e9eaf1",
|
||||
"border-weak-base": "#cdd0dc",
|
||||
"border-weak-hover": "#c3c6d2",
|
||||
"border-weak-active": "#b9bcc8",
|
||||
"border-weak-selected": "#aeb2bf",
|
||||
"border-weak-disabled": "#e6e7ef",
|
||||
"border-weak-focus": "#b3b6c3",
|
||||
"border-base": "#a7abbb",
|
||||
"border-hover": "#9ba0b1",
|
||||
"border-active": "#9095a8",
|
||||
"border-selected": "#83889e",
|
||||
"border-disabled": "#dedfe6",
|
||||
"border-focus": "#9599a8",
|
||||
"border-strong-base": "#757b90",
|
||||
"border-strong-hover": "#6a7084",
|
||||
"border-strong-active": "#5f6578",
|
||||
"border-strong-selected": "#545a6d",
|
||||
"border-strong-disabled": "#c4c6d0",
|
||||
"border-strong-focus": "#666b7f",
|
||||
"surface-diff-add-base": "#dfe7da",
|
||||
"surface-diff-delete-base": "#f4dadd",
|
||||
"surface-diff-hidden-base": "#cfd1dd",
|
||||
"text-base": "#273153",
|
||||
"text-weak": "#5c6390",
|
||||
"text-strong": "#1c2544",
|
||||
"syntax-string": "#587539",
|
||||
"syntax-primitive": "#b15c00",
|
||||
"syntax-property": "#9854f1",
|
||||
"syntax-type": "#3760bf",
|
||||
"syntax-constant": "#007197",
|
||||
"syntax-info": "#007197",
|
||||
"markdown-heading": "#9854f1",
|
||||
"markdown-text": "#273153",
|
||||
"markdown-link": "#2e7de9",
|
||||
"markdown-link-text": "#007197",
|
||||
"markdown-code": "#587539",
|
||||
"markdown-block-quote": "#8c6c3e",
|
||||
"markdown-emph": "#8c6c3e",
|
||||
"markdown-strong": "#b15c00",
|
||||
"markdown-horizontal-rule": "#a1a6c5",
|
||||
"markdown-list-item": "#2e7de9",
|
||||
"markdown-list-enumeration": "#007197",
|
||||
"markdown-image": "#2e7de9",
|
||||
"markdown-image-text": "#007197",
|
||||
"markdown-code-block": "#3760bf"
|
||||
"syntax-keyword": "#9854f1"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#1a1b26",
|
||||
"ink": "#c0caf5",
|
||||
"primary": "#7aa2f7",
|
||||
"accent": "#ff9e64",
|
||||
"success": "#9ece6a",
|
||||
"warning": "#e0af68",
|
||||
"error": "#f7768e",
|
||||
"info": "#7dcfff",
|
||||
"interactive": "#7aa2f7",
|
||||
"diffAdd": "#41a6b5",
|
||||
"diffDelete": "#c34043"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#0f111a",
|
||||
"background-weak": "#111428",
|
||||
"background-strong": "#101324",
|
||||
"background-stronger": "#13172a",
|
||||
"border-weak-base": "#25283b",
|
||||
"border-weak-hover": "#292c43",
|
||||
"border-weak-active": "#2e314b",
|
||||
"border-weak-selected": "#343755",
|
||||
"border-weak-disabled": "#151727",
|
||||
"border-weak-focus": "#30324f",
|
||||
"border-base": "#3a3e57",
|
||||
"border-hover": "#414264",
|
||||
"border-active": "#474972",
|
||||
"border-selected": "#4f507f",
|
||||
"border-disabled": "#1c1d2d",
|
||||
"border-focus": "#45496f",
|
||||
"border-strong-base": "#5a5f82",
|
||||
"border-strong-hover": "#646994",
|
||||
"border-strong-active": "#6f74a6",
|
||||
"border-strong-selected": "#7a7fb8",
|
||||
"border-strong-disabled": "#23243a",
|
||||
"border-strong-focus": "#6a6f9f",
|
||||
"surface-base": "#1f2335",
|
||||
"base": "#1f2335",
|
||||
"surface-base-hover": "#232840",
|
||||
"surface-base-active": "#262c46",
|
||||
"surface-base-interactive-active": "#2b3357",
|
||||
"base2": "#1f2335",
|
||||
"base3": "#1f2335",
|
||||
"surface-inset-base": "#161a2ab3",
|
||||
"surface-inset-base-hover": "#161a2acc",
|
||||
"surface-inset-strong": "#0d111fcc",
|
||||
"surface-inset-strong-hover": "#0d111fcc",
|
||||
"surface-raised-base": "#242a42",
|
||||
"surface-float-base": "#242b45",
|
||||
"surface-float-base-hover": "#2a3154",
|
||||
"surface-raised-base-hover": "#272e49",
|
||||
"surface-raised-base-active": "#2c3353",
|
||||
"surface-raised-strong": "#31385a",
|
||||
"surface-raised-strong-hover": "#373f6b",
|
||||
"surface-raised-stronger": "#3b4261",
|
||||
"surface-raised-stronger-hover": "#444c82",
|
||||
"surface-weak": "#1b2033",
|
||||
"surface-weaker": "#181d2d",
|
||||
"surface-strong": "#323858",
|
||||
"surface-raised-stronger-non-alpha": "#2b3150",
|
||||
"surface-diff-add-base": "#1c2a38",
|
||||
"surface-diff-delete-base": "#2a1f32",
|
||||
"surface-diff-hidden-base": "#24283b",
|
||||
"text-base": "#c0caf5",
|
||||
"text-weak": "#7a88cf",
|
||||
"text-strong": "#eaeaff",
|
||||
"syntax-string": "#9ece6a",
|
||||
"syntax-primitive": "#ff9e64",
|
||||
"syntax-property": "#bb9af7",
|
||||
"syntax-type": "#e0af68",
|
||||
"syntax-constant": "#7dcfff",
|
||||
"syntax-info": "#7dcfff",
|
||||
"markdown-heading": "#bb9af7",
|
||||
"markdown-text": "#c0caf5",
|
||||
"markdown-link": "#7aa2f7",
|
||||
"markdown-link-text": "#7dcfff",
|
||||
"markdown-code": "#9ece6a",
|
||||
"markdown-block-quote": "#e0af68",
|
||||
"markdown-emph": "#e0af68",
|
||||
"markdown-strong": "#ff9e64",
|
||||
"markdown-horizontal-rule": "#3b4261",
|
||||
"markdown-list-item": "#7aa2f7",
|
||||
"markdown-list-enumeration": "#7dcfff",
|
||||
"markdown-image": "#7aa2f7",
|
||||
"markdown-image-text": "#7dcfff",
|
||||
"markdown-code-block": "#c0caf5"
|
||||
"syntax-keyword": "#bb9af7"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,129 +3,38 @@
|
||||
"name": "Vesper",
|
||||
"id": "vesper",
|
||||
"light": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#F0F0F0",
|
||||
"ink": "#101010",
|
||||
"primary": "#FFC799",
|
||||
"accent": "#B30000",
|
||||
"success": "#99FFE4",
|
||||
"warning": "#FFC799",
|
||||
"error": "#FF8080",
|
||||
"info": "#FFC799",
|
||||
"interactive": "#FFC799",
|
||||
"diffAdd": "#99FFE4",
|
||||
"diffDelete": "#FF8080"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#FFF",
|
||||
"background-weak": "#F8F8F8",
|
||||
"background-strong": "#F0F0F0",
|
||||
"background-stronger": "#FBFBFB",
|
||||
"border-weak-hover": "#E0E0E0",
|
||||
"border-weak-active": "#D8D8D8",
|
||||
"border-weak-selected": "#D0D0D0",
|
||||
"border-weak-disabled": "#F0F0F0",
|
||||
"border-weak-focus": "#D8D8D8",
|
||||
"border-base": "#D0D0D0",
|
||||
"border-hover": "#C8C8C8",
|
||||
"border-active": "#C0C0C0",
|
||||
"border-selected": "#B8B8B8",
|
||||
"border-disabled": "#E8E8E8",
|
||||
"border-focus": "#C0C0C0",
|
||||
"border-strong-base": "#A0A0A0",
|
||||
"border-strong-hover": "#989898",
|
||||
"border-strong-active": "#909090",
|
||||
"border-strong-selected": "#888888",
|
||||
"border-strong-disabled": "#D0D0D0",
|
||||
"border-strong-focus": "#909090",
|
||||
"surface-diff-add-base": "#e8f5e8",
|
||||
"surface-diff-delete-base": "#f5e8e8",
|
||||
"surface-diff-hidden-base": "#F0F0F0",
|
||||
"text-base": "#101010",
|
||||
"text-invert-strong": "var(--smoke-dark-alpha-12)",
|
||||
"text-weak": "#606060",
|
||||
"text-strong": "#000000",
|
||||
"syntax-string": "#0D5C4F",
|
||||
"syntax-primitive": "#B30000",
|
||||
"syntax-property": "#C66C00",
|
||||
"syntax-type": "#9C5C12",
|
||||
"syntax-constant": "#404040",
|
||||
"syntax-info": "#606060",
|
||||
"markdown-heading": "#FFC799",
|
||||
"markdown-text": "#101010",
|
||||
"markdown-link": "#FFC799",
|
||||
"markdown-link-text": "#A0A0A0",
|
||||
"markdown-code": "#A0A0A0",
|
||||
"markdown-block-quote": "#101010",
|
||||
"markdown-emph": "#101010",
|
||||
"markdown-strong": "#101010",
|
||||
"markdown-horizontal-rule": "#65737E",
|
||||
"markdown-list-item": "#101010",
|
||||
"markdown-list-enumeration": "#101010",
|
||||
"markdown-image": "#FFC799",
|
||||
"markdown-image-text": "#A0A0A0",
|
||||
"markdown-code-block": "#FFC799"
|
||||
"syntax-keyword": "#b30000"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"seeds": {
|
||||
"palette": {
|
||||
"neutral": "#101010",
|
||||
"ink": "#FFF",
|
||||
"primary": "#FFC799",
|
||||
"accent": "#FF8080",
|
||||
"success": "#99FFE4",
|
||||
"warning": "#FFC799",
|
||||
"error": "#FF8080",
|
||||
"info": "#FFC799",
|
||||
"interactive": "#FFC799",
|
||||
"diffAdd": "#99FFE4",
|
||||
"diffDelete": "#FF8080"
|
||||
},
|
||||
"overrides": {
|
||||
"background-base": "#101010",
|
||||
"background-weak": "#141414",
|
||||
"background-strong": "#0C0C0C",
|
||||
"background-stronger": "#080808",
|
||||
"border-weak-base": "#1C1C1C",
|
||||
"border-weak-hover": "#202020",
|
||||
"border-weak-active": "#242424",
|
||||
"border-weak-selected": "#282828",
|
||||
"border-weak-disabled": "#141414",
|
||||
"border-weak-focus": "#242424",
|
||||
"border-base": "#282828",
|
||||
"border-hover": "#303030",
|
||||
"border-active": "#383838",
|
||||
"border-selected": "#404040",
|
||||
"border-disabled": "#181818",
|
||||
"border-focus": "#383838",
|
||||
"border-strong-base": "#505050",
|
||||
"border-strong-hover": "#585858",
|
||||
"border-strong-active": "#606060",
|
||||
"border-strong-selected": "#686868",
|
||||
"border-strong-disabled": "#202020",
|
||||
"border-strong-focus": "#606060",
|
||||
"surface-diff-add-base": "#0d2818",
|
||||
"surface-diff-delete-base": "#281a1a",
|
||||
"surface-diff-hidden-base": "#141414",
|
||||
"text-base": "#FFF",
|
||||
"text-weak": "#A0A0A0",
|
||||
"text-strong": "#FFFFFF",
|
||||
"syntax-string": "#99FFE4",
|
||||
"syntax-primitive": "#FF8080",
|
||||
"syntax-property": "#FFC799",
|
||||
"syntax-type": "#FFC799",
|
||||
"syntax-constant": "#A0A0A0",
|
||||
"syntax-info": "#8b8b8b",
|
||||
"markdown-heading": "#FFC799",
|
||||
"markdown-text": "#FFF",
|
||||
"markdown-link": "#FFC799",
|
||||
"markdown-link-text": "#A0A0A0",
|
||||
"markdown-code": "#A0A0A0",
|
||||
"markdown-block-quote": "#FFF",
|
||||
"markdown-emph": "#FFF",
|
||||
"markdown-strong": "#FFF",
|
||||
"markdown-horizontal-rule": "#65737E",
|
||||
"markdown-list-item": "#FFF",
|
||||
"markdown-list-enumeration": "#FFF",
|
||||
"markdown-image": "#FFC799",
|
||||
"markdown-image-text": "#A0A0A0",
|
||||
"markdown-code-block": "#FFF"
|
||||
"syntax-keyword": "#ff8080",
|
||||
"syntax-primitive": "#ffc799"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,28 @@ export interface ThemeSeedColors {
|
||||
diffDelete: HexColor
|
||||
}
|
||||
|
||||
export interface ThemeVariant {
|
||||
seeds: ThemeSeedColors
|
||||
export interface ThemePaletteColors {
|
||||
neutral: HexColor
|
||||
ink?: HexColor
|
||||
primary: HexColor
|
||||
success: HexColor
|
||||
warning: HexColor
|
||||
error: HexColor
|
||||
info: HexColor
|
||||
accent?: HexColor
|
||||
interactive?: HexColor
|
||||
diffAdd?: HexColor
|
||||
diffDelete?: HexColor
|
||||
}
|
||||
|
||||
type ThemeVariantBase = {
|
||||
overrides?: Record<string, ColorValue>
|
||||
}
|
||||
|
||||
export type ThemeVariant =
|
||||
| ({ seeds: ThemeSeedColors; palette?: never } & ThemeVariantBase)
|
||||
| ({ palette: ThemePaletteColors; seeds?: never } & ThemeVariantBase)
|
||||
|
||||
export interface DesktopTheme {
|
||||
$schema?: string
|
||||
name: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@opencode-ai/web",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||
|
||||
@@ -28,6 +28,7 @@ description: خصّص اختصارات لوحة المفاتيح.
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode ima listu veza tipki koje možete prilagoditi putem `tui.json`.
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode har en liste over nøglebindinger, som du kan tilpasse gennem `tui.json
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -3,11 +3,11 @@ title: Tastenkombinationen
|
||||
description: Passen Sie Ihre Tastenkombinationen an.
|
||||
---
|
||||
|
||||
OpenCode verfügt über eine Liste von Tastenkombinationen, die Sie über die OpenCode-Konfiguration anpassen können.
|
||||
OpenCode verfügt über eine Liste von Tastenkombinationen, die Sie über `tui.json` anpassen können.
|
||||
|
||||
```json title="opencode.json"
|
||||
```json title="tui.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/tui.json",
|
||||
"keybinds": {
|
||||
"leader": "ctrl+x",
|
||||
"app_exit": "ctrl+c,ctrl+d,<leader>q",
|
||||
@@ -28,6 +28,7 @@ OpenCode verfügt über eine Liste von Tastenkombinationen, die Sie über die Op
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
@@ -117,11 +118,11 @@ Sie müssen für Ihre Keybinds keinen Leader Key verwenden, wir empfehlen jedoch
|
||||
|
||||
## Keybind deaktivieren
|
||||
|
||||
Sie können eine Keybind deaktivieren, indem Sie den Schlüssel mit dem Wert „none“ zu Ihrer Konfiguration hinzufügen.
|
||||
Sie können eine Keybind deaktivieren, indem Sie den Schlüssel mit dem Wert „none“ zu `tui.json` hinzufügen.
|
||||
|
||||
```json title="opencode.json"
|
||||
```json title="tui.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/tui.json",
|
||||
"keybinds": {
|
||||
"session_compact": "none"
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode tiene una lista de combinaciones de teclas que puede personalizar a tra
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode a une liste de raccourcis clavier que vous pouvez personnaliser via la
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode ha una lista di scorciatoie che puoi personalizzare tramite `tui.json`.
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode には、`tui.json` を通じてカスタマイズできるキーバイ
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode has a list of keybinds that you can customize through `tui.json`.
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode에는 `tui.json`을 통해 커스터마이즈할 수 있는 키바인
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode har en liste over tastebindinger som du kan tilpasse gjennom `tui.json`
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode zawiera listę skrótów klawiszowych, które można dostosować za pom
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ O opencode tem uma lista de atalhos de teclado que você pode personalizar atrav
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ opencode имеет список сочетаний клавиш, которые
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode มีรายการปุ่มลัดที่คุณปร
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ opencode, `tui.json` aracılığıyla özelleştirebileceğiniz bir tuş bağlan
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
@@ -134,21 +135,21 @@ Anahtarı yapılandırmanıza "none" değeriyle ekleyerek bir tuş atamasını d
|
||||
|
||||
opencode masaüstü uygulaması bilgi istemi girişi, metni düzenlemek için yaygın Readline/Emacs tarzı kısayolları destekler. Bunlar yerleşiktir ve şu anda `opencode.json` aracılığıyla yapılandırılamaz.
|
||||
|
||||
| Shortcut | Action |
|
||||
| -------- | ---------------------------------------- |
|
||||
| `ctrl+a` | Geçerli satırın başına git |
|
||||
| `ctrl+e` | Move to end of current line |
|
||||
| `ctrl+b` | Move cursor back one character |
|
||||
| `ctrl+f` | Move cursor forward one character |
|
||||
| `alt+b` | Move cursor back one word |
|
||||
| `alt+f` | Move cursor forward one word |
|
||||
| `ctrl+d` | Delete character under cursor |
|
||||
| `ctrl+k` | Kill to end of line |
|
||||
| `ctrl+u` | Satırın başına kadar öldür |
|
||||
| `ctrl+w` | Kill previous word |
|
||||
| `alt+d` | Kill next word |
|
||||
| `ctrl+t` | Transpose characters |
|
||||
| `ctrl+g` | Cancel popovers / abort running response |
|
||||
| Shortcut | Action |
|
||||
| -------- | --------------------------------------------------- |
|
||||
| `ctrl+a` | Geçerli satırın başına git |
|
||||
| `ctrl+e` | Geçerli satırın sonuna git |
|
||||
| `ctrl+b` | İmleci bir karakter geri taşı |
|
||||
| `ctrl+f` | İmleci bir karakter ileri taşı |
|
||||
| `alt+b` | İmleci bir kelime geri taşı |
|
||||
| `alt+f` | İmleci bir kelime ileri taşı |
|
||||
| `ctrl+d` | İmleç altındaki karakteri sil |
|
||||
| `ctrl+k` | Satırın sonuna kadar sil |
|
||||
| `ctrl+u` | Satırın başına kadar sil |
|
||||
| `ctrl+w` | Önceki kelimeyi sil |
|
||||
| `alt+d` | Sonraki kelimeyi sil |
|
||||
| `ctrl+t` | Karakterlerin yerini değiştir |
|
||||
| `ctrl+g` | Açılır pencereleri iptal et / çalışan yanıtı durdur |
|
||||
|
||||
---
|
||||
|
||||
@@ -158,7 +159,7 @@ Bazı terminaller varsayılan olarak Enter ile değiştirici tuşlar göndermez.
|
||||
|
||||
### Windows Terminali
|
||||
|
||||
`settings.json` cihazınızı şu adreste açın:
|
||||
`settings.json` dosyasını şurada açın:
|
||||
|
||||
```
|
||||
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode 提供了一系列快捷键,您可以通过 `tui.json` 进行自定
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
@@ -28,6 +28,7 @@ OpenCode 提供了一系列快捷鍵,您可以透過 `tui.json` 進行自訂
|
||||
"session_unshare": "none",
|
||||
"session_interrupt": "escape",
|
||||
"session_compact": "<leader>c",
|
||||
"session_child_first": "<leader>down",
|
||||
"session_child_cycle": "<leader>right",
|
||||
"session_child_cycle_reverse": "<leader>left",
|
||||
"session_parent": "<leader>up",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user