Checkbox Cards
Card-style multi-select. Each card has a built-in checkbox with highlighted selected state.
Examples
Multi-select cards
Card-style multi-select with highlighted state and a live list of choices.
Enabled: analytics
import { CheckboxCards, CheckboxCardsItem } from "@codefast/ui/checkbox-cards";
import { useState } from "react";
const FEATURES = [
{ value: "analytics", label: "Analytics", description: "Track usage and insights" },
{ value: "notifications", label: "Notifications", description: "Email and push alerts" },
{ value: "api", label: "API access", description: "Integrate with external tools" },
];
export function CheckboxCardsFeatures() {
const [selected, setSelected] = useState<Array<string>>(["analytics"]);
return (
<div className="w-full max-w-xs space-y-3">
<CheckboxCards className="grid gap-2" value={selected} onValueChange={(value) => setSelected(value ?? [])}>
{FEATURES.map(({ value, label, description }) => (
<CheckboxCardsItem key={value} value={value}>
<div className="flex flex-col gap-0.5 text-start">
<span className="text-sm font-medium">{label}</span>
<span className="text-xs text-ui-muted">{description}</span>
</div>
</CheckboxCardsItem>
))}
</CheckboxCards>
<p className="text-center text-xs text-ui-muted">
Enabled: <span className="font-medium text-ui-fg">{selected.join(", ") || "none"}</span>
</p>
</div>
);
}
Two columns
Lay cards out in a grid for compact add-on pickers.
import { CheckboxCards, CheckboxCardsItem } from "@codefast/ui/checkbox-cards";
import { useState } from "react";
const ADDONS = [
{ value: "ci", label: "CI minutes" },
{ value: "seats", label: "Extra seats" },
{ value: "storage", label: "More storage" },
{ value: "support", label: "Priority support" },
];
export function CheckboxCardsColumns() {
const [selected, setSelected] = useState<Array<string>>(["ci", "storage"]);
return (
<CheckboxCards
className="grid w-full max-w-sm grid-cols-2 gap-2"
value={selected}
onValueChange={(value) => setSelected(value ?? [])}
>
{ADDONS.map(({ value, label }) => (
<CheckboxCardsItem key={value} value={value}>
<span className="text-sm font-medium">{label}</span>
</CheckboxCardsItem>
))}
</CheckboxCards>
);
}
Disabled option
Mark an option unavailable while keeping it visible.
import { CheckboxCards, CheckboxCardsItem } from "@codefast/ui/checkbox-cards";
import { useState } from "react";
const PLANS = [
{ value: "free", label: "Free", description: "Up to 3 projects", disabled: false },
{ value: "pro", label: "Pro", description: "Unlimited projects", disabled: false },
{ value: "enterprise", label: "Enterprise", description: "Contact sales", disabled: true },
];
export function CheckboxCardsDisabled() {
const [selected, setSelected] = useState<Array<string>>(["pro"]);
return (
<CheckboxCards
className="grid w-full max-w-xs gap-2"
value={selected}
onValueChange={(value) => setSelected(value ?? [])}
>
{PLANS.map(({ value, label, description, disabled }) => (
<CheckboxCardsItem key={value} value={value} {...(disabled ? { disabled } : {})}>
<div className="flex flex-col gap-0.5 text-start">
<span className="text-sm font-medium">{label}</span>
<span className="text-xs text-ui-muted">{description}</span>
</div>
</CheckboxCardsItem>
))}
</CheckboxCards>
);
}
Usage
The minimal import and composition — see Examples below for styled, real-world variants.
import { CheckboxCards, CheckboxCardsItem } from "@codefast/ui/checkbox-cards";
export function CheckboxCardsUsage() {
return (
<CheckboxCards className="grid grid-cols-2 gap-3" defaultValue={["storage"]}>
<CheckboxCardsItem value="storage">Extra storage</CheckboxCardsItem>
<CheckboxCardsItem value="support">Priority support</CheckboxCardsItem>
</CheckboxCards>
);
}
Anatomy
How the parts nest — every slot the component exposes, in composition order.
Features
- Each CheckboxCardsItem already renders its own Label wrapping the checkbox and its children — the whole card is clickable, no separate <Label htmlFor> needed.
- Built on the same multi-select headless primitive as Checkbox Group, styled as selectable cards sharing one value array.
API reference
Props for each part of the component. All native element props are also forwarded.
CheckboxCards
A multi-selection group of cards sharing one value array.
valuestring[]The controlled list of selected card values.
defaultValuestring[]The selected card values when initially rendered (uncontrolled).
onValueChange(value: string[]) => voidCalled when the selected card values change.
CheckboxCardsItem
valuestringAdded to the array when the card is selected (required).
disabledbooleanMakes a single card non-selectable.
Default
false
Accessibility
Built to be keyboard-navigable and screen-reader friendly out of the box.
| Key | Function |
|---|---|
| Tab | Moves between cards. |
| Space | Toggles the focused card. |
- Each card is a checkbox with its own aria-checked.
- The whole card is the hit target, not just a small box.
- Keep card content concise so the selected state reads clearly.
Guidelines
Conventions that keep usage consistent across an app.
Do
- Use for picking several rich options (features, add-ons).
- Show a short description on each card.
Don’t
- Don’t use for single-select — that’s Radio Cards.
- Don’t put multiple actions inside a card.
Explore further
Ready to integrate?
Follow the Getting Started guide to install @codefast/ui, or browse the full component gallery.