Files
community-rule/app/components/cards/CaseStudy/CaseStudy.view.tsx
T
adilalloandCursor c180e79c38 Give every public route its own description, and keep canonicals and structured data on the host that serves the page.
Decorative images on the marketing pages stay quiet, and every dialog close button is named Close.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-04 11:04:52 -07:00

74 lines
2.4 KiB
TypeScript

"use client";
import { memo } from "react";
import type { ComponentType, SVGProps } from "react";
import MutualAidArt from "../../../../public/assets/case-study/case-study-mutual-aid.svg";
import FoodNotBombsArt from "../../../../public/assets/case-study/case-study-food-not-bombs.svg";
import BoulderCountyStreetMedicsArt from "../../../../public/assets/case-study/case-study-boulder-county-street-medics.svg";
import type { CaseStudyProps } from "./CaseStudy.types";
const SURFACE_CLASS: Record<CaseStudyProps["surface"], string> = {
lavender: "bg-[var(--color-surface-invert-brand-lavender)]",
neutral: "bg-[var(--color-surface-invert-secondary)]",
rose: "bg-[var(--color-surface-invert-brand-red)]",
};
/**
* Inline SVGR components avoid the network round-trip the prior `next/image`
* version required, so the illustration paints with the colored tile shell.
*/
const SURFACE_ART: Record<
CaseStudyProps["surface"],
ComponentType<SVGProps<SVGSVGElement>>
> = {
lavender: MutualAidArt,
neutral: FoodNotBombsArt,
rose: BoulderCountyStreetMedicsArt,
};
const SURFACE_ART_DATA_KEY: Record<CaseStudyProps["surface"], string> = {
lavender: "case-study-mutual-aid",
neutral: "case-study-food-not-bombs",
rose: "case-study-boulder-county-street-medics",
};
/** Figma: ~23px corner (“Card / CaseStudy” shells). */
const CASE_TILE_RADIUS_CLASS = "rounded-[23.093px]";
function CaseStudyView({
surface,
imageAlt = "",
visual,
className = "",
}: CaseStudyProps) {
const Art = SURFACE_ART[surface];
const named = imageAlt.trim().length > 0;
return (
<div
data-figma-node="21993-32352"
className={`relative h-[305px] w-[305px] shrink-0 overflow-hidden ${CASE_TILE_RADIUS_CLASS} ${SURFACE_CLASS[surface]} ${className}`.trim()}
>
{visual ? (
<div className="flex size-full items-center justify-center p-2">{visual}</div>
) : (
<div className="absolute inset-0">
<Art
role={named ? "img" : undefined}
aria-label={named ? imageAlt : undefined}
aria-hidden={named ? undefined : true}
data-case-study-art={SURFACE_ART_DATA_KEY[surface]}
width="100%"
height="100%"
className="pointer-events-none block select-none"
preserveAspectRatio="xMidYMid meet"
/>
</div>
)}
</div>
);
}
CaseStudyView.displayName = "CaseStudyView";
export default memo(CaseStudyView);