docs / patterns / checklist-card
ChecklistCard
a card of short reassurances, each one ticked. for the feature and privacy claims on a landing page, three to five at a time.
intensity · structuresrsc · server
provenance
shaped from sisu-pluslayer
core / patternsintensity
structures · organizes a region, stays out of the contentcomposition
feature and privacy claims on landing pages, three to five itemsa custom marker when the tick reads wrong for the contentnot a todo list. nothing here is interactive or checkableno paragraphs as items. a claim is one linea11y
a realul with the item count · markers are aria-hidden · the title is a headingjest-axedependencies
Card · List from the same packagelive demo · try it out
Privacy
- Runs entirely on your machine
- No tracking, no analytics, no accounts
- Open source, end to end
customize
titleheading above the list, empty to omit
markerdecorative glyph before each item
usage
import { ChecklistCard } from "usva/patterns/checklist-card";
<ChecklistCard
title="Privacy"
items={["Runs entirely on your machine", "No tracking, no analytics, no accounts", "Open source, end to end"]}
/>props
| prop | type | default | notes |
|---|---|---|---|
| items | React.ReactNode[] | — | the claims. strings or nodes. |
| title | React.ReactNode | — | heading above the list. omitted entirely when absent. |
| marker | React.ReactNode | tick | overrides the default tick. decorative either way. |
get it
npx shadcn add https://usva.build/r/checklist-card.jsonsource · components/ui/checklist-card.tsxexactly what this command copies
import * as React from "react";
import { cn } from "@/lib/utils";
import { Card } from "./card";
import { List, ListItem } from "./list";
export interface ChecklistCardProps
extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
title?: React.ReactNode;
items: React.ReactNode[];
/** Defaults to a tick. Decorative either way. */
marker?: React.ReactNode;
}
/**
* A card of reassurances: short claims, each ticked. sisu renders these as bare divs
* with a bottom border, which reads to a screen reader as loose prose rather than a
* set of three related items.
*/
export const ChecklistCard = React.forwardRef<
HTMLDivElement,
ChecklistCardProps
>(({ className, title, items, marker, ...props }, ref) => (
<Card ref={ref} className={cn("p-4", className)} {...props}>
{title != null && (
<h3 className="px-3 pt-1 pb-2 text-base font-semibold tracking-[-0.01em] text-ink">
{title}
</h3>
)}
<List marker={marker ?? <TickIcon />} divided>
{items.map((item, index) => (
<ListItem key={typeof item === "string" ? item : index}>
{item}
</ListItem>
))}
</List>
</Card>
));
ChecklistCard.displayName = "ChecklistCard";
function TickIcon() {
return (
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<path d="M20 6 9 17l-5-5" />
</svg>
);
}