diff --git a/packages/dashboard/app/components/ProviderIcon.tsx b/packages/dashboard/app/components/ProviderIcon.tsx index 969e1d4b62..ad49f2bf90 100644 --- a/packages/dashboard/app/components/ProviderIcon.tsx +++ b/packages/dashboard/app/components/ProviderIcon.tsx @@ -1,3 +1,4 @@ +import { useId } from "react"; import { Cpu } from "lucide-react"; import { inferProviderIconKey } from "../utils/providerIconKey"; @@ -527,11 +528,13 @@ function GitHubIcon({ size, color, label = "GitHub" }: { size: number; color: st } /* -FNXC:ProviderIcons 2026-07-18-18:24: -FN-8354: OMP ACP is a first-class provider, so its shared dashboard icon must use the official omp.sh favicon's stepped T mark rather than the generic Cpu fallback. Render its official single-color silhouette with the provider token so it remains legible in either theme. +FNXC:ProviderIcons 2026-07-22-00:00: +FN-8487: The shared OMP mark must retain the official omp.sh favicon's pink-to-purple-to-cyan diagonal gradient instead of adapting to the theme as a monochrome glyph. Keep the favicon's stepped-T path but omit its dark rounded tile so the mark remains transparent on dashboard chrome. Source: https://omp.sh/favicon.svg */ -function OmpIcon({ size, color, label = "Oh My Pi" }: { size: number; color: string; label?: string }) { +function OmpIcon({ size, label = "Oh My Pi" }: { size: number; color: string; label?: string }) { + const gradientId = `omp-gradient-${useId().replace(/:/g, "")}`; + return ( - + + + + + + + + ); } diff --git a/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx b/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx index 66d981f64b..1b015d1342 100644 --- a/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx +++ b/packages/dashboard/app/components/__tests__/ProviderIcon.test.tsx @@ -74,14 +74,41 @@ describe("ProviderIcon", () => { expect(document.querySelector('[data-provider="cursor"] svg:not([data-testid])')).not.toBeInTheDocument(); }); - it("renders the OMP brand icon, auth label, and tokenized color for omp-cli", () => { + it("renders the OMP brand icon, auth label, and official tokenized gradient for omp-cli", () => { render(); const svg = screen.getByTestId("omp-icon"); + const gradient = svg.querySelector("linearGradient"); + const path = svg.querySelector("path"); + expect(svg).toBeInTheDocument(); expect(screen.getByLabelText("Oh My Pi — via omp ACP")).toBeInTheDocument(); expect(svg.parentElement).toHaveAttribute("data-provider", "omp-cli"); expect(svg.parentElement).toHaveStyle({ color: "var(--provider-omp)" }); - expect(svg.querySelector("path")).toHaveAttribute("fill", "var(--provider-omp)"); + expect(path).toHaveAttribute("fill", `url(#${gradient?.id})`); + expect(gradient).toHaveAttribute("x1", "0"); + expect(gradient).toHaveAttribute("y1", "0"); + expect(gradient).toHaveAttribute("x2", "1"); + expect(gradient).toHaveAttribute("y2", "1"); + expect(Array.from(gradient?.querySelectorAll("stop") ?? []).map((stop) => stop.getAttribute("stop-color"))).toEqual([ + "var(--provider-omp-gradient-start)", + "var(--provider-omp-gradient-mid)", + "var(--provider-omp-gradient-end)", + ]); + }); + + it("assigns unique gradient ids to simultaneous OMP icons", () => { + const { container } = render( + <> + + + , + ); + const gradients = Array.from(container.querySelectorAll("[data-testid='omp-icon'] linearGradient")); + const paths = Array.from(container.querySelectorAll("[data-testid='omp-icon'] path")); + + expect(gradients).toHaveLength(2); + expect(new Set(gradients.map((gradient) => gradient.id)).size).toBe(2); + expect(paths.map((path) => path.getAttribute("fill"))).toEqual(gradients.map((gradient) => `url(#${gradient.id})`)); }); it.each(["omp", "oh-my-pi"])("renders the OMP brand icon for the %s alias", (provider) => { diff --git a/packages/dashboard/app/styles.css b/packages/dashboard/app/styles.css index ecd7dbd147..a2daf359e3 100644 --- a/packages/dashboard/app/styles.css +++ b/packages/dashboard/app/styles.css @@ -396,7 +396,10 @@ svg.spinning { --provider-cursor-cli: #7c3aed; --provider-ollama: #d4a27f; /* Runtime-plugin marks. */ - --provider-omp: var(--text); + --provider-omp-gradient-start: #ed4abf; + --provider-omp-gradient-mid: #9b4dff; + --provider-omp-gradient-end: #5ad8e6; + --provider-omp: var(--provider-omp-gradient-mid); --provider-hermes: #d4961c; --provider-openclaw: #ff4f40; --provider-paperclip: var(--text);