From 0ac5c7a319a7dc2882e4c88e3d0b94659e9cfbc7 Mon Sep 17 00:00:00 2001 From: Waishnav <86405648+Waishnav@users.noreply.github.com> Date: Sat, 29 Aug 2026 10:58:03 +0530 Subject: [PATCH 1/3] fix(ui): use theme-specific provider logos --- .../assets/provider-logos/copilot-light.svg | 1 + src/ui/assets/provider-logos/cursor-light.svg | 1 + src/ui/assets/provider-logos/openai-light.svg | 1 + .../assets/provider-logos/opencode-dark.svg | 2 +- .../assets/provider-logos/opencode-light.svg | 1 + src/ui/assets/provider-logos/pi-on-light.svg | 1 + src/ui/icons.ts | 39 +++++++++++++++---- src/ui/workspace-app.tsx | 24 ++++++++++-- 8 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 src/ui/assets/provider-logos/copilot-light.svg create mode 100644 src/ui/assets/provider-logos/cursor-light.svg create mode 100644 src/ui/assets/provider-logos/openai-light.svg create mode 100644 src/ui/assets/provider-logos/opencode-light.svg create mode 100644 src/ui/assets/provider-logos/pi-on-light.svg diff --git a/src/ui/assets/provider-logos/copilot-light.svg b/src/ui/assets/provider-logos/copilot-light.svg new file mode 100644 index 00000000..64c54639 --- /dev/null +++ b/src/ui/assets/provider-logos/copilot-light.svg @@ -0,0 +1 @@ + diff --git a/src/ui/assets/provider-logos/cursor-light.svg b/src/ui/assets/provider-logos/cursor-light.svg new file mode 100644 index 00000000..d0cd849c --- /dev/null +++ b/src/ui/assets/provider-logos/cursor-light.svg @@ -0,0 +1 @@ + diff --git a/src/ui/assets/provider-logos/openai-light.svg b/src/ui/assets/provider-logos/openai-light.svg new file mode 100644 index 00000000..7aff9250 --- /dev/null +++ b/src/ui/assets/provider-logos/openai-light.svg @@ -0,0 +1 @@ + diff --git a/src/ui/assets/provider-logos/opencode-dark.svg b/src/ui/assets/provider-logos/opencode-dark.svg index 62e10df4..0bdfe089 100644 --- a/src/ui/assets/provider-logos/opencode-dark.svg +++ b/src/ui/assets/provider-logos/opencode-dark.svg @@ -1 +1 @@ - + diff --git a/src/ui/assets/provider-logos/opencode-light.svg b/src/ui/assets/provider-logos/opencode-light.svg new file mode 100644 index 00000000..8a274375 --- /dev/null +++ b/src/ui/assets/provider-logos/opencode-light.svg @@ -0,0 +1 @@ + diff --git a/src/ui/assets/provider-logos/pi-on-light.svg b/src/ui/assets/provider-logos/pi-on-light.svg new file mode 100644 index 00000000..5472a94e --- /dev/null +++ b/src/ui/assets/provider-logos/pi-on-light.svg @@ -0,0 +1 @@ + diff --git a/src/ui/icons.ts b/src/ui/icons.ts index 8bada413..8fcb11c4 100644 --- a/src/ui/icons.ts +++ b/src/ui/icons.ts @@ -34,17 +34,40 @@ export const toolIcons = { export type ToolIcon = IconNode; const providerLogos = { - claude: new URL("./assets/provider-logos/claude.svg", import.meta.url).href, - codex: new URL("./assets/provider-logos/openai-dark.svg", import.meta.url).href, - copilot: new URL("./assets/provider-logos/copilot-dark.svg", import.meta.url).href, - cursor: new URL("./assets/provider-logos/cursor-dark.svg", import.meta.url).href, - opencode: new URL("./assets/provider-logos/opencode-dark.svg", import.meta.url).href, - pi: new URL("./assets/provider-logos/pi-on-dark.svg", import.meta.url).href, + claude: { + light: new URL("./assets/provider-logos/claude.svg", import.meta.url).href, + dark: new URL("./assets/provider-logos/claude.svg", import.meta.url).href, + }, + codex: { + light: new URL("./assets/provider-logos/openai-light.svg", import.meta.url).href, + dark: new URL("./assets/provider-logos/openai-dark.svg", import.meta.url).href, + }, + copilot: { + light: new URL("./assets/provider-logos/copilot-light.svg", import.meta.url).href, + dark: new URL("./assets/provider-logos/copilot-dark.svg", import.meta.url).href, + }, + cursor: { + light: new URL("./assets/provider-logos/cursor-light.svg", import.meta.url).href, + dark: new URL("./assets/provider-logos/cursor-dark.svg", import.meta.url).href, + }, + opencode: { + light: new URL("./assets/provider-logos/opencode-light.svg", import.meta.url).href, + dark: new URL("./assets/provider-logos/opencode-dark.svg", import.meta.url).href, + }, + pi: { + light: new URL("./assets/provider-logos/pi-on-light.svg", import.meta.url).href, + dark: new URL("./assets/provider-logos/pi-on-dark.svg", import.meta.url).href, + }, } as const; -export function getProviderLogo(name: string): string | undefined { +export type ProviderLogoTheme = "light" | "dark"; + +export function getProviderLogo( + name: string, + theme: ProviderLogoTheme = "dark", +): string | undefined { const normalizedName = name.trim().toLowerCase() as keyof typeof providerLogos; - return providerLogos[normalizedName]; + return providerLogos[normalizedName]?.[theme]; } export function renderIcon(icon: ToolIcon, className = "icon-svg"): SVGElement { diff --git a/src/ui/workspace-app.tsx b/src/ui/workspace-app.tsx index bc101cb3..9dec916d 100644 --- a/src/ui/workspace-app.tsx +++ b/src/ui/workspace-app.tsx @@ -12,7 +12,13 @@ import { type HostContext, type ToolResultCard, } from "./card-types.js"; -import { getProviderLogo, renderIcon, toolIcons, type ToolIcon } from "./icons.js"; +import { + getProviderLogo, + renderIcon, + toolIcons, + type ProviderLogoTheme, + type ToolIcon, +} from "./icons.js"; import { getFileChangePathDisplay, getPatchDisplayParts, @@ -83,6 +89,7 @@ async function boot(): Promise { }; app.onhostcontextchanged = (ctx) => { + const previousTheme = hostContext?.theme; hostContext = { ...hostContext, ...ctx, @@ -90,7 +97,11 @@ async function boot(): Promise { applyHostContext(); // Workspace details inherit host variables directly. Rebuilding their DOM on // iframe resize would reset an in-progress instruction preview interaction. - if (card?.tool !== "open_workspace") renderPayloadIfNeeded(); + if (card?.tool === "open_workspace") { + if (ctx.theme && ctx.theme !== previousTheme) render(); + } else { + renderPayloadIfNeeded(); + } }; app.onteardown = async () => { @@ -583,6 +594,9 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v const providers = card.agentProviders ?? []; const agents = card.agents ?? []; + const providerLogoTheme: ProviderLogoTheme = hostContext?.theme === "light" + ? "light" + : "dark"; const agentChips: WorkspaceChip[] = agents.map((agent) => { const name = agent.name ?? "Unnamed agent"; const providerName = agent.provider?.trim(); @@ -594,14 +608,16 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v ].filter((value): value is string => Boolean(value)).join("\n"); return { label: name, - logo: providerName ? getProviderLogo(providerName) : undefined, + logo: providerName + ? getProviderLogo(providerName, providerLogoTheme) + : undefined, profile: true, title: title || undefined, }; }); const providerChips: WorkspaceChip[] = providers.map((provider) => { const name = provider.id?.trim() || "Unknown provider"; - const logo = getProviderLogo(name); + const logo = getProviderLogo(name, providerLogoTheme); const title = [ provider.model ? `Model: ${provider.model}` : undefined, provider.effort ? `Effort: ${provider.effort}` : undefined, From 0f2548db093707934d2749fa7b7c6c6bc31b68bb Mon Sep 17 00:00:00 2001 From: Waishnav <86405648+Waishnav@users.noreply.github.com> Date: Sat, 29 Aug 2026 11:03:21 +0530 Subject: [PATCH 2/3] chore(ui): refresh official provider assets --- src/ui/assets/provider-logos/copilot-dark.svg | 2 +- src/ui/assets/provider-logos/copilot-light.svg | 2 +- src/ui/assets/provider-logos/cursor-dark.svg | 13 ++++++++++++- src/ui/assets/provider-logos/cursor-light.svg | 13 ++++++++++++- src/ui/assets/provider-logos/openai-dark.svg | 12 +++++++++++- src/ui/assets/provider-logos/openai-light.svg | 12 +++++++++++- 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/ui/assets/provider-logos/copilot-dark.svg b/src/ui/assets/provider-logos/copilot-dark.svg index d09df805..275b8393 100644 --- a/src/ui/assets/provider-logos/copilot-dark.svg +++ b/src/ui/assets/provider-logos/copilot-dark.svg @@ -1 +1 @@ - + diff --git a/src/ui/assets/provider-logos/copilot-light.svg b/src/ui/assets/provider-logos/copilot-light.svg index 64c54639..b52d96cf 100644 --- a/src/ui/assets/provider-logos/copilot-light.svg +++ b/src/ui/assets/provider-logos/copilot-light.svg @@ -1 +1 @@ - + diff --git a/src/ui/assets/provider-logos/cursor-dark.svg b/src/ui/assets/provider-logos/cursor-dark.svg index d50421b5..6849fbc3 100644 --- a/src/ui/assets/provider-logos/cursor-dark.svg +++ b/src/ui/assets/provider-logos/cursor-dark.svg @@ -1 +1,12 @@ - + + + + + + + + diff --git a/src/ui/assets/provider-logos/cursor-light.svg b/src/ui/assets/provider-logos/cursor-light.svg index d0cd849c..b054b189 100644 --- a/src/ui/assets/provider-logos/cursor-light.svg +++ b/src/ui/assets/provider-logos/cursor-light.svg @@ -1 +1,12 @@ - + + + + + + + + diff --git a/src/ui/assets/provider-logos/openai-dark.svg b/src/ui/assets/provider-logos/openai-dark.svg index 7e19c92d..cd86afb5 100644 --- a/src/ui/assets/provider-logos/openai-dark.svg +++ b/src/ui/assets/provider-logos/openai-dark.svg @@ -1 +1,11 @@ - + + + + + + + + + + + diff --git a/src/ui/assets/provider-logos/openai-light.svg b/src/ui/assets/provider-logos/openai-light.svg index 7aff9250..a57ca0da 100644 --- a/src/ui/assets/provider-logos/openai-light.svg +++ b/src/ui/assets/provider-logos/openai-light.svg @@ -1 +1,11 @@ - + + + + + + + + + + + From 16fada9820789d29b710f3881abdd31f81e895f0 Mon Sep 17 00:00:00 2001 From: Waishnav <86405648+Waishnav@users.noreply.github.com> Date: Sat, 29 Aug 2026 11:05:41 +0530 Subject: [PATCH 3/3] fix(ui): preserve workspace state on theme changes --- src/ui/workspace-app.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ui/workspace-app.tsx b/src/ui/workspace-app.tsx index 9dec916d..27d4f5b8 100644 --- a/src/ui/workspace-app.tsx +++ b/src/ui/workspace-app.tsx @@ -98,7 +98,9 @@ async function boot(): Promise { // Workspace details inherit host variables directly. Rebuilding their DOM on // iframe resize would reset an in-progress instruction preview interaction. if (card?.tool === "open_workspace") { - if (ctx.theme && ctx.theme !== previousTheme) render(); + if (ctx.theme && ctx.theme !== previousTheme) { + syncWorkspaceProviderLogos(ctx.theme === "light" ? "light" : "dark"); + } } else { renderPayloadIfNeeded(); } @@ -611,6 +613,7 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v logo: providerName ? getProviderLogo(providerName, providerLogoTheme) : undefined, + logoProvider: providerName, profile: true, title: title || undefined, }; @@ -626,6 +629,7 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v return { label: name, logo, + logoProvider: logo ? name : undefined, bareLogo: Boolean(logo), ariaLabel: name, title: title || name, @@ -652,6 +656,7 @@ function renderWorkspacePayload(container: HTMLElement, card: ToolResultCard): v interface WorkspaceChip { label: string; logo?: string; + logoProvider?: string; profile?: boolean; bareLogo?: boolean; ariaLabel?: string; @@ -929,6 +934,7 @@ function renderWorkspaceChips(chips: WorkspaceChip[]): HTMLElement { ? "workspace-agent-profile-logo" : "workspace-chip-logo"; logo.src = chip.logo; + if (chip.logoProvider) logo.dataset.provider = chip.logoProvider; logo.alt = ""; logo.setAttribute("aria-hidden", "true"); item.append(logo); @@ -941,6 +947,15 @@ function renderWorkspaceChips(chips: WorkspaceChip[]): HTMLElement { return list; } +function syncWorkspaceProviderLogos(theme: ProviderLogoTheme): void { + for (const logo of document.querySelectorAll("img[data-provider]")) { + const providerName = logo.dataset.provider; + if (!providerName) continue; + const src = getProviderLogo(providerName, theme); + if (src && logo.src !== src) logo.src = src; + } +} + function element( tag: K, options: {