Radio Cards
Card-based selection for single or multiple choices with icons, colors, and responsive grid layout.
Overview
RadioCards is the shared card-based selection component used when the user needs to compare and choose from a visible set of options.
It supports:
- single selection (default)
- multiple selection via
mode="multiple" - optional icons, descriptions, and semantic colors per card
- responsive grid layout with container-query breakpoints
- keyboard navigation and roving focus within the group
Use RadioCards when the options deserve visual comparison — status pickers, task types, dependency choices, and similar decision surfaces. For compact segmented toggles, prefer SegmentedControl. For simple yes/no, prefer BooleanRadio or Toggle.
SelectableChip is deprecated in favor of RadioCards.
Basic Usage
import { RadioCards } from '@fsai/shared-ui';
<RadioCards
value={selected}
onChange={setSelected}
options={[
{ value: 'planned', label: 'Planned', icon: 'CalendarCheck', color: 'blue' },
{ value: 'open', label: 'Open', icon: 'WorkspaceSolid', color: 'green' },
{ value: 'closed', label: 'Closed', icon: 'CircleBanSign', color: 'red' },
]}
aria-label="Status"
/>This is the pattern used in AddTaskModal.tsx for task-type classification.
With Descriptions
<RadioCards
value={selected}
onChange={setSelected}
options={[
{
value: 'location',
label: 'Location',
description: 'Create a new franchise location',
icon: 'LocationPin',
color: 'blue',
},
{
value: 'territory',
label: 'Territory',
description: 'Define a geographic territory',
icon: 'Map',
color: 'green',
},
]}
aria-label="Creation type"
/>Multiple Selection
<RadioCards
mode="multiple"
value={selectedIds}
onChange={setSelectedIds}
options={dependencies.map((dep) => ({
value: dep.id,
label: dep.name,
description: dep.summary,
color: dep.color,
}))}
aria-label="Phase dependencies"
/>Props
RadioCards
| Prop | Type | Default | Description |
|---|---|---|---|
options | Array<RadioCardOption> | — | Required. Card definitions. |
value | TValue | null (single) or TValue[] (multiple) | — | Required. Selected value(s). |
onChange | (value) => void | — | Required. Called when selection changes. |
mode | 'single' | 'multiple' | 'single' | Selection mode. |
disabled | boolean | false | Disables the entire group. |
className | string | — | Additional classes on the root. |
aria-label | string | — | Accessible group label. |
aria-labelledby | string | — | ID of an external label element. |
RadioCardOption
| Prop | Type | Description |
|---|---|---|
value | string | Required. Option identifier. |
label | ReactNode | Required. Primary card label. |
description | ReactNode | — |
icon | IconName | ComponentType | — |
color | RadioCardColor | — |
disabled | boolean | — |
title | string | — |
RadioCardColor
'blue' | 'gray' | 'green' | 'orange' | 'red' | 'purple' | 'yellow'
Radio Cards Primitive
For custom card layouts, use the low-level compound primitive exported as RadioCardsPrimitive (or the individual parts from @fsai/shared-ui primitives):
| Part | Purpose |
|---|---|
RadioCardsPrimitive.Root | Selection state, keyboard navigation, and group semantics. |
RadioCardsPrimitive.Item | Individual selectable card. |
RadioCardsPrimitive.Icon | Icon slot inside an item. |
RadioCardsPrimitive.Label | Label slot inside an item. |
RadioCardsPrimitive.Description | Description slot inside an item. |
RadioCardsPrimitive.Indicator | Selected-state checkmark indicator. |
Most feature code should use the high-level RadioCards component with an options array instead of composing the primitive manually.
Important Conventions
- Always provide
aria-labeloraria-labelledbyon the group. - The root uses
@containerand lays cards out in a responsive grid (1 → 2 → 3 → 4columns). - Keyboard navigation supports arrow keys and roving focus between cards.
- In single mode, clicking a selected card does not deselect it.
- In multiple mode, clicking toggles individual cards on and off.
Brand Dashboard And Shared Usage
| Pattern | Path | Notes |
|---|---|---|
| Task type picker | fsai/apps/brand-dashboard/src/pages/Projects/components/AddTaskModal.tsx | Single-select cards with icon, label, and description. |
| Phase dependencies | fsai/apps/brand-dashboard/src/modules/projects/components/PhaseDependenciesField/PhaseDependenciesField.tsx | Multiple-select dependency cards. |
| Location creation | fsai/apps/brand-dashboard/src/modules/locations/components/CreateLocationModal/CreateLocationModal.tsx | Path-selection cards inside a guided flow. |
| Connect accounts | fsai/packages/shared-ui/src/modules/socials/components/ConnectAccountsModal.tsx | Account connection choice cards. |
Guidelines
- Do use
RadioCardswhen options should be compared visually - Do provide meaningful icons and colors when they carry semantic signal
- Do use
mode="multiple"for multi-select card groups - Don't use
RadioCardsfor simple binary on/off settings — useToggleorBooleanRadio - Don't use
SelectableChipin new code — it is deprecated