Apply the FAQ Small, Medium, and Large variants at the matching breakpoints so the About accordion is not using desktop inset and type on tablet.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,22 +11,22 @@ const SIZE_CLASSES: Record<
|
|||||||
> = {
|
> = {
|
||||||
s: {
|
s: {
|
||||||
header:
|
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]",
|
title: "text-[14px] font-medium leading-[18px]",
|
||||||
subhead: "text-x-small-label",
|
subhead: "text-x-small-label",
|
||||||
},
|
},
|
||||||
/** Figma: Layout / Accordion — Medium (22135-890258; header gap/px/py + Large/Label 18/24). */
|
/** Figma: Layout / Accordion — Medium (22135-890258; header gap/px/py + Large/Label 18/24). */
|
||||||
m: {
|
m: {
|
||||||
header:
|
header:
|
||||||
"gap-[var(--spacing-scale-024)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-024)] items-center",
|
"min-h-[104px] gap-[var(--spacing-scale-024)] px-[var(--spacing-scale-016)] py-[var(--spacing-scale-024)] items-center",
|
||||||
title: "text-large-label",
|
title: "text-large-label font-medium leading-6",
|
||||||
subhead: "text-[14px] leading-[18px] font-medium",
|
subhead: "text-[14px] leading-[18px] font-medium",
|
||||||
},
|
},
|
||||||
l: {
|
l: {
|
||||||
header:
|
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). */
|
/** 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",
|
subhead: "text-large-label",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -137,11 +137,15 @@ function AccordionView({
|
|||||||
) : null}
|
) : null}
|
||||||
</span>
|
</span>
|
||||||
<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
|
aria-hidden
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={`flex size-6 items-center justify-center transition-transform ${isOpen ? "-rotate-90" : "rotate-90"}`}
|
||||||
>
|
>
|
||||||
<Icon name="chevron_right" size={24} />
|
<Icon name="chevron_right" size={24} />
|
||||||
</span>
|
</span>
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</h3>
|
</h3>
|
||||||
{isOpen && children ? (
|
{isOpen && children ? (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { FaqAccordionProps, FaqAccordionViewProps } from "./Accordion.types
|
|||||||
import type { AccordionSizeValue } from "../../layout/Accordion";
|
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>(
|
const FaqAccordionContainer = memo<FaqAccordionProps>(
|
||||||
({ size: sizeProp = "s", lgSize: lgSizeProp = "m", xlSize: xlSizeProp = "l", ...props }) => {
|
({ 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";
|
import type { FaqAccordionViewProps } from "./Accordion.types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Figma: "Sections / Accordion" (22130-889248; mobile FAQ 22132-889380). **xl** rows **Large** via `xlSize` (22135:890328).
|
* Figma: "Sections / Accordion" (22130-889248; mobile FAQ 22132-889380).
|
||||||
* 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).
|
* 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({
|
function FaqAccordionView({
|
||||||
title,
|
title,
|
||||||
@@ -20,12 +22,12 @@ function FaqAccordionView({
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
aria-labelledby={headingId}
|
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
|
<h2
|
||||||
id={headingId}
|
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}
|
{title}
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default {
|
|||||||
docs: {
|
docs: {
|
||||||
description: {
|
description: {
|
||||||
component:
|
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 userEvent from "@testing-library/user-event";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen } from "@testing-library/react";
|
||||||
import { describe, it, expect } from "vitest";
|
import { describe, it, expect } from "vitest";
|
||||||
@@ -19,4 +20,25 @@ describe("Accordion", () => {
|
|||||||
|
|
||||||
expect(screen.getByText("Answer copy")).toBeInTheDocument();
|
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]");
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user