FN-7818: replace placeholder Cursor icon with official brand mark

Swap the hand-drawn Cursor CLI placeholder SVG for Cursor's official cube/arrow brand mark and ensure model-id-shaped provider strings resolve to it.

- Replace CursorCliIcon's placeholder rounded-square+badge SVG with Cursor's official cube/arrow brand mark path data
- Add cursor -> cursor-cli mapping in inferProviderIconKey so cursor, cursor-agent, and cursor/<model> strings resolve to the branded icon instead of falling through to the generic CPU icon
- Update ProviderIcon and providerIconKey tests to cover the new brand mark paths and provider-string inference
- Add a patch changeset documenting the fix

Files changed:
 .changeset/fn-7818-cursor-logo.md                  |  7 +++++
 packages/dashboard/app/components/ProviderIcon.tsx | 33 +++++++++++-----------
 .../app/components/__tests__/ProviderIcon.test.tsx | 12 ++++++--
 .../app/utils/__tests__/providerIconKey.test.ts    |  4 +++
 packages/dashboard/app/utils/providerIconKey.ts    |  8 ++++++
 5 files changed, 44 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-7818

Fusion-Task-Lineage: 73e85e18-e98a-4dc3-b89d-f831525620de

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-11 17:41:52 -07:00
parent a2c9b0fd52
commit 3da9da28f3
5 changed files with 44 additions and 20 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Use the real Cursor logo in the usage dropdown, model selection, and other provider surfaces.
category: fix
dev: Replaces the placeholder CursorCliIcon SVG with the Cursor brand mark and adds a `cursor` → `cursor-cli` mapping in inferProviderIconKey.

View File

@@ -682,6 +682,10 @@ function DroidCliIcon({ size, color, label = "Factory AI — via Droid CLI" }: {
);
}
/*
FNXC:ProviderIcons 2026-07-11-00:00:
FN-7818 replaced the hand-drawn Cursor placeholder with Cursor's official cube/arrow brand mark from cursor.com. This shared icon component is the single source for the Usage dropdown, model-selection surfaces, provider auth cards, and onboarding.
*/
function CursorCliIcon({ size, color, label = "Cursor — via Cursor CLI" }: { size: number; color: string; label?: string }) {
return (
<svg
@@ -693,23 +697,18 @@ function CursorCliIcon({ size, color, label = "Cursor — via Cursor CLI" }: { s
data-testid="cursor-cli-icon"
aria-label={label}
>
<rect x="2" y="3" width="14" height="14" rx="3" fill={color} />
<path
d="M10.8 7.2a3.6 3.6 0 1 0 0 5.6"
stroke="var(--provider-icon-contrast)"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
/>
<rect x="13" y="13" width="10" height="9" rx="1.5" fill={color} />
<path
d="M15.2 16.2l1.6 1.4-1.6 1.4M18.6 19.6h2.4"
stroke="var(--provider-icon-contrast)"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
<g transform="translate(1.47 0) scale(0.06564) translate(-96 -73)">
<path
data-cursor-brand-mark="cube"
d="m410.344 159.545-146.38-84.5111c-4.7-2.7145-10.5-2.7145-15.2 0l-146.373 84.5111c-3.9515 2.282-6.391 6.501-6.391 11.071v170.418c0 4.569 2.4395 8.789 6.391 11.07l146.379 84.512c4.701 2.714 10.501 2.714 15.201 0l146.38-84.512c3.951-2.281 6.391-6.501 6.391-11.07v-170.418c0-4.57-2.44-8.789-6.391-11.071z"
fill={color}
/>
<path
data-cursor-brand-mark="arrow"
d="m401.149 177.447-141.308 244.751c-.955 1.65-3.477.976-3.477-.934v-160.261c0-3.203-1.711-6.164-4.487-7.772l-138.786-80.127c-1.65-.956-.976-3.478.934-3.478h282.616c4.013 0 6.522 4.35 4.515 7.828h-.007z"
fill="var(--provider-icon-contrast)"
/>
</g>
</svg>
);
}

View File

@@ -58,16 +58,22 @@ describe("ProviderIcon", () => {
expect(svg.parentElement).toHaveStyle({ color: "var(--provider-openai)" });
});
it("renders cursor-cli icon with provider token color", () => {
it("renders cursor-cli icon with provider token color and official brand mark", () => {
render(<ProviderIcon provider="cursor-cli" />);
const svg = screen.getByTestId("cursor-cli-icon");
expect(svg).toBeInTheDocument();
expect(screen.getByLabelText("Cursor — via Cursor CLI")).toBeInTheDocument();
const badgeGlyph = svg.querySelector('path[stroke="var(--provider-icon-contrast)"]');
expect(badgeGlyph).toBeInTheDocument();
expect(svg.querySelector('path[data-cursor-brand-mark="cube"]')).toHaveAttribute("fill", "var(--provider-cursor-cli)");
expect(svg.querySelector('path[data-cursor-brand-mark="arrow"]')).toHaveAttribute("fill", "var(--provider-icon-contrast)");
expect(svg.parentElement).toHaveStyle({ color: "var(--provider-cursor-cli)" });
});
it("infers cursor provider strings to the cursor-cli brand icon", () => {
render(<ProviderIcon provider="cursor" />);
expect(screen.getByTestId("cursor-cli-icon")).toBeInTheDocument();
expect(document.querySelector('[data-provider="cursor"] svg:not([data-testid])')).not.toBeInTheDocument();
});
it("renders grok-cli icon reusing the xAI brand mark", () => {
render(<ProviderIcon provider="grok-cli" />);
const svg = screen.getByTestId("xai-icon");

View File

@@ -9,6 +9,10 @@ describe("inferProviderIconKey", () => {
["openai-codex", "openai"],
["gemini-2.5-pro", "google"],
["google-antigravity", "google"],
["cursor", "cursor-cli"],
["Cursor", "cursor-cli"],
["cursor-agent", "cursor-cli"],
["cursor/gpt-5", "cursor-cli"],
["ollama/llama3", "ollama"],
["minimax-text-01", "minimax"],
["zhipu-glm-4", "zai"],

View File

@@ -11,6 +11,14 @@ export function inferProviderIconKey(modelOrProviderName: string): string {
const normalized = modelOrProviderName.toLowerCase();
// Map common provider/model names to their icon keys.
/*
FNXC:ProviderIcons 2026-07-11-00:00:
FN-7818: model-id-shaped Cursor provider strings (cursor, cursor-agent, cursor/<model>) must resolve to the cursor-cli brand icon on model-selection surfaces instead of the generic CPU fallback, mirroring UsageIndicator's local mapping.
Run before broad model-family checks so cursor/gpt-5 stays Cursor-branded instead of OpenAI-branded.
*/
if (normalized.includes("cursor")) {
return "cursor-cli";
}
if (normalized.includes("claude") || normalized.includes("anthropic")) {
return "anthropic";
}