Thrive Design System

Components

Radio Card

A card-style radio button for visually prominent single-selection choices with icon, label, and description support.

Installation

npm install @thrivecart/ui
yarn add @thrivecart/ui
pnpm add @thrivecart/ui
bun add @thrivecart/ui

Usage

import { RadioCard, RadioCardItem } from '@thrivecart/ui';

Examples

Basic

Plan Selection

Radio cards for selecting a pricing plan

For individuals getting started

For growing businesses

For large organizations

<RadioCard defaultValue="pro" className="max-w-md">
<RadioCardItem value="starter" label="Starter" description="For individuals getting started" />
<RadioCardItem value="pro" label="Pro" description="For growing businesses" />
<RadioCardItem value="enterprise" label="Enterprise" description="For large organizations" />
</RadioCard>

With Indicator

The indicator renders a radio dot inside the card. Control its position with indicatorPlacement ('start', 'end'), or hide it with indicator={null}.

Indicator Placement

Radio indicator at different positions, or hidden

Indicator at end (default)

Billed every month

Billed once a year — save 20%

Indicator at start

Billed every month

Billed once a year — save 20%

No indicator

Billed every month

Billed once a year — save 20%

{/* End (default) */}
<RadioCardItem value="a" label="Option" description="..." />

{/* Start */}
<RadioCardItem indicatorPlacement="start" value="b" label="Option" description="..." />

{/* Hidden */}
<RadioCardItem indicator={null} value="c" label="Option" description="..." />

With Icons

Cards with Icons

Radio cards with leading icons

Up to 1,000 contacts

Up to 10,000 contacts

Unlimited contacts

<RadioCard defaultValue="pro" className="max-w-md">
<RadioCardItem
  value="starter"
  icon={<MdRocketLaunch className="size-5 text-icon" />}
  label="Starter"
  description="Up to 1,000 contacts"
/>
<RadioCardItem
  value="pro"
  icon={<MdSpeed className="size-5 text-icon" />}
  label="Pro"
  description="Up to 10,000 contacts"
/>
<RadioCardItem
  value="enterprise"
  icon={<MdStar className="size-5 text-icon" />}
  label="Enterprise"
  description="Unlimited contacts"
/>
</RadioCard>

Grid Layout

Grid Layout

Cards in a multi-column grid for layout selection

Card-based layout

Detailed list view

Compact grid view

<RadioCard defaultValue="grid" className="grid-cols-3 max-w-2xl">
<RadioCardItem
  value="module"
  icon={<MdViewModule className="size-5 text-icon" />}
  label="Module"
  description="Card-based layout"
/>
<RadioCardItem
  value="list"
  icon={<MdViewList className="size-5 text-icon" />}
  label="List"
  description="Detailed list view"
/>
<RadioCardItem
  value="grid"
  icon={<MdGridView className="size-5 text-icon" />}
  label="Grid"
  description="Compact grid view"
/>
</RadioCard>

With Addon

Cards with Addon

Radio cards with additional metadata

Visa, Mastercard, Amex

Processing fee: 2.9%

Direct ACH payment

No fee

Pay with PayPal balance

Processing fee: 3.4%
<RadioCard defaultValue="card" className="max-w-md">
<RadioCardItem
  value="card"
  icon={<MdCreditCard className="size-5 text-icon" />}
  label="Credit Card"
  description="Visa, Mastercard, Amex"
  addon={<span className="text-xs text-ink-muted">Processing fee: 2.9%</span>}
/>
<RadioCardItem
  value="bank"
  icon={<MdAccountBalance className="size-5 text-icon" />}
  label="Bank Transfer"
  description="Direct ACH payment"
  addon={<span className="text-xs text-ink-muted">No fee</span>}
/>
<RadioCardItem
  value="paypal"
  icon={<MdPayment className="size-5 text-icon" />}
  label="PayPal"
  description="Pay with PayPal balance"
  addon={<span className="text-xs text-ink-muted">Processing fee: 3.4%</span>}
/>
</RadioCard>

Disabled

Disabled State

Disabled radio cards

This option can be selected

This option is not available

<RadioCard defaultValue="active" className="max-w-md">
<RadioCardItem value="active" label="Active Option" description="This option can be selected" />
<RadioCardItem value="disabled" label="Disabled Option" description="This option is not available" disabled />
</RadioCard>

Best Practices

Limit options to 3-5

Keep the number of radio cards manageable. Too many options cause decision fatigue.

Pre-select a recommended option

When appropriate, pre-select the most common or recommended option.

Don't use without descriptions

If options don't need descriptions, use standard RadioGroup instead.

Don't mix with regular radio buttons

Use either card radios or standard radios within the same form section.

Props

PropTypeDefaultDescription
valuestring-Unique value for the radio item
labelReactNode-Card title text
descriptionReactNode-Card description text
iconReactElement-Leading icon element
addonReactNode-Additional content below the description
indicatorReactNode | nullDefault radio dotCustom indicator element, or null to hide
indicatorPlacement'start' | 'end''end'Position of the indicator
disabledbooleanfalseDisable the radio card
classNamestring-Additional className for the card wrapper

RadioCard (Group) Props

PropTypeDefaultDescription
valuestring-Controlled selected value
defaultValuestring-Default selected value (uncontrolled)
onValueChange(value: string) => void-Callback when selection changes
classNamestring-Additional className for the group

Accessibility

  • Only one option can be selected at a time within a group.
  • Arrow keys navigate between options, Space/Enter selects.
  • Selected state is communicated via aria-checked.
  • Uses role="radiogroup" for the container.