You're in the Library

ChoiceCard

One choice among two to four options that each need a title and a short description, shown as cards: Keep mine or Use the library's, a starting brand, a corner style. The whole card is the click target.
Stable
Edit

Preview appears after the next Storybook update.

ChoiceCard example
<ChoiceCard />
Rendered with the real componentFrom the code
Light
Dark

When to use

Use it for

  • A decision where each option needs a line of explanation or a value to compare: resolving a conflict, picking a starting brand.
  • Two to four options. Side by side (horizontal, the default) when the reader compares them; they stack on their own when they no longer fit.
  • vertical when the descriptions are long or the options are a ranked list.
  • Put a TokenValue in description when the choice is between token values, so the reader sees what each card keeps.
  • hideLabel when the row around the group already asks the question; the legend stays the accessible name.

Not for

  • Options a short label explains on its own: use RadioGroup.
  • Switching a view or a mode that applies at once: use SegmentedControl.
  • Several options the reader can pick together: use Checkbox.
  • More than four options: use RadioGroup or Select.

Do and don't

Every example is rendered with the real component, so it always matches what ships.

Starting brand
Do

Titles are the choice, descriptions are the consequence

The title says what the reader picks in a few words, the description says what happens or what it keeps.

Corner style
Do

Ask the question in the legend

The legend names the decision, as a question or a noun, so the cards read as answers.

Theme
Don't

Cards for one-word options

When the titles say it all and nothing needs comparing, cards take room for nothing. Use RadioGroup.

Which value should this change keep?
Don't

Descriptions that repeat the title

"Keep mine: keeps your value" says it twice. Show the value instead, or what changes.

Accessibility

  • A fieldset with a legend around a Base UI RadioGroup: the legend names the group, each card is a radio named by its title.
  • Each card's description is linked to its radio with aria-describedby, so screen readers read it after the title. The group description and error are linked to the group.
  • Tab enters the group on the selected card and leaves it; arrow keys move the selection.
  • The selected card shows the checked radio, a Deep Harbor edge and the selected surface: never color alone.
  • A disabled card is skipped by the arrow keys and cannot be picked; say why in its description.
  • The focus ring (focus.ring.color) shows on the radio on keyboard focus only.

Content guidelines

  • Legend: the decision, as a question or a noun, sentence case: "Which value should this change keep?", "Starting brand".
  • Title: a verb or a short name, a few words: "Keep mine", "Use the library's", "Ocean".
  • Description: one or two lines, the consequence or the value. No period after a lone value.
  • Error: what to do, not what went wrong: "Pick a value before you add it to the library."

From the code Generated from the component, not editable here.

Anatomy and tokens

Read from packages/react/src/components/ChoiceCard/ChoiceCard.module.css at build time. Every value is a token: open one to see its alias chain in both themes.

26 own tokens27 from RadioGroup16 semantic or component, change with theme and brand1 density, change with comfortable or compact9 from the shared scales

From RadioGroup

ChoiceCard reuses the stylesheet of RadioGroup, so it also paints with these 27 tokens. Changing them changes both.

Motion and interaction

ChoiceCard animates on hover, check and uncheck. Try it in the preview at the top.

WhenWhat changesDurationEasing
HoverBackground and bordermotion.duration.instant75 msmotion.easing.standardsettles in place
Check and uncheckBackground, border and movementmotion.duration.fast150 msmotion.easing.enterstarts fast, lands softly

With reduced motion turned on, every change happens at once.

From the code Generated from the component, not editable here.

Props

Parsed from the TypeScript types in packages/react/src/components/ChoiceCard/ChoiceCard.tsx, so this table cannot drift from the code.

PropTypeDefaultDescription
valuerequiredstringnoneValue selected when this card is chosen.
titlerequiredReactNodenoneThe option, as a verb or a short name: "Keep mine", "Use the library's".
descriptionReactNodenoneWhat choosing it means, or the value it keeps (a TokenValue). One or two lines.
disabledbooleannoneNo description in the code yet.
classNamestringnoneNo description in the code yet.

Playground

Change the props and see the real ChoiceCard update. Controls are generated from the TypeScript props; nothing here changes the system.

Code for these props
<ChoiceCard
  value="mine"
  title="Keep mine"
  description="{color.harbor.600}, the value in your change."
/>

Workbench

For contributors: every state with the accessibility panel, in the component workbench (Storybook). The stories double as visual test fixtures; the guidance on this page is the user documentation (open ChoiceCard in Storybook).

Embed Storybook stories here (7)

Loads from https://bridge-storybook.floriangouloubi.com (set STORYBOOK_URL at build time). If Storybook is not running, the frames stay empty.

Conflict

StartingBrand

Vertical

WithError

DisabledCard

NarrowConflict

AllStates

From the code Generated from the component, not editable here.

Changelog

  • Fix

    Component scan: Storybook story ids keep a camel-case title word whole (Forms/ChoiceCard is forms-choicecard), so Library previews of multi-word components open the right story

    v1.0.0, Nov 11, 2026

  • Fix

    Stories per Figma variant for the sets whose checked state comes from their group (ChoiceCard, Radio, MenuRadioItem), with a checked arg the render turns into the group's value, so the Storybook measure maps each story to its variant

    v1.0.0, Nov 11, 2026

All release notes