From 2303740b4a385826f3292ed13b5e716c39f669fd Mon Sep 17 00:00:00 2001 From: Serhii Dziupin Date: Wed, 12 Aug 2026 09:14:33 +0000 Subject: [PATCH] fix(integrations): restore brand icons and provider logo fallbacks The Integrations cards render Icon(plugin.icon), so Claude Code / Command Code / Cursor brand glyphs belong in the sprite. Also restore claude-code.svg and the Command Code ProviderLogo fallback used after Set up opens the Providers page. Leave out unused opencode.svg. Co-authored-by: Serhii Dziupin --- .../ui/src/assets/provider-logos/claude-code.svg | 4 ++++ packages/ui/src/components/icon/sprite.ts | 4 +++- .../ThirdPartyIntegrationsSection.tsx | 2 +- .../sections/integrations/thirdPartyPlugins.ts | 9 +++++++-- packages/ui/src/components/ui/ProviderLogo.tsx | 5 ++++- .../components/ui/providerLogoFallback.test.ts | 13 +++++++++++++ .../ui/src/components/ui/providerLogoFallback.ts | 5 +++++ scripts/generate-icon-sprite.mjs | 15 +++++++++++++++ 8 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 packages/ui/src/assets/provider-logos/claude-code.svg create mode 100644 packages/ui/src/components/ui/providerLogoFallback.test.ts create mode 100644 packages/ui/src/components/ui/providerLogoFallback.ts diff --git a/packages/ui/src/assets/provider-logos/claude-code.svg b/packages/ui/src/assets/provider-logos/claude-code.svg new file mode 100644 index 00000000..9a454303 --- /dev/null +++ b/packages/ui/src/assets/provider-logos/claude-code.svg @@ -0,0 +1,4 @@ + diff --git a/packages/ui/src/components/icon/sprite.ts b/packages/ui/src/components/icon/sprite.ts index 769b58cd..b93478e6 100644 --- a/packages/ui/src/components/icon/sprite.ts +++ b/packages/ui/src/components/icon/sprite.ts @@ -51,6 +51,7 @@ export const iconSpriteData = { "checkbox-blank-circle-fill": ``, "checkbox-circle": ``, "checkbox-multiple": ``, + "claude-code": ``, "clipboard": ``, "close": ``, "close-circle": ``, @@ -62,11 +63,12 @@ export const iconSpriteData = { "code-sslash": ``, "collapse-vertical": ``, "command": ``, + "command-code": ``, "compass-3": ``, "computer": ``, "contract-up-down": ``, "corner-down-left": ``, - "cursor": ``, + "cursor": ``, "database-2": ``, "delete-bin": ``, "discord-fill": ``, diff --git a/packages/ui/src/components/sections/integrations/ThirdPartyIntegrationsSection.tsx b/packages/ui/src/components/sections/integrations/ThirdPartyIntegrationsSection.tsx index 02066ed3..cd0b9a1e 100644 --- a/packages/ui/src/components/sections/integrations/ThirdPartyIntegrationsSection.tsx +++ b/packages/ui/src/components/sections/integrations/ThirdPartyIntegrationsSection.tsx @@ -315,7 +315,7 @@ export const ThirdPartyIntegrationsSection: React.FC
- +
{t(plugin.nameKey)}
diff --git a/packages/ui/src/components/sections/integrations/thirdPartyPlugins.ts b/packages/ui/src/components/sections/integrations/thirdPartyPlugins.ts index cf1b4d80..ff28c43e 100644 --- a/packages/ui/src/components/sections/integrations/thirdPartyPlugins.ts +++ b/packages/ui/src/components/sections/integrations/thirdPartyPlugins.ts @@ -7,6 +7,8 @@ export interface ThirdPartyPluginDefinition { packageName: string; providerId: string; icon: IconName; + /** Brand mark tint (e.g. Claude orange); neutral marks use text-foreground. */ + brandClassName: string; nameKey: I18nKey; descriptionKey: I18nKey; homepage: string; @@ -17,7 +19,8 @@ export const THIRD_PARTY_PLUGINS: readonly ThirdPartyPluginDefinition[] = [ id: 'opencode-claude', packageName: '@otto-assistant/opencode-claude', providerId: 'claude-code', - icon: 'sparkling', + icon: 'claude-code', + brandClassName: 'text-[#D97757]', nameKey: 'settings.integrations.thirdParty.opencodeClaude.name', descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description', homepage: 'https://github.com/otto-assistant/opencode-claude', @@ -26,7 +29,8 @@ export const THIRD_PARTY_PLUGINS: readonly ThirdPartyPluginDefinition[] = [ id: 'opencode-commandcode', packageName: '@otto-assistant/opencode-commandcode', providerId: 'command-code', - icon: 'terminal-box', + icon: 'command-code', + brandClassName: 'text-foreground', nameKey: 'settings.integrations.thirdParty.opencodeCommandcode.name', descriptionKey: 'settings.integrations.thirdParty.opencodeCommandcode.description', homepage: 'https://github.com/otto-assistant/opencode-commandcode', @@ -36,6 +40,7 @@ export const THIRD_PARTY_PLUGINS: readonly ThirdPartyPluginDefinition[] = [ packageName: '@otto-assistant/opencode-cursor-oauth', providerId: 'cursor', icon: 'cursor', + brandClassName: 'text-foreground', nameKey: 'settings.integrations.thirdParty.opencodeCursorOauth.name', descriptionKey: 'settings.integrations.thirdParty.opencodeCursorOauth.description', homepage: 'https://github.com/otto-assistant/opencode-cursor', diff --git a/packages/ui/src/components/ui/ProviderLogo.tsx b/packages/ui/src/components/ui/ProviderLogo.tsx index ef2e3bac..70af4f45 100644 --- a/packages/ui/src/components/ui/ProviderLogo.tsx +++ b/packages/ui/src/components/ui/ProviderLogo.tsx @@ -1,6 +1,8 @@ import React from 'react'; +import { Icon } from '@/components/icon/Icon'; import { useProviderLogo } from '@/hooks/useProviderLogo'; import { cn } from '@/lib/utils'; +import { getProviderLogoFallbackIcon } from './providerLogoFallback'; interface ProviderLogoProps { providerId: string; @@ -16,6 +18,7 @@ export const ProviderLogo: React.FC = ({ onError: externalOnError }) => { const { src, onError: handleInternalError, hasLogo } = useProviderLogo(providerId); + const fallbackIcon = getProviderLogoFallbackIcon(providerId); const handleError = React.useCallback(() => { handleInternalError(); @@ -23,7 +26,7 @@ export const ProviderLogo: React.FC = ({ }, [handleInternalError, externalOnError]); if (!hasLogo || !src) { - return null; + return fallbackIcon ? : null; } return ( diff --git a/packages/ui/src/components/ui/providerLogoFallback.test.ts b/packages/ui/src/components/ui/providerLogoFallback.test.ts new file mode 100644 index 00000000..c82b9ad3 --- /dev/null +++ b/packages/ui/src/components/ui/providerLogoFallback.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from 'bun:test'; +import { getProviderLogoFallbackIcon } from './providerLogoFallback'; + +describe('provider logo fallbacks', () => { + test('uses a local terminal icon when Command Code has no resolved logo', () => { + expect(getProviderLogoFallbackIcon('command-code')).toBe('terminal-box'); + }); + + test('does not replace providers with their own logo assets', () => { + expect(getProviderLogoFallbackIcon('claude-code')).toBeNull(); + expect(getProviderLogoFallbackIcon('cursor')).toBeNull(); + }); +}); diff --git a/packages/ui/src/components/ui/providerLogoFallback.ts b/packages/ui/src/components/ui/providerLogoFallback.ts new file mode 100644 index 00000000..9aa871fd --- /dev/null +++ b/packages/ui/src/components/ui/providerLogoFallback.ts @@ -0,0 +1,5 @@ +import type { IconName } from '@/components/icon/icons'; + +export function getProviderLogoFallbackIcon(providerId: string | null | undefined): IconName | null { + return providerId?.trim().toLowerCase() === 'command-code' ? 'terminal-box' : null; +} diff --git a/scripts/generate-icon-sprite.mjs b/scripts/generate-icon-sprite.mjs index 1d1f1c3e..3098bb05 100644 --- a/scripts/generate-icon-sprite.mjs +++ b/scripts/generate-icon-sprite.mjs @@ -22,6 +22,21 @@ const customIconData = new Map([ "openchamber", ``, ], + // Claude spark — official Anthropic mark (Simple Icons path), monochrome. + [ + "claude-code", + ``, + ], + // Cursor two-cursor mark — official (Simple Icons path), monochrome. + [ + "cursor", + ``, + ], + // Command Code — corner squares + center square (official logo geometry). + [ + "command-code", + ``, + ], ]) const source = readFileSync(remixPath, "utf-8")