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();