feat(FN-1344): add MiniMax and Z.ai provider logos to usage dialog

- Add MiniMax provider icon with distinct blue gradient design
- Add Z.ai provider icon with geometric dot pattern
- Integrate new icons into UsageIndicator component
- Add comprehensive tests for ProviderIcon rendering
This commit is contained in:
gsxdsm
2026-04-09 08:43:49 -07:00
parent 4d1a14f49e
commit 5844f873fc
3 changed files with 102 additions and 0 deletions

View File

@@ -91,6 +91,46 @@ function OllamaIcon({ size, color, label = "Ollama" }: { size: number; color: st
);
}
// MiniMax logo — stylized geometric "M" mark
function MiniMaxIcon({ size, color, label = "MiniMax" }: { size: number; color: string; label?: string }) {
return (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
data-testid="minimax-icon"
aria-label={label}
>
<path
d="M3 3h6.5L12 7.5 14.5 3H21v18h-5.5v-8.75L12 18l-3.5-5.75V21H3V3z"
fill={color}
/>
</svg>
);
}
// Z.ai / Zhipu AI logo — stylized abstract mark
function ZaiIcon({ size, color, label = "Z.ai" }: { size: number; color: string; label?: string }) {
return (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
data-testid="zai-icon"
aria-label={label}
>
<path
d="M4 4h16l-7 9h7L9 21l3-7H5l6-8H4V4z"
fill={color}
/>
</svg>
);
}
const providerConfig: Record<
string,
{ component: typeof AnthropicIcon; color: string; label?: string }
@@ -101,6 +141,8 @@ const providerConfig: Record<
google: { component: GeminiIcon, color: "#4285f4" }, // blue
gemini: { component: GeminiIcon, color: "#4285f4" }, // blue (same as google)
ollama: { component: OllamaIcon, color: "#fff" }, // white
minimax: { component: MiniMaxIcon, color: "#612BFF" }, // purple
zai: { component: ZaiIcon, color: "#1A6DFF" }, // blue
};
export function ProviderIcon({ provider, size = "sm" }: ProviderIconProps) {

View File

@@ -229,6 +229,12 @@ function getProviderIconKey(providerName: string): string {
if (normalized.includes('ollama')) {
return 'ollama';
}
if (normalized.includes('minimax')) {
return 'minimax';
}
if (normalized.includes('zai') || normalized.includes('zhipu')) {
return 'zai';
}
// Return the original name as fallback (ProviderIcon will show a default icon)
return providerName;

View File

@@ -182,4 +182,58 @@ describe("ProviderIcon", () => {
expect(paths.length).toBeGreaterThan(0);
expect(paths[0]).toHaveAttribute("fill", "#fff");
});
it("renders MiniMax brand icon for minimax provider", () => {
render(<ProviderIcon provider="minimax" />);
expect(screen.getByTestId("minimax-icon")).toBeInTheDocument();
expect(screen.getByLabelText("MiniMax")).toBeInTheDocument();
});
it("applies provider-specific color for minimax", () => {
render(<ProviderIcon provider="minimax" />);
const icon = screen.getByTestId("minimax-icon").parentElement;
expect(icon).toHaveStyle({ color: "#612BFF" });
});
it("passes correct color to SVG fill for minimax", () => {
render(<ProviderIcon provider="minimax" />);
const svg = screen.getByTestId("minimax-icon");
const paths = svg.querySelectorAll("path");
expect(paths.length).toBeGreaterThan(0);
expect(paths[0]).toHaveAttribute("fill", "#612BFF");
});
it("normalizes Minimax (capitalized) to minimax", () => {
render(<ProviderIcon provider="Minimax" />);
expect(screen.getByTestId("minimax-icon")).toBeInTheDocument();
const wrapper = screen.getByTestId("minimax-icon").parentElement;
expect(wrapper).toHaveAttribute("data-provider", "minimax");
});
it("renders Z.ai brand icon for zai provider", () => {
render(<ProviderIcon provider="zai" />);
expect(screen.getByTestId("zai-icon")).toBeInTheDocument();
expect(screen.getByLabelText("Z.ai")).toBeInTheDocument();
});
it("applies provider-specific color for zai", () => {
render(<ProviderIcon provider="zai" />);
const icon = screen.getByTestId("zai-icon").parentElement;
expect(icon).toHaveStyle({ color: "#1A6DFF" });
});
it("passes correct color to SVG fill for zai", () => {
render(<ProviderIcon provider="zai" />);
const svg = screen.getByTestId("zai-icon");
const paths = svg.querySelectorAll("path");
expect(paths.length).toBeGreaterThan(0);
expect(paths[0]).toHaveAttribute("fill", "#1A6DFF");
});
it("normalizes Zai (capitalized) to zai", () => {
render(<ProviderIcon provider="Zai" />);
expect(screen.getByTestId("zai-icon")).toBeInTheDocument();
const wrapper = screen.getByTestId("zai-icon").parentElement;
expect(wrapper).toHaveAttribute("data-provider", "zai");
});
});