Radio Card

Radio Card is a bordered, card-sized option for choosing exactly one of a few choices. Use it when each option needs a description or visual.

  • Beta
  • Accessibility
  • Figma Radio Card 4457:60026 (row) and 3045:53929 (stacked)
  • packages/ui/src/components/ChoiceCard

Beta until the focus indicator (C5) is resolved and design confirms the code-only focused card and the disabled text colours (C49, FC-20), and the code-only RadioGroup wrapper. Everything else on this page is implemented and tested.

Preview

Change the controls to try every supported combination. The cards are a controlled RadioGroup: click anywhere on a card to select it.

Learning path
New

Lessons unlock in order, with a quiz after each unit.

Open any lesson in any order.

tsx
<RadioGroup label="Learning path" value={path} onValueChange={setPath}>
  <RadioCard
    value="guided"
    label="Guided path"
    sublabel="(Recommended)"
    badge={<Badge size="sm" color="blue" appearance="light">New</Badge>}
    description="Lessons unlock in order, with a quiz after each unit."
    leading={<KeyIcon icon={<RiKey2Line />} size={40} />}
  />
  <RadioCard value="free" label="Free explore" description="Open any lesson in any order." />
</RadioGroup>

Installation

Availability

@nuton/ui and @nuton/tokens are private workspace packages and aren't published yet (D4, D12). Inside the Nuton monorepo, add them as workspace dependencies.

bash
pnpm add @nuton/ui @nuton/tokens @remixicon/react
tsx
import '@nuton/tokens/tokens.css'
import '@nuton/ui/styles.css'

Usage

tsx
import { RadioCard, RadioGroup } from '@nuton/ui'

<RadioGroup label="Choose a plan" name="plan" defaultValue="pro">
  <RadioCard value="free" label="Free" description="3 courses, community support." />
  <RadioCard value="pro" label="Pro" sublabel="($8/month)" description="Unlimited courses and AI tutor feedback." />
</RadioGroup>
  • Use cards when each option needs a description, price or visual. For short options, use Radio.
  • Always put cards in a RadioGroup. It shares the name, holds the value, names the set with its legend and gives native arrow-key movement. Cards stretch to the group's width (Figma 360px).
  • The whole card is the click target. Each card needs a value.
  • Preselect the most common or safest option unless the choice must be deliberate.
  • The leading visual is decorative. Use a 40px KeyIcon, Avatar or a logo your app supplies.

Variants and sizes

Radio Card has one size. Figma's Type property only changes the leading visual, so code takes any 40px element in `leading`.

Types (leading visual)

Leading visual

No leading visual.

A 40px key icon.

A 40px avatar.

Card Provider, Brand and Company show third-party logos in Figma. Nuton ships no brand assets (D12), so pass your own <img alt=""> or SVG; it is sized to the 40px slot.

Layout

The default row puts the text between the leading visual and the radio. layout="stacked" puts the visual and the radio on one row with the text below, which suits short choices in a two-column grid, such as the onboarding questions.

Tutor

Formal, structured, academic.

Encouraging and confidence building.

Stacked cards draw the selected state with a 2px primary stroke, as Figma's Active variant does (3045:53929). Row cards keep the 1px stroke. Both are code-only choices pending design (C83).

Text options

Learning path
New

Lessons unlock in order, with a quiz after each unit.

PartMeasurement
CardFills its group (Figma 360 × 72), radius 12, padding 16, gap 14, 1px stroke
Leading slot40 × 40
Text columnGap 4; title row gap 4, items centred
Label · sublabel · descriptionLabel/Small · Paragraph/X Small · Paragraph/X Small
Control20px Radio at the trailing edge, top-aligned
Between cards12 (RadioGroup gap, code-only)
Stacked cardFigma 262 × 126: padding 16, gap 14, vertical; a 40px head row (leading at the start, radio at the end), text below; Active 2px stroke

States and interactions

DefaultBg/White, 1px Stroke/Soft-200, regular-shadow/x-small.
HoverBg/Weak-50 with no stroke or shadow. Only on hover-capable pointers.
Active (selected)Bg/White with a 1px State/Primary/Base stroke; the radio fills primary.
Focus (code-only)Figma has no focused card. Code adds the primary stroke and the primary focus halo, below 3:1 today (C5).

