Files
sharper.ly/apps/web/app/components/ui/Card/CardCTA.tsx
T
2026-09-11 02:46:56 +02:00

98 lines
3.1 KiB
TypeScript

/* ============================================================================
Card.CTA - Figma 25:802 (720 x 141)
----------------------------------------------------------------------------
A call to action on the accent fill: eyebrow, headline, supporting line and
one outlined action. The action is the only interactive element, so this
card is never stretched over a link.
The panel carries data-surface="dark" because it is a dark green field
whatever the page around it is doing: inside it the focus ring, the hover
veil and every text role resolve for a dark background, on a light page too.
USAGE
-----
<Card.CTA
eyebrow="Ready to join us?"
headline="Empower your local community"
body="Apply now to join the upcoming civil dialogue summit and help draft public policies."
action={{ href: "/en/opportunities", label: "Learn more" }}
/>
// Arabic
<Card.CTA
headline="مكّن مجتمعك المحلي"
action={{ href: "/ar/opportunities", label: "اعرف المزيد" }}
/>
// External application form
<Card.CTA
headline="Call for expression of interest"
action={{ href: "https://forms.example.org/eoi", label: "Apply" }}
/>
========================================================================= */
import { Button } from "../Button";
import { CardLink, cx } from "./CardShell";
import type { CardLinkTarget, CardTitleElement } from "./types";
export interface CardCTAAction extends CardLinkTarget {
label: string;
}
export interface CardCTAProps {
headline: string;
action: CardCTAAction;
/** Small line above the headline ("Ready to join us?"). */
eyebrow?: string;
body?: string;
headlineAs?: CardTitleElement;
className?: string;
}
export function CardCTA({
headline,
action,
eyebrow,
body,
headlineAs = "h2",
className,
}: CardCTAProps) {
const Headline = headlineAs;
const { label, ...destination } = action;
return (
<section
data-surface="dark"
className={cx(
"sh-card relative flex flex-col gap-lg rounded-surface p-10",
"bg-surface-accent text-text-on-accent shadow-[var(--elevation-popover)]",
"sm:flex-row sm:items-center",
className,
)}
>
<div className="flex flex-1 flex-col gap-xs">
{eyebrow ? <p className="label-md">{eyebrow}</p> : null}
<Headline className="heading-h3">{headline}</Headline>
{/* Figma dims this line to 90%; left at full strength because white on
the accent green is already close to the AA floor. */}
{body ? <p className="body-md">{body}</p> : null}
</div>
{/* The outlined action is the project Button, not a look-alike: inside
this dark subtree its secondary variant already resolves to the white
stroke and white label the design asks for. CardLink keeps internal
hrefs routing client-side and external ones a plain anchor. */}
<Button
as={CardLink}
variant="secondary"
className="sh-card-cta-action shrink-0"
{...destination}
>
{label}
</Button>
</section>
);
}