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
@@ -10,11 +10,11 @@ const SURFACE_CLASS: Record<CaseStudyProps["surface"], string> = {
rose: "bg-[var(--color-surface-invert-brand-red)]",
};
/** Default art per tile: PNG composites (FNB/BCSM) or vector Mutual Aid logo. */
/** Default art per tile: Figma-exported SVG composites (305×305 incl. rounded bg). */
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",
neutral: "/assets/case-study/case-study-food-not-bombs.svg",
rose: "/assets/case-study/case-study-boulder-county-street-medics.svg",
};
/** Figma: ~23px corner (“Card / CaseStudy” shells). */
@@ -39,12 +39,8 @@ function CaseStudyView({
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"
}`}
unoptimized
className="pointer-events-none size-full select-none object-contain object-center"
draggable={false}
/>
)}
@@ -28,6 +28,8 @@ const RuleContainer = memo<RuleProps>(
onDescriptionClick,
descriptionEmptyHint,
descriptionEditAriaLabel,
onTitleClick,
titleEditAriaLabel,
icon,
backgroundColor = "bg-[var(--color-community-teal-100)]",
className = "",
@@ -84,6 +86,8 @@ const RuleContainer = memo<RuleProps>(
onDescriptionClick={onDescriptionClick}
descriptionEmptyHint={descriptionEmptyHint}
descriptionEditAriaLabel={descriptionEditAriaLabel}
onTitleClick={onTitleClick}
titleEditAriaLabel={titleEditAriaLabel}
icon={icon}
backgroundColor={backgroundColor}
className={className}
+9
View File
@@ -39,6 +39,13 @@ export interface RuleProps {
descriptionEditAriaLabel?: string;
/** Shown when {@link onDescriptionClick} is set and `description` is empty. */
descriptionEmptyHint?: string;
/**
* When set, the title in the card header is clickable — caller handles modal /
* navigation (e.g. edit published rule).
*/
onTitleClick?: () => void;
/** When {@link onTitleClick} is set, forwarded to the controls `aria-label`. */
titleEditAriaLabel?: string;
icon?: React.ReactNode;
backgroundColor?: string;
className?: string;
@@ -80,6 +87,8 @@ export interface RuleViewProps {
onDescriptionClick?: () => void;
descriptionEmptyHint?: string;
descriptionEditAriaLabel?: string;
onTitleClick?: () => void;
titleEditAriaLabel?: string;
icon?: React.ReactNode;
backgroundColor: string;
className: string;
+23 -5
View File
@@ -14,6 +14,8 @@ export function RuleView({
onDescriptionClick,
descriptionEmptyHint,
descriptionEditAriaLabel,
onTitleClick,
titleEditAriaLabel,
icon,
backgroundColor,
className,
@@ -307,11 +309,27 @@ export function RuleView({
{t("recommendedLabel")}
</Tag>
) : null}
<h3
className={`${titleClass} cursor-inherit text-[var(--color-content-invert-primary)] overflow-hidden text-ellipsis w-full`}
>
{title}
</h3>
{onTitleClick ? (
<InlineTextButton
type="button"
underline={false}
data-testid="rule-title-edit"
ariaLabel={titleEditAriaLabel}
className={`${titleClass} w-full min-w-0 cursor-pointer text-left text-[var(--color-content-invert-primary)] hover:!opacity-100 overflow-hidden text-ellipsis`}
onClick={(e) => {
e.stopPropagation();
onTitleClick();
}}
>
{title}
</InlineTextButton>
) : (
<h3
className={`${titleClass} cursor-inherit text-[var(--color-content-invert-primary)] overflow-hidden text-ellipsis w-full`}
>
{title}
</h3>
)}
</div>
</div>
)}