Not on your plan.

DisabledWhite with a Soft-200 stroke; label, sublabel and description Sub-600. Disable the group or one card.

State tokens

Set on .nu-choice-card, shared with Checkbox Card: --nu-choice-card-bg (Bg/White), -bg-hover (Bg/Weak-50), -stroke (Stroke/Soft-200), -stroke-checked (State/Primary/Base), -shadow (regular-shadow/x-small) and -focus-shadow (buttons/primary-focus).

Figma discrepancies (pending a decision)

  • Radio Card binds the remote 01-Tokens library for its white background, Soft-200 stroke and Weak-50 hover. Code maps them to the local tokens of the same name (C19).
  • FC-20: disabled sublabel and description are Sub-600 here but Soft-400 on Checkbox Card. Code follows each component; proposal: align both.
  • Disabled badges switch to Gray Light with a Soft-200 stroke in Figma. Pass <Badge color="gray" appearance="stroke"> when the card is disabled.
  • The radio uses the darker unselected ring approved in C48. Figma defines no group; the 12px gap and legend come from the code-only RadioGroup.

Composition examples

Plan picker

A controlled group with prices in the sublabel and a badge for the popular plan.

Choose a plan

3 courses, community support.

Popular

Unlimited courses and AI tutor feedback.

Shared spaces, progress reports and admin tools.

Selected: pro

API reference

Props

Radio Card props
PropTypeDefaultDescription
valuerequiredstring—This option's value, compared with the RadioGroup's value.
labelrequiredReactNode—Figma Label. The accessible name; a click anywhere on the card selects it.
sublabelReactNode—Figma Sublabel, e.g. "($8/month)". Part of the accessible name.
badgeReactNode—Figma Badge. Rendered outside the label, so not part of the name.
descriptionReactNode—Figma Description. Linked with aria-describedby.
leadingReactNode—Figma Type: a decorative 40px visual (KeyIcon, Avatar or your logo).
layout"row" | "stacked""row"Row: visual, text and radio side by side. Stacked: visual and radio on top, text below (Figma 3045:53929).
disabledboolean—Disables this card. Inherits the group's disabled when omitted.
invalidboolean—Marks the option invalid. Inherits from the RadioGroup when omitted.
classNamestring—Class for the card.
…input propsInputHTMLAttributes—id, onChange and other attributes go to the native radio. The ref points at the input. Outside a RadioGroup, pass name and checked yourself.

Accessibility

Keyboard

KeyBehaviour
TabMoves focus into the group, to the selected card
↑ / ↓Selects the previous or next card
SpaceSelects the focused card

Screen readers

Native radios in a fieldset named by the legend. Each is named by its label and sublabel and described by its description; the badge and leading visual are not part of the name.

Focus

Focus stays on the native input; the whole card shows the primary stroke and halo.

Contrast and colour

Label 17.93:1, description 6.69:1. The selected stroke is State/Primary/Base, and the radio fill also shows the state, so it doesn't rely on the border colour alone.

Touch and pointer

The whole card, at least 52px tall, is the target, well above 24 × 24 (WCAG 2.5.8).

You must: put cards in a RadioGroup with a label, and give each card a unique, meaningful label.

Figma mapping

Figma propertyFigma valuesCode
TypeBasic · Left Icon · Avatar · Card Provider · Brand · Companyleading (none for Basic)
Radio Card [1.1] 3045:53929: Property 1Default · Active (vertical)layout="stacked"; Active is the group's value
StateDefault · Hover · Active · DisabledInteractive states, the group's value and disabled
Label · Sublabel · DescriptionText · boolean + text · textlabel · sublabel · description
BadgeBooleanbadge (pass a Badge)
Provider · Brand · CompanyInstance swapYour logo in leading
(none)No group componentRadioGroup (code-only)

Guidelines and related components

Use Radio Card for

  • Two to five options that each need a description, price or visual
  • Plans, learning paths or sign-in methods

Don't use Radio Card for

  • Many or short options (use Radio or Select)
  • Choosing several options (use Checkbox Card)

Do and don't

Lesson length

Fits a short break.

Covers a full unit.

DoGroup cards and preselect a sensible default People see the recommended choice and can change it.
Notifications
Don'tUse a single radio card One option can't be unselected, so it is not a choice. Use a Checkbox Card.