Implement use cases page
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import CaseStudyView from "./CaseStudy.view";
|
||||
import type { CaseStudyProps } from "./CaseStudy.types";
|
||||
|
||||
/**
|
||||
* Figma: Section org lockup ([22112-871524](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22112-871524)): **Card / CaseStudy** — MAC vector (`assets/case-study/`), FNB/BCSM rasters (**21993‑32352** / **32353**).
|
||||
*/
|
||||
const CaseStudyContainer = memo<CaseStudyProps>((props) => {
|
||||
return <CaseStudyView {...props} />;
|
||||
});
|
||||
|
||||
CaseStudyContainer.displayName = "CaseStudy";
|
||||
|
||||
export default CaseStudyContainer;
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export const CASE_STUDY_SURFACE_OPTIONS = ["lavender", "neutral", "rose"] as const;
|
||||
|
||||
export type CaseStudySurfaceValue = (typeof CASE_STUDY_SURFACE_OPTIONS)[number];
|
||||
|
||||
export interface CaseStudyProps {
|
||||
surface: CaseStudySurfaceValue;
|
||||
/**
|
||||
* Alt text for built-in raster art (`public/assets/use-cases/`) when **`visual`** is omitted.
|
||||
*/
|
||||
imageAlt?: string;
|
||||
/** Overrides built-in raster with custom slot content when provided. */
|
||||
visual?: ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { memo } from "react";
|
||||
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)]",
|
||||
};
|
||||
|
||||
/** Default art per tile: PNG composites (FNB/BCSM) or vector Mutual Aid logo. */
|
||||
const SURFACE_ART: Record<CaseStudyProps["surface"], string> = {
|
||||
lavender: "/assets/case-study/case-study-mutual-aid.svg",
|
||||
neutral: "/assets/use-cases/case-study-food-not-bombs.png",
|
||||
rose: "/assets/use-cases/case-study-boulder-county-street-medics.png",
|
||||
};
|
||||
|
||||
/** Figma: ~23px corner (“Card / CaseStudy” shells). */
|
||||
const CASE_TILE_RADIUS_CLASS = "rounded-[23.093px]";
|
||||
|
||||
function CaseStudyView({
|
||||
surface,
|
||||
imageAlt = "",
|
||||
visual,
|
||||
className = "",
|
||||
}: CaseStudyProps) {
|
||||
return (
|
||||
<div
|
||||
data-figma-node="21993-32352"
|
||||
className={`relative flex 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>
|
||||
) : (
|
||||
<Image
|
||||
src={SURFACE_ART[surface]}
|
||||
alt={imageAlt}
|
||||
width={305}
|
||||
height={305}
|
||||
unoptimized={
|
||||
SURFACE_ART[surface].endsWith(".svg") ? true : undefined
|
||||
}
|
||||
className={`pointer-events-none select-none ${
|
||||
surface === "lavender" ? "object-contain object-center" : "object-cover"
|
||||
}`}
|
||||
draggable={false}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CaseStudyView.displayName = "CaseStudyView";
|
||||
|
||||
export default memo(CaseStudyView);
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default } from "./CaseStudy.container";
|
||||
export type { CaseStudyProps, CaseStudySurfaceValue } from "./CaseStudy.types";
|
||||
export { CASE_STUDY_SURFACE_OPTIONS } from "./CaseStudy.types";
|
||||
Reference in New Issue
Block a user