Refine use cases rule examples

This commit is contained in:
adilallo
2026-05-19 22:16:08 -06:00
parent 7c46cbd87b
commit 2f2b5d0dc2
65 changed files with 3129 additions and 252 deletions
@@ -28,6 +28,11 @@ export interface CommunityRuleSection {
export interface CommunityRuleProps {
sections: CommunityRuleSection[];
className?: string;
/** When true, wrap in white background with left teal bar (small breakpoint). */
/** When true, wrap in white background with left accent bar (small breakpoint). */
useCardStyle?: boolean;
/**
* Accent bar color when {@link useCardStyle} is true; should match the page
* surface behind the card (defaults to create-flow teal).
*/
cardAccentColor?: string;
}
@@ -17,17 +17,22 @@ function CommunityRuleView({
sections,
className = "",
useCardStyle = false,
cardAccentColor,
}: CommunityRuleProps) {
const accent = cardAccentColor ?? TEAL_BG;
const rootClass = useCardStyle
? `rounded-[12px] bg-white pl-3 border-l-4 ${className}`
? `rounded-[12px] bg-white pl-4 ${className}`
: className;
const rootStyle = useCardStyle ? { borderLeftColor: TEAL_BG } : undefined;
const rootStyle = useCardStyle
? {
gap: SECTION_GAP,
// Inset bar (not border) — Safari mishandles `border-left` + CSS variable accent colors.
boxShadow: `inset 4px 0 0 0 ${accent}`,
}
: { gap: SECTION_GAP };
return (
<div
className={`flex flex-col min-w-0 ${rootClass}`}
style={{ gap: SECTION_GAP, ...rootStyle }}
>
<div className={`flex flex-col min-w-0 ${rootClass}`} style={rootStyle}>
{sections.map((ruleSection, sectionIndex) => (
<Section
key={sectionIndex}
@@ -111,9 +111,9 @@ const ContentLockupContainer = memo<ContentLockupProps>(
titleGroup: "flex flex-col gap-[var(--spacing-scale-008)]",
titleContainer: "flex gap-[var(--spacing-scale-008)] items-center",
title:
"font-bricolage-grotesque font-medium text-[36px] leading-[110%] tracking-[0] lg:text-[44px] lg:leading-[1.1] text-[var(--color-content-default-brand-primary)]",
"font-bricolage-grotesque font-medium text-[32px] leading-[1.1] tracking-[0] md:text-[44px] md:leading-[1.1] text-[var(--color-content-default-brand-primary)]",
subtitle:
"font-inter font-normal text-[18px] leading-[130%] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-default-primary)]",
"font-inter font-normal text-[18px] leading-[1.3] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-default-primary)]",
shape:
"w-[16px] h-[16px] md:w-[20px] md:h-[20px] lg:w-[24px] lg:h-[24px]",
},
@@ -123,9 +123,9 @@ const ContentLockupContainer = memo<ContentLockupProps>(
titleGroup: "flex flex-col gap-[var(--spacing-scale-008)] w-full",
titleContainer: "flex gap-[var(--spacing-scale-008)] items-center",
title:
"font-bricolage-grotesque font-medium text-[36px] leading-[110%] tracking-[0] lg:text-[44px] lg:leading-[1.1] text-[var(--color-content-inverse-primary)]",
"font-bricolage-grotesque font-medium text-[32px] leading-[1.1] tracking-[0] md:text-[44px] md:leading-[1.1] text-[var(--color-content-inverse-primary)]",
subtitle:
"font-inter font-normal text-[18px] leading-[130%] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-invert-secondary)]",
"font-inter font-normal text-[18px] leading-[1.3] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-invert-secondary)]",
shape:
"w-[16px] h-[16px] md:w-[20px] md:h-[20px] lg:w-[24px] lg:h-[24px]",
},
@@ -29,10 +29,10 @@ function HeaderLockupView({
}`}
>
{/* Title */}
<div className="flex items-center relative shrink-0 w-full">
<div className="flex w-full shrink-0 items-center">
<h1
id={titleId}
className={`flex-[1_0_0] min-h-px min-w-px overflow-hidden relative ${titleColorClass} text-ellipsis whitespace-pre-wrap ${
className={`relative w-full min-w-0 ${titleColorClass} whitespace-pre-wrap ${
isLeft ? "text-left" : "text-center"
} ${
isL
@@ -49,7 +49,7 @@ function HeaderLockupView({
!(typeof description === "string" && description.length === 0) &&
(typeof description === "string" ? (
<p
className={`font-inter font-normal max-w-[640px] overflow-hidden relative shrink-0 ${descriptionColorClass} text-ellipsis w-full whitespace-pre-wrap ${
className={`font-inter font-normal max-w-[640px] overflow-visible relative shrink-0 ${descriptionColorClass} w-full whitespace-pre-wrap ${
isLeft ? "" : "text-center"
} ${
isL ? "text-[18px] leading-[1.3]" : "text-[14px] leading-[20px]"
@@ -59,7 +59,7 @@ function HeaderLockupView({
</p>
) : (
<div
className={`font-inter font-normal max-w-[640px] overflow-hidden relative shrink-0 ${descriptionColorClass} text-ellipsis w-full whitespace-pre-wrap ${
className={`font-inter font-normal max-w-[640px] overflow-visible relative shrink-0 ${descriptionColorClass} w-full whitespace-pre-wrap ${
isLeft ? "" : "text-center"
} ${
isL ? "text-[18px] leading-[1.3]" : "text-[14px] leading-[20px]"
@@ -15,6 +15,11 @@ interface SectionHeaderProps {
* subtitle **18 / 1.3** at `lg`, **24/32** at `xl`, **left-aligned** in its column from `lg` (Figma **22085:860413**).
*/
ruleStackDesktopTypeScale?: boolean;
/**
* When true with `ruleStackDesktopTypeScale`, title and subtitle split into two columns from project **`md`** (640px),
* e.g. `/use-cases` Rule stack. Default keeps the split at **`lg`** (1024px).
*/
twoColumnsFromMd?: boolean;
}
/**
@@ -29,12 +34,18 @@ const SectionHeader = memo<SectionHeaderProps>(
variant: variantProp = "default",
stackedDesktopLines,
ruleStackDesktopTypeScale = false,
twoColumnsFromMd = false,
}) => {
const variant = variantProp;
const useStackedDesktop =
variant === "multi-line" && stackedDesktopLines != null;
const rowAlignClasses =
variant === "multi-line"
const splitFromMd =
twoColumnsFromMd &&
ruleStackDesktopTypeScale &&
variant === "multi-line";
const rowAlignClasses = splitFromMd
? "md:flex-row md:justify-between md:items-center xl:gap-[var(--spacing-scale-024)]"
: variant === "multi-line"
? "lg:flex-row lg:justify-between lg:items-center xl:gap-[var(--spacing-scale-024)]"
: "lg:flex-row lg:justify-between lg:items-start xl:gap-[var(--spacing-scale-024)]";
@@ -42,11 +53,13 @@ const SectionHeader = memo<SectionHeaderProps>(
<div
className={`flex flex-col gap-[var(--spacing-scale-004)] w-full ${rowAlignClasses}`}
>
{/* Title — left column at lg+ */}
{/* Title — left column at md+ (use cases) or lg+ */}
<div
className={
variant === "multi-line"
? "lg:w-[50%] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center xl:w-[50%] xl:h-[156px] xl:flex xl:items-center"
? splitFromMd
? "md:w-[50%] md:h-[var(--spacing-scale-120)] md:flex md:items-center xl:w-[50%] xl:h-[156px] xl:flex xl:items-center"
: "lg:w-[50%] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center xl:w-[50%] xl:h-[156px] xl:flex xl:items-center"
: "lg:w-[369px] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center xl:w-[452px] xl:h-[156px] xl:flex xl:items-center"
}
>
@@ -54,30 +67,38 @@ const SectionHeader = memo<SectionHeaderProps>(
className={
variant === "multi-line"
? ruleStackDesktopTypeScale
? "font-bricolage-grotesque font-bold text-[28px] leading-[36px] md:text-[32px] md:leading-[40px] lg:w-full lg:max-w-none lg:text-left lg:text-[32px] lg:leading-[40px] xl:text-[40px] xl:leading-[52px] text-[var(--color-content-default-primary)]"
? splitFromMd
? "font-bricolage-grotesque font-bold text-[28px] leading-[36px] text-[var(--color-content-default-primary)] md:w-full md:max-w-none md:text-left md:text-[32px] md:leading-[40px] xl:text-[40px] xl:leading-[52px]"
: "font-bricolage-grotesque font-bold text-[28px] leading-[36px] md:text-[32px] md:leading-[40px] lg:w-full lg:max-w-none lg:text-left lg:text-[32px] lg:leading-[40px] xl:text-[40px] xl:leading-[52px] text-[var(--color-content-default-primary)]"
: "font-bricolage-grotesque font-bold text-[28px] leading-[36px] md:text-[32px] md:leading-[40px] lg:w-[410px] lg:text-left xl:text-[40px] xl:leading-[52px] text-[var(--color-content-default-primary)]"
: "font-bricolage-grotesque font-bold text-[28px] leading-[36px] sm:text-[32px] sm:leading-[40px] lg:text-[32px] lg:leading-[40px] lg:w-[369px] lg:pr-[var(--spacing-scale-096)] xl:text-[40px] xl:leading-[52px] xl:w-[452px] xl:pr-[var(--spacing-scale-096)] text-[var(--color-content-default-primary)]"
}
>
<span className="block lg:hidden">{title}</span>
<span className={splitFromMd ? "block md:hidden" : "block lg:hidden"}>
{title}
</span>
{useStackedDesktop ? (
<span className="hidden lg:block">
<span className={splitFromMd ? "hidden md:block" : "hidden lg:block"}>
<span className="block">{stackedDesktopLines[0]}</span>
<span className="block">{stackedDesktopLines[1]}</span>
<span className="block">{stackedDesktopLines[2]}</span>
</span>
) : (
<span className="hidden lg:block">{titleLg || title}</span>
<span className={splitFromMd ? "hidden md:block" : "hidden lg:block"}>
{titleLg || title}
</span>
)}
</h2>
</div>
{/* Subtitle — right column at lg+ (Figma X Large / Large / stacked small) */}
{/* Subtitle — right column at md+ (use cases) or lg+ */}
<div
className={
variant === "multi-line"
? ruleStackDesktopTypeScale
? "lg:w-[50%] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center lg:justify-start lg:ml-[var(--spacing-scale-016)] xl:ml-0 xl:w-[50%] xl:h-[156px] xl:flex xl:items-center xl:justify-start"
? splitFromMd
? "md:w-[50%] md:h-[var(--spacing-scale-120)] md:flex md:items-center md:justify-start md:ml-[var(--spacing-scale-016)] xl:ml-0 xl:w-[50%] xl:h-[156px] xl:flex xl:items-center xl:justify-start"
: "lg:w-[50%] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center lg:justify-start lg:ml-[var(--spacing-scale-016)] xl:ml-0 xl:w-[50%] xl:h-[156px] xl:flex xl:items-center xl:justify-start"
: "lg:w-[50%] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center lg:justify-end lg:ml-[var(--spacing-scale-016)] xl:ml-0 xl:w-[50%] xl:h-[156px] xl:flex xl:items-center xl:justify-end"
: "lg:w-[928px] lg:h-[var(--spacing-scale-120)] lg:flex lg:items-center lg:justify-end xl:h-[156px] xl:flex xl:items-center xl:justify-end"
}
@@ -86,7 +107,9 @@ const SectionHeader = memo<SectionHeaderProps>(
className={
variant === "multi-line"
? ruleStackDesktopTypeScale
? "font-inter font-normal text-[14px] leading-[20px] md:text-[18px] md:leading-[130%] lg:text-left lg:text-[18px] lg:leading-[130%] text-[var(--color-content-default-tertiary)] xl:text-[24px] xl:leading-[32px]"
? splitFromMd
? "font-inter font-normal text-[14px] leading-[20px] text-[var(--color-content-default-tertiary)] md:text-left md:text-[18px] md:leading-[130%] xl:text-[24px] xl:leading-[32px]"
: "font-inter font-normal text-[14px] leading-[20px] md:text-[18px] md:leading-[130%] lg:text-left lg:text-[18px] lg:leading-[130%] text-[var(--color-content-default-tertiary)] xl:text-[24px] xl:leading-[32px]"
: "font-inter font-normal text-[14px] leading-[20px] md:text-[18px] md:leading-[130%] xl:text-[24px] xl:leading-[32px] text-[var(--color-content-default-tertiary)] lg:text-right"
: "font-inter font-normal text-[18px] leading-[130%] sm:text-[18px] sm:leading-[32px] lg:text-[24px] lg:leading-[32px] xl:text-[32px] xl:leading-[40px] xl:text-right text-[#484848] sm:text-[var(--color-content-default-tertiary)] lg:text-[var(--color-content-default-tertiary)] xl:text-[var(--color-content-default-tertiary)] tracking-[0px]"
}
@@ -6,7 +6,7 @@ import type { TripleTextBlockProps } from "./TripleTextBlock.types";
/**
* Figma: "Type / TripleTextBlock" — use cases **`lg` 22037-26994**, **`xl` 22085-860414**;
* **`md` 22085-862437**; stacked 22137:890676; lg 22128:888715; xl 22135:889705 (default).
* baseline **22112-871529**; **`md` 22085-862437**; stacked 22137:890676; lg 22128:888715; xl 22135:889705 (default).
*/
const TripleTextBlockContainer = memo<TripleTextBlockProps>((props) => {
const headingId = useId();
@@ -14,19 +14,19 @@ function columnUsesLargeBreakpointCopy(column: TripleTextBlockColumn): boolean {
function TripleTextUseCasesColumn({ column }: { column: TripleTextBlockColumn }) {
return (
<div className="flex w-full flex-col gap-[var(--spacing-scale-020)] lg:gap-0 xl:gap-[var(--spacing-scale-020)]">
<div className="flex flex-col gap-[var(--spacing-scale-008)] lg:gap-[var(--spacing-scale-004)] xl:gap-[var(--spacing-scale-008)]">
<h3 className="text-left font-bricolage-grotesque text-[24px] font-medium leading-8 text-[var(--color-content-default-primary,white)] md:text-[32px] md:leading-[1.1] lg:text-[18px] lg:leading-[var(--spacing-scale-022)] xl:text-[32px] xl:leading-[1.1]">
{column.title}
</h3>
<div className="flex flex-col gap-[var(--spacing-scale-024)] font-inter text-[16px] font-normal leading-6 text-[var(--color-content-default-secondary)] md:text-[24px] md:leading-8 lg:gap-[var(--spacing-scale-020)] lg:text-[14px] lg:leading-5 xl:gap-[var(--spacing-scale-032)] xl:text-[24px] xl:leading-8">
<p>{column.description}</p>
{column.descriptionSecondary ? (
<p>{column.descriptionSecondary}</p>
) : null}
</div>
<article className="flex w-full flex-col gap-[var(--spacing-scale-006)] md:gap-[var(--spacing-scale-008)] lg:gap-[var(--spacing-scale-004)] xl:gap-[var(--spacing-scale-008)]">
<h3 className="text-left font-bricolage-grotesque text-[24px] font-medium leading-8 text-[var(--color-content-default-primary,white)] md:text-[32px] md:leading-[1.1] lg:text-[18px] lg:leading-[var(--spacing-scale-022)] xl:text-[32px] xl:leading-[1.1]">
{column.title}
</h3>
<div className="flex flex-col font-inter text-[16px] font-normal leading-6 text-[var(--color-content-default-secondary)] md:text-[24px] md:leading-8 lg:text-[14px] lg:leading-5 xl:text-[24px] xl:leading-8">
<p>{column.description}</p>
{column.descriptionSecondary ? (
<p className="mt-[var(--spacing-scale-024)] md:mt-[var(--spacing-scale-032)] lg:mt-0 lg:pt-[var(--spacing-scale-020)] xl:mt-[var(--spacing-scale-032)]">
{column.descriptionSecondary}
</p>
) : null}
</div>
</div>
</article>
);
}
@@ -82,7 +82,7 @@ function TripleTextBlockColumnLockup({
* Section horizontal padding adds **+ Scale/096** below `xl` (outer frame inset); **use cases `xl`** uses **Scale/160** only ([22085:860414](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22085-860414&m=dev)).
*
* Figma: use cases **`lg`** [22037:26994](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22037-26994&m=dev);
* **`md`** [22085:862437](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22085-862437&m=dev); stacked **22137:890676**;
* baseline **22112:871529** / **22085:860366**; **`md`** [22085:862437](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22085-862437&m=dev); stacked **22137:890676**;
* lg 3-col **22128:888715**; xl **22135:889705** (default preset).
*/
function TripleTextBlockView({
@@ -102,11 +102,11 @@ function TripleTextBlockView({
<section
{...(isUseCases ? { "data-figma-node": "22085-860414" } : {})}
aria-labelledby={hasSectionTitle ? headingId : undefined}
className={`bg-black px-[calc(var(--spacing-scale-032)+var(--spacing-scale-096))] py-[var(--spacing-scale-064)] md:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))] md:py-[var(--spacing-scale-064)] lg:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))] lg:py-[var(--spacing-scale-064)] ${
className={`bg-black py-[var(--spacing-scale-064)] xl:py-[var(--spacing-scale-064)] ${
isUseCases
? "xl:px-[var(--spacing-scale-160)]"
: "xl:px-[calc(var(--spacing-scale-160)+var(--spacing-scale-096))]"
} xl:py-[var(--spacing-scale-064)] ${className}`.trim()}
? "px-[var(--spacing-scale-032)] md:px-[var(--spacing-scale-096)] lg:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))] xl:px-[var(--spacing-scale-160)]"
: "px-[calc(var(--spacing-scale-032)+var(--spacing-scale-096))] md:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))] lg:px-[calc(var(--spacing-scale-096)+var(--spacing-scale-096))] xl:px-[calc(var(--spacing-scale-160)+var(--spacing-scale-096))]"
} ${className}`.trim()}
>
<div
className={