QA pass: layout, create-flow, and About books #68

Merged
an.di merged 38 commits from adilallo/fix/CR-129-create-rule-button into main 2026-08-26 15:46:56 +00:00
6 changed files with 69 additions and 14 deletions
Showing only changes of commit 9e698e7ab6 - Show all commits
@@ -11,22 +11,22 @@ const SIZE_CLASSES: Record<
> = {
s: {
header:
"gap-[var(--spacing-scale-016)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-020)] items-center",
"min-h-[88px] gap-[var(--spacing-scale-016)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-020)] items-center",
title: "text-[14px] font-medium leading-[18px]",
subhead: "text-x-small-label",
},
/** Figma: Layout / Accordion — Medium (22135-890258; header gap/px/py + Large/Label 18/24). */
m: {
header:
"gap-[var(--spacing-scale-024)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-024)] items-center",
title: "text-large-label",
"min-h-[104px] gap-[var(--spacing-scale-024)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-024)] items-center",
title: "text-large-label font-medium leading-6",
subhead: "text-[14px] leading-[18px] font-medium",
},
l: {
header:
"gap-[var(--spacing-scale-048)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-032)] items-center",
"min-h-[135px] gap-[var(--spacing-scale-048)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-032)] items-center",
/** Figma Large: X Large Label 24 Regular, lh 28 (21842-2869). */
title: "text-x-large-label",
title: "text-x-large-label font-normal leading-7",
subhead: "text-large-label",
},
};
@@ -137,10 +137,14 @@ function AccordionView({
) : null}
</span>
<span
className={`flex size-6 shrink-0 items-center justify-center text-[var(--color-content-default-primary,white)] transition-transform ${isOpen ? "-rotate-90" : "rotate-90"}`}
className="flex h-6 w-12 shrink-0 items-center justify-end text-[var(--color-content-default-primary,white)]"
aria-hidden
>
<Icon name="chevron_right" size={24} />
<span
className={`flex size-6 items-center justify-center transition-transform ${isOpen ? "-rotate-90" : "rotate-90"}`}
>
<Icon name="chevron_right" size={24} />
</span>
</span>
</button>
</h3>
@@ -6,7 +6,7 @@ import type { FaqAccordionProps, FaqAccordionViewProps } from "./Accordion.types
import type { AccordionSizeValue } from "../../layout/Accordion";
/**
* Figma: "Sections / Accordion" (22130-889248). Rows: **s** / **m** at `lg` (22135-890258); **Large** (`l`) at `xl` (22135:890328).
* Figma: "Sections / Accordion" (22130-889248). Rows: **s** through `md` (22130:889249); **m** at `lg` (22135-890258); **l** at `xl` (22135:890328).
*/
const FaqAccordionContainer = memo<FaqAccordionProps>(
({ size: sizeProp = "s", lgSize: lgSizeProp = "m", xlSize: xlSizeProp = "l", ...props }) => {
@@ -5,8 +5,10 @@ import LayoutAccordion from "../../layout/Accordion";
import type { FaqAccordionViewProps } from "./Accordion.types";
/**
* Figma: "Sections / Accordion" (22130-889248; mobile FAQ 22132-889380). **xl** rows **Large** via `xlSize` (22135:890328).
* Section title: Large Heading (32px, lh 40) below `lg`; X Large Heading (36px, lh 44) at `lg`; XX Large Heading (40px, lh 52) at `xl` (Figma desktop frame 22135:890398).
* Figma: "Sections / Accordion" (22130-889248; mobile FAQ 22132-889380).
* Inset: **4/32** stacked, **96/64** from `md` (22130:889249), **160/96** from `lg` (22130:889247 / 22135:890328).
* Rows: **s** below `lg`, **m** at `lg`, **l** at `xl` via `xlSize`.
* Section title: Large Heading below `lg`; X Large Heading at `lg`; XX Large Heading at `xl` (22135:890398).
*/
function FaqAccordionView({
title,
@@ -20,12 +22,12 @@ function FaqAccordionView({
return (
<section
aria-labelledby={headingId}
className={`bg-[var(--color-surface-default-secondary)] px-[var(--spacing-scale-004)] py-[var(--spacing-scale-032)] md:px-[var(--spacing-scale-160)] md:py-[var(--spacing-scale-096)] ${className}`.trim()}
className={`bg-[var(--color-surface-default-secondary)] px-[var(--spacing-scale-004)] py-[var(--spacing-scale-032)] md:px-[var(--spacing-scale-096)] md:py-[var(--spacing-scale-064)] lg:px-[var(--spacing-scale-160)] lg:py-[var(--spacing-scale-096)] ${className}`.trim()}
>
<div className="mx-auto flex w-full max-w-[1440px] flex-col items-center gap-[var(--spacing-scale-096)] md:gap-[var(--spacing-scale-040)]">
<div className="mx-auto flex w-full flex-col items-center gap-[var(--spacing-scale-096)] md:gap-[var(--spacing-scale-040)]">
<h2
id={headingId}
className="w-full px-[var(--spacing-scale-016)] text-center font-bricolage-grotesque text-[length:var(--text-large-heading)] font-bold leading-[length:var(--text-large-heading--line-height)] text-[var(--color-content-default-brand-primary,#fefcc9)] md:px-0 lg:text-[length:var(--text-x-large-heading)] lg:leading-[length:var(--text-x-large-heading--line-height)] xl:text-[length:var(--text-xx-large-heading)] xl:leading-[length:var(--text-xx-large-heading--line-height)] xl:tracking-[var(--text-xx-large-heading--letter-spacing)]"
className="w-full text-center font-bricolage-grotesque text-[length:var(--text-large-heading)] font-bold leading-[length:var(--text-large-heading--line-height)] text-[var(--color-content-default-brand-primary,#fefcc9)] lg:text-[length:var(--text-x-large-heading)] lg:leading-[length:var(--text-x-large-heading--line-height)] xl:text-[length:var(--text-xx-large-heading)] xl:leading-[length:var(--text-xx-large-heading--line-height)] xl:tracking-[var(--text-xx-large-heading--letter-spacing)]"
>
{title}
</h2>
+1 -1
View File
@@ -9,7 +9,7 @@ export default {
docs: {
description: {
component:
"About-page FAQ wrapper over layout/Accordion. Sizes: s below lg, m at lg, l at xl.",
"About-page FAQ wrapper over layout/Accordion. Rows: s below lg, m at lg, l at xl. Section inset: 4/32, 96/64 from md, 160/96 from lg.",
},
},
},
@@ -1,3 +1,4 @@
import "@testing-library/jest-dom/vitest";
import userEvent from "@testing-library/user-event";
import { render, screen } from "@testing-library/react";
import { describe, it, expect } from "vitest";
@@ -19,4 +20,25 @@ describe("Accordion", () => {
expect(screen.getByText("Answer copy")).toBeInTheDocument();
});
it("stacks FAQ size variants at lg and xl", () => {
render(
<Accordion size="s" lgSize="m" xlSize="l" title="Question">
Answer copy
</Accordion>,
);
const button = screen.getByRole("button", { name: "Question" });
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)]");
const title = screen.getByText("Question");
expect(title).toHaveClass("text-[14px]");
expect(title).toHaveClass("lg:text-large-label");
expect(title).toHaveClass("xl:text-x-large-label");
expect(title).toHaveClass("xl:font-normal");
expect(title).toHaveClass("xl:leading-7");
});
});
@@ -0,0 +1,27 @@
import "@testing-library/jest-dom/vitest";
import { render } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import FaqAccordion from "../../../app/components/sections/Accordion";
describe("FaqAccordion", () => {
it("uses Figma section inset per breakpoint and does not cap the inner stack at 1440", () => {
const { container } = render(
<FaqAccordion
title="Get answers to your questions"
items={[{ title: "What is CommunityRule, and who is it for?", answer: "Groups." }]}
/>,
);
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?.firstElementChild).not.toHaveClass("max-w-[1440px]");
});
});