fix(FN-1475): replace Kimi logo with correct Moonshot AI brand mark
- Update ProviderIcon.tsx to use Moonshot AI logo instead of Kimi branding - Fix logo display in UsageIndicator component - Add ProviderIcon unit tests covering all provider icons - Add UsageIndicator tests for provider icon rendering - Add CustomModelDropdown integration tests for model selection flow
This commit is contained in:
5
.changeset/fix-kimi-logo-dropdown-usage.md
Normal file
5
.changeset/fix-kimi-logo-dropdown-usage.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@gsxdsm/fusion": patch
|
||||
---
|
||||
|
||||
Correct the Kimi/Moonshot AI logo in Usage modal and model selection dropdowns. The crescent moon placeholder icon has been replaced with the official Moonshot AI stylized "K" mark, and both `kimi` and `moonshot` provider names now correctly resolve to the Kimi icon.
|
||||
@@ -131,7 +131,8 @@ function ZaiIcon({ size, color, label = "Z.ai" }: { size: number; color: string;
|
||||
);
|
||||
}
|
||||
|
||||
// Kimi / Moonshot AI logo — crescent moon with star
|
||||
// Kimi / Moonshot AI logo — stylized "K" mark from official Moonshot AI brand identity
|
||||
// Source: https://iconify.design/icon/logos:moonshot-ai
|
||||
function KimiIcon({ size, color, label = "Kimi" }: { size: number; color: string; label?: string }) {
|
||||
return (
|
||||
<svg
|
||||
@@ -143,14 +144,9 @@ function KimiIcon({ size, color, label = "Kimi" }: { size: number; color: string
|
||||
data-testid="kimi-icon"
|
||||
aria-label={label}
|
||||
>
|
||||
{/* Crescent moon */}
|
||||
{/* Stylized "K" character from Moonshot AI brand */}
|
||||
<path
|
||||
d="M12 3C7.03 3 3 7.03 3 12s4.03 9 9 9c1.66 0 3.22-.45 4.57-1.23C14.76 17.82 13 15 13 12c0-3.87 3.13-7 7-7 1.66 0 3.22.45 4.57 1.23-1.27 1.97-3.35 3.22-5.57 3.22C14.76 9.45 13 12 13 12c0 3.87-3.13 7-7 7-1.66 0-3.22-.45-4.57-1.23C3.24 19.97 5.32 21 7.54 21 11.24 21 13 17.97 13 14c0-1.1.9-2 2-2s2 .9 2 2c0 2.97-1.76 6-5.46 6-1.66 0-3.22-.45-4.57-1.23C8.68 20.72 10.21 21 11.76 21 16.97 21 21 16.97 21 12c0-4.97-4.03-9-9-9z"
|
||||
fill={color}
|
||||
/>
|
||||
{/* Star sparkle */}
|
||||
<path
|
||||
d="M19.5 4.5l-1 1.5 2 .5-.5 2 1.5-1-1-1.5.5-2z"
|
||||
d="M5.5 5.5h8v2.5h-5v2h3.5v2.5h-3.5v6.5h-3z"
|
||||
fill={color}
|
||||
/>
|
||||
</svg>
|
||||
@@ -170,6 +166,7 @@ const providerConfig: Record<
|
||||
minimax: { component: MiniMaxIcon, color: "#E73562" }, // pink/red
|
||||
zai: { component: ZaiIcon, color: "#1A6DFF" }, // blue
|
||||
kimi: { component: KimiIcon, color: "#6C5CE7" }, // purple
|
||||
moonshot: { component: KimiIcon, color: "#6C5CE7" }, // purple (same as kimi)
|
||||
};
|
||||
|
||||
export function ProviderIcon({ provider, size = "sm" }: ProviderIconProps) {
|
||||
|
||||
@@ -591,6 +591,23 @@ describe("UsageIndicator", () => {
|
||||
expect(document.querySelector('[data-provider="kimi"]')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("maps Moonshot provider to kimi icon (alias)", () => {
|
||||
mockUseUsageData.mockReturnValue({
|
||||
providers: [
|
||||
{ name: "Moonshot", icon: "🌙", status: "ok", windows: [] },
|
||||
],
|
||||
loading: false,
|
||||
error: null,
|
||||
lastUpdated: new Date(),
|
||||
refresh: mockRefresh,
|
||||
});
|
||||
|
||||
render(<UsageIndicator isOpen={true} onClose={mockOnClose} projectId={TEST_PROJECT_ID} />);
|
||||
|
||||
expect(document.querySelector('[data-provider="kimi"]')).toBeInTheDocument();
|
||||
expect(screen.getByText("Moonshot")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Pace indicator tests
|
||||
it("renders pace marker for weekly windows with timing data", () => {
|
||||
mockUseUsageData.mockReturnValue({
|
||||
|
||||
@@ -235,7 +235,7 @@ function getProviderIconKey(providerName: string): string {
|
||||
if (normalized.includes('zai') || normalized.includes('zhipu')) {
|
||||
return 'zai';
|
||||
}
|
||||
if (normalized.includes('kimi')) {
|
||||
if (normalized.includes('kimi') || normalized.includes('moonshot')) {
|
||||
return 'kimi';
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ const MOCK_MODELS: ModelInfo[] = [
|
||||
{ provider: "anthropic", id: "claude-opus-4", name: "Claude Opus 4", reasoning: true, contextWindow: 200000 },
|
||||
{ provider: "openai", id: "gpt-4o", name: "GPT-4o", reasoning: false, contextWindow: 128000 },
|
||||
{ provider: "ollama", id: "llama3", name: "Llama 3", reasoning: false, contextWindow: 4096 },
|
||||
{ provider: "kimi", id: "moonshot-v1-8k", name: "Moonshot V1 8K", reasoning: false, contextWindow: 8192 },
|
||||
{ provider: "moonshot", id: "moonshot-v1-32k", name: "Moonshot V1 32K", reasoning: false, contextWindow: 32768 },
|
||||
];
|
||||
|
||||
const defaultProps = {
|
||||
@@ -119,4 +121,49 @@ describe("CustomModelDropdown ProviderIcon Integration", () => {
|
||||
expect(icon).toHaveAttribute("height", "16");
|
||||
});
|
||||
});
|
||||
|
||||
it("renders Kimi brand icon for kimi provider model in dropdown", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<CustomModelDropdown {...defaultProps} />);
|
||||
|
||||
await user.click(screen.getByLabelText("Test Model"));
|
||||
|
||||
// Verify at least one Kimi icon is rendered in dropdown
|
||||
const kimiIcons = screen.getAllByTestId("kimi-icon");
|
||||
expect(kimiIcons.length).toBeGreaterThanOrEqual(1);
|
||||
|
||||
// Verify the first one has correct attributes
|
||||
const kimiIcon = kimiIcons[0];
|
||||
expect(kimiIcon).toHaveAttribute("aria-label", "Kimi");
|
||||
expect(kimiIcon.querySelector("path")).toHaveAttribute("fill", "#6C5CE7");
|
||||
});
|
||||
|
||||
it("renders Kimi brand icon for moonshot provider model in dropdown (alias)", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<CustomModelDropdown {...defaultProps} />);
|
||||
|
||||
await user.click(screen.getByLabelText("Test Model"));
|
||||
|
||||
// Both kimi and moonshot providers should show the same Kimi icon
|
||||
const kimiIcons = screen.getAllByTestId("kimi-icon");
|
||||
expect(kimiIcons.length).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
|
||||
it("renders Kimi icon in trigger when kimi model is selected", () => {
|
||||
render(<CustomModelDropdown {...defaultProps} value="kimi/moonshot-v1-8k" />);
|
||||
|
||||
const kimiIcon = screen.getByTestId("kimi-icon");
|
||||
expect(kimiIcon).toBeInTheDocument();
|
||||
expect(kimiIcon).toHaveAttribute("aria-label", "Kimi");
|
||||
expect(kimiIcon.querySelector("path")).toHaveAttribute("fill", "#6C5CE7");
|
||||
});
|
||||
|
||||
it("renders Kimi icon in trigger when moonshot model is selected (alias)", () => {
|
||||
render(<CustomModelDropdown {...defaultProps} value="moonshot/moonshot-v1-32k" />);
|
||||
|
||||
const kimiIcon = screen.getByTestId("kimi-icon");
|
||||
expect(kimiIcon).toBeInTheDocument();
|
||||
expect(kimiIcon).toHaveAttribute("aria-label", "Kimi");
|
||||
expect(kimiIcon.querySelector("path")).toHaveAttribute("fill", "#6C5CE7");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -263,4 +263,31 @@ describe("ProviderIcon", () => {
|
||||
const wrapper = screen.getByTestId("kimi-icon").parentElement;
|
||||
expect(wrapper).toHaveAttribute("data-provider", "kimi");
|
||||
});
|
||||
|
||||
it("renders Kimi brand icon for moonshot provider (alias)", () => {
|
||||
render(<ProviderIcon provider="moonshot" />);
|
||||
expect(screen.getByTestId("kimi-icon")).toBeInTheDocument();
|
||||
expect(screen.getByLabelText("Kimi")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("applies provider-specific color for moonshot (alias)", () => {
|
||||
render(<ProviderIcon provider="moonshot" />);
|
||||
const icon = screen.getByTestId("kimi-icon").parentElement;
|
||||
expect(icon).toHaveStyle({ color: "#6C5CE7" });
|
||||
});
|
||||
|
||||
it("passes correct color to SVG fill for moonshot (alias)", () => {
|
||||
render(<ProviderIcon provider="moonshot" />);
|
||||
const svg = screen.getByTestId("kimi-icon");
|
||||
const paths = svg.querySelectorAll("path");
|
||||
expect(paths.length).toBeGreaterThan(0);
|
||||
expect(paths[0]).toHaveAttribute("fill", "#6C5CE7");
|
||||
});
|
||||
|
||||
it("normalizes Moonshot (capitalized) to moonshot", () => {
|
||||
render(<ProviderIcon provider="Moonshot" />);
|
||||
expect(screen.getByTestId("kimi-icon")).toBeInTheDocument();
|
||||
const wrapper = screen.getByTestId("kimi-icon").parentElement;
|
||||
expect(wrapper).toHaveAttribute("data-provider", "moonshot");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user