feat(FN-2591): add Bedrock provider icon support

- Add a dedicated Bedrock SVG provider icon and provider token styling
- Wire Bedrock provider aliases so provider detection resolves to the new icon key
- Update usage indicator mapping so Bedrock usage providers render the correct icon
- Expand ProviderIcon tests to cover Bedrock icon rendering and alias coverage
This commit is contained in:
Fusion
2026-04-26 10:25:07 -07:00
committed by gsxdsm
parent 7b24497438
commit 022d1522ea
4 changed files with 65 additions and 0 deletions

View File

@@ -155,6 +155,25 @@ function KimiIcon({ size, color, label = "Kimi" }: { size: number; color: string
); );
} }
function BedrockIcon({ size, color, label = "Amazon Bedrock" }: { 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="bedrock-icon"
aria-label={label}
>
<path
d="M.045 18.02c.072-.116.187-.124.348-.022 2.344 1.476 4.878 2.212 7.607 2.212 1.86 0 3.68-.398 5.453-1.198.386-.168.71-.298.972-.39.26-.092.478-.113.654-.06.176.052.263.2.263.443 0 .222-.12.453-.358.693-.96.962-2.16 1.71-3.592 2.242A12.126 12.126 0 0 1 7.297 23c-2.456 0-4.583-.665-6.378-1.992a.39.39 0 0 1-.098-.096c-.05-.078-.05-.156 0-.234zm6.609-3.26c0-.37.093-.665.282-.886.188-.222.43-.332.727-.332.282 0 .524.105.726.314.2.21.3.498.3.866v4.116c0 .382-.098.676-.294.882-.196.206-.436.31-.72.31-.294 0-.54-.108-.738-.324-.198-.216-.296-.506-.296-.868v-4.078h.014zm-2.986 2.3c0-.376.096-.672.288-.89.192-.216.434-.324.726-.324.292 0 .534.108.726.324.192.218.288.514.288.89v1.778c0 .376-.096.672-.288.89-.192.216-.434.324-.726.324-.292 0-.534-.108-.726-.324-.192-.218-.288-.514-.288-.89v-1.778zm-2.92 1.334c0-.36.09-.65.27-.868.18-.218.42-.328.722-.328s.544.11.73.328c.186.218.278.508.278.868v.444c0 .36-.092.65-.278.868-.186.218-.428.328-.73.328s-.542-.11-.722-.328c-.18-.218-.27-.508-.27-.868v-.444zM21.93 16.4c.804.456 1.39.87 1.758 1.242.368.372.552.7.552.984 0 .208-.102.37-.308.488-.206.118-.462.128-.768.032-.306-.096-.674-.316-1.104-.66a12.728 12.728 0 0 1-1.864-1.75c-1.592.644-3.342.966-5.25.966-1.354 0-2.604-.178-3.752-.534a8.103 8.103 0 0 1-.09-.032l.03.012c-.136-.048.056.022-.042-.014-.04-.016-.04-.016 0 0l.012.004-.012-.004c-.32-.122-.528-.222-.624-.3-.096-.078-.144-.178-.144-.3 0-.098.04-.186.122-.264.082-.078.19-.116.326-.116.076 0 .284.054.624.162 1.078.34 2.264.51 3.558.51 1.642 0 3.194-.286 4.658-.856a17.018 17.018 0 0 1-1.904-3.326c-.416-.94-.726-1.86-.93-2.758-.206-.898-.308-1.728-.308-2.49 0-.664.094-1.194.28-1.592.188-.396.456-.594.804-.594.2 0 .392.074.576.224.184.148.312.354.384.614.1.358.178.758.234 1.198.056.44.084.876.084 1.306 0 .898-.116 1.862-.348 2.894-.232 1.032-.614 2.11-1.146 3.234a16.217 16.217 0 0 0 1.916 1.694z"
fill={color}
/>
</svg>
);
}
function XaiIcon({ size, color, label = "xAI" }: { size: number; color: string; label?: string }) { function XaiIcon({ size, color, label = "xAI" }: { size: number; color: string; label?: string }) {
return ( return (
<svg <svg
@@ -297,6 +316,9 @@ const providerConfig: Record<
moonshot: { component: KimiIcon, color: "var(--provider-kimi)" }, // Moonshot alias moonshot: { component: KimiIcon, color: "var(--provider-kimi)" }, // Moonshot alias
"kimi-coding": { component: KimiIcon, color: "var(--provider-kimi)", label: "Kimi" }, // Kimi alias "kimi-coding": { component: KimiIcon, color: "var(--provider-kimi)", label: "Kimi" }, // Kimi alias
bedrock: { component: BedrockIcon, color: "var(--provider-bedrock)" },
"amazon-bedrock": { component: BedrockIcon, color: "var(--provider-bedrock)", label: "Amazon Bedrock" },
xai: { component: XaiIcon, color: "var(--text)" }, xai: { component: XaiIcon, color: "var(--text)" },
grok: { component: XaiIcon, color: "var(--text)", label: "xAI" }, grok: { component: XaiIcon, color: "var(--text)", label: "xAI" },

View File

@@ -238,6 +238,9 @@ function getProviderIconKey(providerName: string): string {
if (normalized.includes('kimi') || normalized.includes('moonshot')) { if (normalized.includes('kimi') || normalized.includes('moonshot')) {
return 'kimi'; return 'kimi';
} }
if (normalized.includes('bedrock') || normalized.includes('amazon')) {
return 'bedrock';
}
if (normalized.includes('xai') || normalized.includes('grok')) { if (normalized.includes('xai') || normalized.includes('grok')) {
return 'xai'; return 'xai';
} }

View File

@@ -437,4 +437,43 @@ describe("ProviderIcon", () => {
// Verify the new crescent moon geometry: contains circle arc notation "a9 9" // Verify the new crescent moon geometry: contains circle arc notation "a9 9"
expect(pathD).toContain("a9 9"); expect(pathD).toContain("a9 9");
}); });
it("renders Bedrock brand icon for bedrock provider", () => {
render(<ProviderIcon provider="bedrock" />);
expect(screen.getByTestId("bedrock-icon")).toBeInTheDocument();
expect(screen.getByLabelText("Amazon Bedrock")).toBeInTheDocument();
});
it("applies provider-specific color for bedrock", () => {
render(<ProviderIcon provider="bedrock" />);
const icon = screen.getByTestId("bedrock-icon").parentElement;
expect(icon).toHaveStyle({ color: "var(--provider-bedrock)" });
});
it("passes correct color to SVG fill for bedrock", () => {
render(<ProviderIcon provider="bedrock" />);
const svg = screen.getByTestId("bedrock-icon");
const paths = svg.querySelectorAll("path");
expect(paths.length).toBeGreaterThan(0);
expect(paths[0]).toHaveAttribute("fill", "var(--provider-bedrock)");
});
it("normalizes Bedrock (capitalized) to bedrock", () => {
render(<ProviderIcon provider="Bedrock" />);
expect(screen.getByTestId("bedrock-icon")).toBeInTheDocument();
const wrapper = screen.getByTestId("bedrock-icon").parentElement;
expect(wrapper).toHaveAttribute("data-provider", "bedrock");
});
it("renders Bedrock brand icon for amazon-bedrock alias", () => {
render(<ProviderIcon provider="amazon-bedrock" />);
expect(screen.getByTestId("bedrock-icon")).toBeInTheDocument();
expect(screen.getByLabelText("Amazon Bedrock")).toBeInTheDocument();
});
it("applies provider-specific color for amazon-bedrock alias", () => {
render(<ProviderIcon provider="amazon-bedrock" />);
const icon = screen.getByTestId("bedrock-icon").parentElement;
expect(icon).toHaveStyle({ color: "var(--provider-bedrock)" });
});
}); });

View File

@@ -169,6 +169,7 @@
--provider-minimax: #e73562; --provider-minimax: #e73562;
--provider-zai: #1a6dff; --provider-zai: #1a6dff;
--provider-kimi: #6c5ce7; --provider-kimi: #6c5ce7;
--provider-bedrock: #ff9900;
--provider-opencode: #38bdf8; --provider-opencode: #38bdf8;
--provider-icon-contrast: var(--bg); --provider-icon-contrast: var(--bg);