Choice Card
Radio options drawn as cards — icon, title, description — two across from @sm.
- Status
- Since
0.23.116- Accessibility pattern
- radio group; each card labels its radio; arrows move
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Choice Card before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify choice-cardInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/choice-cardRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/field, @vegastack/radio-group.
Usage
import { ChoiceCard, ChoiceCardGroup } from "@/components/ui/choice-card";
<ChoiceCardGroup aria-label="Access" value={access} onValueChange={setAccess}>
<ChoiceCard
value="open"
icon={<Globe />}
title="Open"
description="Everyone can find and join"
/>
<ChoiceCard
value="private"
icon={<Lock />}
title="Private"
description="Only members can find and open it"
/>
</ChoiceCardGroup>;A thin wrapper over the documented Field choice-card pattern (FieldLabel around a horizontal
Field with a RadioGroupItem): the look, the hover and the checked tint are Field's and
RadioGroup's own. The group lays the cards out two across once its own container is @sm wide, and
stacks them below that.
Scope
- Owns: the card layout and the two-across grid.
- Does not own: the radio behaviour (RadioGroup) or the card surface (Field).
- Compose with:
SettingsRow(a stacked row), forms.
Anatomy
Examples
Disabled option
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
title* | React.ReactNode | — | The option's name. |
value* | string | — | The option's value. |
className | string | — | Classes for the card. |
description | React.ReactNode | — | One muted line under the title. |
disabled | boolean | false | Shown but not choosable. |
icon | React.ReactNode | — | A leading icon (a lucide icon), drawn muted at 16px. |
id | string | — | The radio's id; one is generated when omitted. |
Data attributes and CSS variables on ChoiceCard
| Attribute | Values |
|---|---|
data-disabled | "true" |
data-slot | "choice-card" | "choice-card-icon" |
ChoiceCardGroup takes RadioGroup's props (value, defaultValue, onValueChange, disabled).
Accessibility
- A radio group: name it with
aria-labeloraria-labelledby. Each card is its radio's label, so the title and description are the radio's name.
| Key | Action |
|---|---|
| Tab | Into and out of the group |
| ↑ / ↓ | Move and choose |
| Contract | States tested |
|---|---|
| Behaviour | unchecked, checked, disabled, keyboard |
| Accessibility | labeled, keyboard, browser-accessibility-test |
| Visual | default, hover, focus |