Point color, radius, stroke, focus, and type tokens at the Figma scale so later sections use the same values.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilalloandCursor committed 2026-11-02 17:03:43 -07:00
1 parent 63d5d21ae0
commit e808fe70bf
162 files changed
+1385 -1377

No files matched your search

+5 -5
View File
@@ -99,8 +99,8 @@ describe("AskOrganizer (behavioral tests)", () => {
);
const section = container.querySelector('[data-figma-node="22015-42624"]');
expect(section).toBeInTheDocument();
expect(section).toHaveClass("py-[var(--spacing-scale-032)]");
expect(section).not.toHaveClass("py-[var(--spacing-scale-096)]");
expect(section).toHaveClass("py-[var(--space-800)]");
expect(section).not.toHaveClass("py-[var(--space-2400)]");
expect(
screen.getByRole("heading", { name: "Still have questions?" }),
).toBeInTheDocument();
@@ -116,10 +116,10 @@ describe("AskOrganizer (behavioral tests)", () => {
);
const section = container.querySelector('[data-figma-node="18116-15960"]');
expect(section).toHaveClass(
"py-[var(--spacing-scale-040)]",
"px-[var(--spacing-scale-032)]",
"py-[var(--space-1000)]",
"px-[var(--space-800)]",
);
expect(section).not.toHaveClass("py-[var(--spacing-scale-096)]");
expect(section).not.toHaveClass("py-[var(--space-2400)]");
});
it("does not force 358px min-width below md (fits 320px baseline)", () => {
+1 -1
View File
@@ -103,7 +103,7 @@ describe("Avatar (behavioral tests)", () => {
<Avatar alt="Org" initials="CR" shape="rounded-square" />,
);
expect(container.firstChild).toHaveClass(
"rounded-[var(--measures-radius-200,8px)]",
"rounded-[var(--radius-200)]",
);
});
+1 -1
View File
@@ -54,7 +54,7 @@ describe("Chip", () => {
expect(chip.style.color).toContain("--color-content-default-brand-primary");
expect(chip.style.backgroundColor).toBe("transparent");
expect(chip.style.borderColor).toContain(
"--color-border-default-tertiary",
"--color-border-default-control",
);
});
+1 -1
View File
@@ -198,7 +198,7 @@ describe("ContentBanner", () => {
'[data-node-id="22078:806960"]',
);
expect(logoMarkWrap?.className).toMatch(
/max-sm:pb-\[var\(--spacing-scale-024\)\]/,
/max-sm:pb-\[var\(--space-600\)\]/,
);
expect(logoMarkWrap).toHaveClass("md:justify-end");
const logoMark = logoMarkWrap?.querySelector("img");
+1 -1
View File
@@ -118,7 +118,7 @@ describe("FeatureGrid (behavioral tests)", () => {
render(<FeatureGrid title="Test Title" subtitle="Test Subtitle" />);
const title = screen.getByRole("heading", { name: "Test Title" });
expect(title.className).toMatch(/text-\[18px\]/);
expect(title.className).toMatch(/md:text-\[length:var\(--sizing-600,24px\)\]/);
expect(title.className).toMatch(/md:text-\[length:var\(--sizing-600\)\]/);
const subtitle = screen.getByText("Test Subtitle");
expect(subtitle.tagName).toBe("P");
expect(subtitle).toHaveClass("text-small-paragraph", "md:text-medium-paragraph");
+1 -1
View File
@@ -91,7 +91,7 @@ describe("InputLabel – behaviour specifics", () => {
render(<InputLabel label="Test Label" palette="inverse" />);
const label = screen.getByText("Test Label");
expect(label).toHaveClass(
"text-[color:var(--color-content-inverse-secondary,#1f1f1f)]",
"text-[color:var(--color-content-invert-secondary,#1f1f1f)]",
);
});
});
+2 -2
View File
@@ -75,8 +75,8 @@ describe("Logo (behavioral tests)", () => {
it("uses the Figma 6px wordmark-to-mark gap at the default size", () => {
const { container } = render(<Logo />);
const row = container.querySelector("a > div");
expect(row?.className).toContain("gap-[var(--spacing-scale-006)]");
expect(row?.className).toContain("h-[var(--spacing-scale-040)]");
expect(row?.className).toContain("gap-[var(--space-150)]");
expect(row?.className).toContain("h-[var(--space-1000)]");
});
it("shows the folder-top wordmark without a breakpoint hide", () => {
+4 -4
View File
@@ -102,9 +102,9 @@ describe('Top "Create rule" button', () => {
it("pads the standard header to hug Create rule", () => {
renderWithProviders(<Top folderTop={false} />);
const nav = screen.getByRole("navigation", { name: "Main navigation" });
expect(nav.className).toContain("py-[var(--spacing-scale-008)]");
expect(nav.className).toContain("lg:py-[var(--spacing-scale-016)]");
expect(nav.className).not.toContain("min-h-[var(--spacing-scale-040)]");
expect(nav.className).toContain("py-[var(--space-200)]");
expect(nav.className).toContain("lg:py-[var(--space-400)]");
expect(nav.className).not.toContain("min-h-[var(--space-1000)]");
});
it("uses ghost for Create rule", () => {
@@ -188,7 +188,7 @@ describe("Top header chrome", () => {
expect(tab?.className).toContain("sm:flex-1");
expect(nav?.className).toContain("md:absolute");
expect(nav?.className).toContain(
"md:left-[calc(50vw-var(--spacing-scale-016))]",
"md:left-[calc(50vw-var(--space-400))]",
);
expect(nav?.className).not.toContain("ml-auto");
});
+1 -1
View File
@@ -32,7 +32,7 @@ describe("Accordion", () => {
expect(button).toHaveClass("min-h-[88px]");
expect(button).toHaveClass("lg:min-h-[104px]");
expect(button).toHaveClass("xl:min-h-[135px]");
expect(button).toHaveClass("xl:gap-[var(--spacing-scale-048)]");
expect(button).toHaveClass("xl:gap-[var(--space-1200)]");
const title = screen.getByText("Question");
expect(title).toHaveClass("text-[14px]");
+8 -8
View File
@@ -14,14 +14,14 @@ describe("FaqAccordion", () => {
const section = container.querySelector("section");
expect(section).toBeTruthy();
expect(section).toHaveClass("px-[var(--spacing-scale-004)]");
expect(section).toHaveClass("py-[var(--spacing-scale-032)]");
expect(section).toHaveClass("md:px-[var(--spacing-scale-096)]");
expect(section).toHaveClass("md:py-[var(--spacing-scale-064)]");
expect(section).toHaveClass("lg:px-[var(--spacing-scale-160)]");
expect(section).toHaveClass("lg:py-[var(--spacing-scale-096)]");
expect(section).not.toHaveClass("md:px-[var(--spacing-scale-160)]");
expect(section).not.toHaveClass("md:py-[var(--spacing-scale-096)]");
expect(section).toHaveClass("px-[var(--space-100)]");
expect(section).toHaveClass("py-[var(--space-800)]");
expect(section).toHaveClass("md:px-[var(--space-2400)]");
expect(section).toHaveClass("md:py-[var(--space-1800)]");
expect(section).toHaveClass("lg:px-[var(--space-4000)]");
expect(section).toHaveClass("lg:py-[var(--space-2400)]");
expect(section).not.toHaveClass("md:px-[var(--space-4000)]");
expect(section).not.toHaveClass("md:py-[var(--space-2400)]");
expect(section?.firstElementChild).not.toHaveClass("max-w-[1440px]");
});
});
+2 -2
View File
@@ -52,8 +52,8 @@ describe("AboutHeader", () => {
);
const heading = screen.getByRole("heading");
expect(heading.className).toContain("gap-[var(--spacing-scale-010)]");
expect(heading.className).toContain("xl:gap-[var(--spacing-scale-012)]");
expect(heading.className).toContain("gap-[var(--space-250)]");
expect(heading.className).toContain("xl:gap-[var(--space-300)]");
const marks = container.querySelectorAll("h1 span.inline-flex");
expect(marks).toHaveLength(2);
+11 -11
View File
@@ -68,15 +68,15 @@ describe("TripleTextBlock", () => {
const section = container.querySelector("section");
expect(section).toBeTruthy();
expect(section).toHaveClass("px-[var(--spacing-scale-032)]");
expect(section).toHaveClass("md:px-[var(--spacing-scale-096)]");
expect(section).toHaveClass("lg:px-[var(--spacing-scale-096)]");
expect(section).toHaveClass("xl:px-[var(--spacing-scale-160)]");
expect(section).toHaveClass("px-[var(--space-800)]");
expect(section).toHaveClass("md:px-[var(--space-2400)]");
expect(section).toHaveClass("lg:px-[var(--space-2400)]");
expect(section).toHaveClass("xl:px-[var(--space-4000)]");
expect(section).not.toHaveClass(
"md:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))]",
"md:px-[calc(var(--space-2400)+var(--space-2400))]",
);
expect(section).not.toHaveClass(
"xl:px-[calc(var(--spacing-scale-160)+var(--spacing-scale-096))]",
"xl:px-[calc(var(--space-4000)+var(--space-2400))]",
);
expect(section?.firstElementChild).not.toHaveClass("max-w-[1440px]");
});
@@ -100,11 +100,11 @@ describe("TripleTextBlock", () => {
const section = container.querySelector('[data-figma-node="22085-860414"]');
expect(section).toBeTruthy();
expect(section).toHaveClass("px-[var(--spacing-scale-032)]");
expect(section).toHaveClass("lg:px-[var(--spacing-scale-096)]");
expect(section).toHaveClass("xl:px-[var(--spacing-scale-160)]");
expect(section).toHaveClass("px-[var(--space-800)]");
expect(section).toHaveClass("lg:px-[var(--space-2400)]");
expect(section).toHaveClass("xl:px-[var(--space-4000)]");
expect(section).not.toHaveClass(
"lg:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))]",
"lg:px-[calc(var(--space-2400)+var(--space-2400))]",
);
expect(section?.firstElementChild).not.toHaveClass("max-w-[1440px]");
@@ -123,7 +123,7 @@ describe("TripleTextBlock", () => {
expect(screen.getByText("First paragraph.")).toBeInTheDocument();
expect(screen.getByText("Second paragraph.")).toBeInTheDocument();
expect(screen.getByText("Second paragraph.")).toHaveClass(
"mt-[var(--spacing-scale-024)]",
"mt-[var(--space-600)]",
);
expect(screen.getByRole("link", { name: "Setup your community" })).toHaveAttribute(
"href",
+6 -6
View File
@@ -185,8 +185,8 @@ describe("BlogPostPage", () => {
const article = document.querySelector("article");
expect(article).toBeInTheDocument();
expect(article).toHaveClass(
"p-[var(--spacing-scale-024)]",
"sm:py-[var(--spacing-scale-032)]",
"p-[var(--space-600)]",
"sm:py-[var(--space-800)]",
);
// Check content is rendered
@@ -276,14 +276,14 @@ describe("BlogPostPage", () => {
.closest("div.post-body");
expect(contentDiv).toHaveClass("post-body");
expect(contentDiv).toHaveClass(
"text-[var(--color-content-inverse-primary)]",
"text-[var(--color-content-invert-primary)]",
);
expect(contentDiv).toHaveClass("text-medium-paragraph");
const article = contentDiv?.closest("article");
expect(article).toHaveClass("p-[var(--spacing-scale-024)]");
expect(article).toHaveClass("sm:py-[var(--spacing-scale-032)]");
expect(article).not.toHaveClass("-mt-[var(--spacing-scale-048)]");
expect(article).toHaveClass("p-[var(--space-600)]");
expect(article).toHaveClass("sm:py-[var(--space-800)]");
expect(article).not.toHaveClass("-mt-[var(--space-1200)]");
});
it("applies responsive text sizing", async () => {
+1 -1
View File
@@ -136,7 +136,7 @@ describe("ProfilePageView", () => {
"border-[var(--color-border-default-negative-primary)]",
);
expect(confirm.className).not.toContain(
"bg-[var(--color-surface-inverse-primary)]",
"bg-[var(--color-surface-invert-primary)]",
);
await user.click(confirm);
+3 -3
View File
@@ -105,7 +105,7 @@ describe("CardSteps Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"bg-transparent",
"py-[var(--spacing-scale-032)]",
"py-[var(--space-800)]",
);
});
@@ -172,8 +172,8 @@ describe("CardSteps Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"py-[var(--spacing-scale-032)]",
"sm:py-[var(--spacing-scale-048)]",
"py-[var(--space-800)]",
"sm:py-[var(--space-1200)]",
);
});
+6 -6
View File
@@ -75,7 +75,7 @@ describe("ContentContainer", () => {
"font-bricolage-grotesque",
"font-medium",
"text-xx-small-display",
"text-[var(--color-content-inverse-brand-royal)]",
"text-[var(--color-content-invert-brand-royal)]",
);
});
@@ -86,7 +86,7 @@ describe("ContentContainer", () => {
expect(description).toBeInTheDocument();
expect(description).toHaveClass(
"text-x-small-paragraph",
"text-[var(--color-content-inverse-brand-royal)]",
"text-[var(--color-content-invert-brand-royal)]",
);
});
@@ -132,7 +132,7 @@ describe("ContentContainer", () => {
// Check the content container (parent of icon)
expect(iconContainer.parentElement).toHaveClass(
"gap-[var(--measures-spacing-008)]",
"gap-[var(--space-200)]",
);
// Check the text container (parent of title) - it has responsive gap classes
expect(textContainer.parentElement).toHaveClass("flex", "flex-col");
@@ -146,7 +146,7 @@ describe("ContentContainer", () => {
"flex",
"min-w-0",
"items-end",
"gap-[var(--measures-spacing-008)]",
"gap-[var(--space-200)]",
);
});
@@ -156,13 +156,13 @@ describe("ContentContainer", () => {
const author = screen.getByText("Test Author");
expect(author).toHaveClass(
"text-xx-small-paragraph",
"text-[var(--color-content-inverse-brand-royal)]",
"text-[var(--color-content-invert-brand-royal)]",
);
const date = screen.getByText("April 2025");
expect(date).toHaveClass(
"text-xx-small-paragraph",
"text-[var(--color-content-inverse-brand-royal)]",
"text-[var(--color-content-invert-brand-royal)]",
);
});
-5
View File
@@ -13,10 +13,6 @@ vi.mock("next/font/google", () => ({
variable: "--font-bricolage-grotesque",
style: { fontFamily: "Bricolage Grotesque" },
})),
Space_Grotesk: vi.fn(() => ({
variable: "--font-space-grotesk",
style: { fontFamily: "Space Grotesk" },
})),
}));
function findChildByType(node, type) {
@@ -60,7 +56,6 @@ describe("RootLayout", () => {
expect(body).toBeTruthy();
expect(body.props.className).toContain("--font-inter");
expect(body.props.className).toContain("--font-bricolage-grotesque");
expect(body.props.className).toContain("--font-space-grotesk");
});
test("renders main layout structure", () => {
+3 -3
View File
@@ -48,7 +48,7 @@ describe("LogoWall Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"bg-[var(--color-surface-default-primary)]",
"p-[var(--spacing-scale-032)]",
"p-[var(--space-800)]",
);
});
@@ -57,8 +57,8 @@ describe("LogoWall Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"p-[var(--spacing-scale-032)]",
"md:px-[var(--spacing-scale-024)]",
"p-[var(--space-800)]",
"md:px-[var(--space-600)]",
);
});
+6 -6
View File
@@ -59,8 +59,8 @@ describe("QuoteBlock Component", () => {
// Compact variant should have different styling
const section = screen.getByRole("region");
expect(section).toHaveClass(
"py-[var(--spacing-scale-032)]",
"px-[var(--spacing-scale-016)]",
"py-[var(--space-800)]",
"px-[var(--space-400)]",
);
rerender(
@@ -69,8 +69,8 @@ describe("QuoteBlock Component", () => {
// Extended variant should have different styling
expect(section).toHaveClass(
"py-[var(--spacing-scale-048)]",
"px-[var(--spacing-scale-024)]",
"py-[var(--space-1200)]",
"px-[var(--space-600)]",
);
});
@@ -166,10 +166,10 @@ describe("QuoteBlock Component", () => {
render(<QuoteBlock quote="Test quote" author="Test Author" />);
const section = document.querySelector("section");
expect(section).toHaveClass("md:py-[var(--spacing-scale-032)]");
expect(section).toHaveClass("md:py-[var(--space-800)]");
const card = section.querySelector(
'[class*="bg-[var(--color-surface-default-brand-darker-accent)]"]',
'[class*="bg-[var(--color-surface-invert-brand-secondary)]"]',
);
expect(card).toBeInTheDocument();
});
+1 -1
View File
@@ -191,7 +191,7 @@ describe("Rule Component", () => {
const card = screen.getByRole("button");
expect(card).toHaveClass("shadow-[0px_0px_48px_0px_rgba(0,0,0,0.1)]");
expect(card).toHaveClass("rounded-[var(--radius-measures-radius-small)]");
expect(card).toHaveClass("rounded-[var(--radius-300)]");
});
it("maintains proper heading structure", () => {
+1 -1
View File
@@ -86,7 +86,7 @@ describe("Step Component", () => {
.getByText("Test Card Text")
.closest("div").parentElement;
expect(card).toHaveClass(
"bg-[var(--color-surface-inverse-primary)]",
"bg-[var(--color-surface-invert-primary)]",
"shadow-lg",
);
});
+52
View File
@@ -0,0 +1,52 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
const css = readFileSync("app/tailwind.css", "utf8");
function decl(name: string): string {
const match = css.match(new RegExp(`${name}:\\s*([\\s\\S]*?);`));
if (!match?.[1]) throw new Error(`missing ${name}`);
return match[1].replace(/\s+/g, " ").trim();
}
describe("Figma tokens", () => {
it("points theme colors, radius, and focus at Figma", () => {
expect(decl("--radius-500")).toBe("24px");
expect(decl("--color-surface-default-brand-royal")).toContain("royal-blue600");
expect(decl("--color-surface-default-brand-kiwi")).toContain("kiwi800");
expect(decl("--color-content-default-brand-secondary")).toContain("yellow200");
expect(decl("--color-content-invert-brand-secondary")).toContain("yellow800");
expect(decl("--color-content-invert-brand-royal")).toContain("royal-blue400");
expect(decl("--color-content-default-utility-negative")).toContain("red300");
expect(decl("--color-content-default-negative-primary")).toContain(
"utility-negative",
);
expect(decl("--color-border-invert-secondary")).toContain("gray-100");
expect(decl("--color-border-invert-tertiary")).toContain("gray-300");
expect(decl("--color-border-default-control")).toContain("gray-400");
expect(decl("--shadow-focus-default")).toContain("gray-900");
expect(decl("--shadow-focus-invert")).toContain("gray-000");
expect(css).not.toMatch(/--color-[a-z0-9-]+-light:/);
expect(css).not.toContain("--font-mono");
expect(css).not.toContain("--measures-radius-");
expect(css).not.toContain("--color-surface-inverse-");
});
it("matches the type scale and the five sizing steps", () => {
expect(decl("--sizing-450")).toBe("18px");
expect(decl("--sizing-700")).toBe("28px");
expect(decl("--sizing-900")).toBe("36px");
expect(decl("--sizing-1100")).toBe("44px");
expect(decl("--sizing-1300")).toBe("52px");
expect(decl("--text-display-s")).toBe("32px");
expect(decl("--text-display-s--font-weight")).toBe("500");
expect(decl("--text-display-xxl--line-height")).toContain("line-height-2600");
expect(decl("--text-heading-xl--font-weight")).toBe("700");
expect(decl("--text-paragraph-l--line-height")).toContain("line-height-600");
expect(decl("--text-paragraph-strong-m--font-weight")).toBe("700");
expect(decl("--text-paragraph-em-m")).toBe("16px");
expect(decl("--text-link-s")).toBe("14px");
expect(decl("--text-small-display")).toContain("display-s");
expect(decl("--typography-line-height-1800")).toContain("scale-072");
});
});