diff --git a/.changeset/fn-7801-grok-xai-logo.md b/.changeset/fn-7801-grok-xai-logo.md new file mode 100644 index 0000000000..4d55de01ad --- /dev/null +++ b/.changeset/fn-7801-grok-xai-logo.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Show the xAI logo for Grok model IDs across dashboard provider surfaces. +category: fix +dev: ProviderIcon now falls back through inferProviderIconKey before the generic CPU icon. diff --git a/packages/dashboard/app/components/ProviderIcon.tsx b/packages/dashboard/app/components/ProviderIcon.tsx index b374577ddc..8c3ab8c7c1 100644 --- a/packages/dashboard/app/components/ProviderIcon.tsx +++ b/packages/dashboard/app/components/ProviderIcon.tsx @@ -1,5 +1,7 @@ import { Cpu } from "lucide-react"; +import { inferProviderIconKey } from "../utils/providerIconKey"; + function LlamaCppIcon({ size, color, label = "llama.cpp" }: { size: number; color: string; label?: string }) { return ; } @@ -829,7 +831,14 @@ const providerConfig: Record< export function ProviderIcon({ provider, size = "sm" }: ProviderIconProps) { const normalizedProvider = provider.toLowerCase(); - const config = providerConfig[normalizedProvider]; + const directConfig = providerConfig[normalizedProvider]; + /* + FNXC:ProviderIcons 2026-07-10-00:00: + FN-7801: dashboard surfaces can pass model-id-shaped provider strings such as grok-4.5 or grok-cli/grok-4-fast, which strict providerConfig lookups miss. + Fall through to the shared inferProviderIconKey normalizer before the Cpu default so Grok/xAI and other provider families keep their brand icons, while exact keys and genuinely unknown providers retain existing behavior. + */ + const inferredConfig = directConfig ? undefined : providerConfig[inferProviderIconKey(provider)]; + const config = directConfig ?? inferredConfig; const IconComponent = config?.component; const color = config?.color ?? "var(--text-muted)"; const label = config?.label; diff --git a/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx b/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx index d06deebba1..08a9567e00 100644 --- a/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx +++ b/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx @@ -122,6 +122,7 @@ describe("ProviderIcon", () => { it("renders Cpu icon as fallback for unknown providers", () => { render(); + expect(screen.queryByTestId("xai-icon")).not.toBeInTheDocument(); // Cpu icon from lucide-react renders as an svg without our custom data-testid const icon = screen.getByText((_, element) => { return element?.tagName.toLowerCase() === "svg" && @@ -132,6 +133,7 @@ describe("ProviderIcon", () => { it("renders Cpu icon as fallback for empty provider", () => { render(); + expect(screen.queryByTestId("xai-icon")).not.toBeInTheDocument(); const icon = screen.getByText((_, element) => { return element?.tagName.toLowerCase() === "svg" && element?.parentElement?.getAttribute("data-provider") === ""; @@ -418,6 +420,31 @@ describe("ProviderIcon", () => { }); // xAI provider tests + it.each(["xai", "grok", "grok-cli"])("renders xAI brand icon for exact %s provider key", (provider) => { + render(); + expect(screen.getByTestId("xai-icon")).toBeInTheDocument(); + }); + + it.each([ + ["grok-4.5", "grok-4.5"], + ["grok-4-fast", "grok-4-fast"], + ["grok-cli/grok-4-fast", "grok-cli/grok-4-fast"], + ["xai-grok-4", "xai-grok-4"], + ["Grok-4.5", "grok-4.5"], + ])("renders xAI brand icon for inferred Grok model/provider string %s", (provider, expectedDataProvider) => { + render(); + const icon = screen.getByTestId("xai-icon").parentElement; + expect(icon).toHaveStyle({ color: "var(--text)" }); + expect(icon).toHaveAttribute("data-provider", expectedDataProvider); + }); + + it("infers non-Grok provider icons from model-shaped ids", () => { + render(); + const icon = screen.getByTestId("openai-icon").parentElement; + expect(icon).toHaveStyle({ color: "var(--provider-openai)" }); + expect(icon).toHaveAttribute("data-provider", "gpt-5.5"); + }); + it("renders xAI brand icon for xai provider", () => { render(); expect(screen.getByTestId("xai-icon")).toBeInTheDocument();