Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions src/components/ApiCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,48 @@ describe("ApiCard skeleton", () => {
});

it("uses tone stellar for themed skeleton appearance", () => {
const { container } = render(<ApiCard loading />);
const skeletons = container.querySelectorAll(".skeleton--stellar");
expect(skeletons.length).toBeGreaterThan(0);
const { container } = render(<ApiCard loading />);
const skeletons = container.querySelectorAll(".skeleton--stellar");
expect(skeletons.length).toBeGreaterThan(0);
});

it("uses CSS variable tokens for icon size and radius matching final card shape", () => {
const { container } = render(<ApiCard loading />);
const header = container.querySelector(".api-marketplace-card-header");
expect(header).toBeTruthy();
// Header gap should use the CSS variable token
expect(header?.getAttribute("style")).toContain("mkt-space-lg");
});

it("uses CSS variable token for price padding-right matching final card layout", () => {
const { container } = render(<ApiCard loading />);
// The price column should use the CSS variable for padding-right
const priceDivs = container.querySelectorAll('[style*="padding-right"]');
const hasVariable = Array.from(priceDivs).some(
(el) => (el as HTMLElement).style.paddingRight?.includes("mkt-card-price-padding-right")
);
expect(hasVariable).toBe(true);
});

it("applies flexWrap on title row to match final card's responsive layout", () => {
const { container } = render(<ApiCard loading />);
// The title row inside the body should have flexWrap
const body = container.querySelector(".api-marketplace-card-body");
expect(body).toBeTruthy();
const titleRow = body?.querySelector('[style*="flex-wrap"]');
expect(titleRow).toBeTruthy();
});

it("uses CSS variable token for sparkline gap matching final card", () => {
const { container } = render(<ApiCard loading />);
// The sparkline section should use mkt-space-lg for gap
const sparklineSections = container.querySelectorAll('[style*="justify-content: space-between"]');
const hasVariable = Array.from(sparklineSections).some(
(el) => (el as HTMLElement).style.gap?.includes("mkt-space-lg")
);
expect(hasVariable).toBe(true);
});
});
});

describe("ApiCard responsiveness", () => {
const mockApi: APIItem = {
Expand Down
30 changes: 18 additions & 12 deletions src/components/ApiCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,22 @@ export function ApiCardSkeleton({ density = "comfortable" }: { density?: "comfor
<Skeleton tone="stellar" width={60} height={28} borderRadius={8} />
</div>

<div className="api-marketplace-card-header" style={{ display: "flex", gap: 12, alignItems: "center" }}>
<Skeleton tone="stellar" width={56} height={56} borderRadius={10} />

<div style={{ flex: 1, display: "flex", flexDirection: "column", gap: "var(--mkt-space-md, 8px)" }}>
<div style={{ display: "flex", gap: "var(--mkt-space-md, 8px)", alignItems: "baseline" }}>
<div className="api-marketplace-card-header" style={{ display: "flex", gap: "var(--mkt-space-lg, 12px)", alignItems: "center" }}>
<Skeleton
tone="stellar"
width="var(--mkt-card-icon-size, 56px)"
height="var(--mkt-card-icon-size, 56px)"
borderRadius="var(--mkt-card-icon-radius, 10px)"
/>

<div className="api-marketplace-card-body" style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0, gap: "var(--mkt-space-md, 8px)" }}>
<div style={{ display: "flex", gap: "var(--mkt-space-md, 8px)", alignItems: "baseline", flexWrap: "wrap" }}>
<Skeleton tone="stellar" width="60%" height={18} />
<Skeleton tone="stellar" width="20%" height={12} />
</div>

{!isCompact && (
<div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
<div style={{ display: "flex", flexDirection: "column", gap: "var(--mkt-card-margin-top-sm, 4px)" }}>
<Skeleton tone="stellar" width="90%" height={14} />
<Skeleton tone="stellar" width="70%" height={14} />
</div>
Expand All @@ -103,7 +108,7 @@ export function ApiCardSkeleton({ density = "comfortable" }: { density?: "comfor
<div
style={{
textAlign: "right",
paddingRight: 36,
paddingRight: "var(--mkt-card-price-padding-right, 36px)",
flexShrink: 0,
display: "flex",
flexDirection: "column",
Expand All @@ -116,7 +121,7 @@ export function ApiCardSkeleton({ density = "comfortable" }: { density?: "comfor
</div>
</div>

<div className="api-marketplace-card-tags" style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 4 }}>
<div className="api-marketplace-card-tags" style={{ display: "flex", gap: "var(--mkt-space-md, 8px)", flexWrap: "wrap", marginTop: 4 }}>
<Skeleton tone="stellar" width={45} height={24} borderRadius={8} />
<Skeleton tone="stellar" width={55} height={24} borderRadius={8} />
<Skeleton tone="stellar" width={40} height={24} borderRadius={8} />
Expand All @@ -130,14 +135,15 @@ export function ApiCardSkeleton({ density = "comfortable" }: { density?: "comfor
</div>
)}

{/* Sparkline section placeholder */}
{/* Sparkline section placeholder — matches final card's marginTop, gap, and flexWrap */}
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: 12,
marginTop: 2,
gap: "var(--mkt-space-lg, 12px)",
flexWrap: "wrap",
marginTop: "var(--mkt-space-md, 16px)",
}}
>
<Skeleton tone="stellar" width={52} height={12} />
Expand Down Expand Up @@ -167,7 +173,7 @@ export function ApiCardSkeleton({ density = "comfortable" }: { density?: "comfor
display: "flex",
justifyContent: "space-between",
alignItems: "center",
gap: 12,
gap: "var(--mkt-space-lg, 12px)",
flexWrap: "wrap",
}}
>
Expand Down
Loading