Checkbox Card

Checkbox Card is a bordered, card-sized checkbox for choosing any number of options. Use it when each option needs a description or visual.

  • Beta
  • Accessibility
  • Figma Checkbox Card 427:24878
  • 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). Everything else on this page is implemented and tested.

Preview

Change the controls to try every supported combination. The card is controlled: click anywhere on it and the code follows.

New

A short nudge at 7 pm to keep your streak going.

tsx
const [checked, setChecked] = useState(true)

<CheckboxCard
  label="Daily study reminder"
  sublabel="(Recommended)"
  badge={<Badge size="sm" color="blue" appearance="light">New</Badge>}
  description="A short nudge at 7 pm to keep your streak going."
  leading={<KeyIcon icon={<RiKey2Line />} size={40} />}
  checked={checked}
  onCheckedChange={setChecked}
/>

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 { CheckboxCard, KeyIcon } from '@nuton/ui'
import { RiTimerLine } from '@remixicon/react'

<CheckboxCard
  name="goals"
  value="exams"
  label="Prepare for exams"
  description="Timed practice tests and spaced review."
  leading={<KeyIcon icon={<RiTimerLine />} size={40} />}
/>
  • Use cards when each option needs a description, price or visual. For a plain list of options, use Checkbox.
  • The whole card is the click target. The control is a native checkbox, so name, value, required and form submission work as usual.
  • Stack cards in a column and give the set a heading or a Field label. Cards fill their container's width (Figma 360px).
  • Keep labels short and parallel. Put detail in description, which is announced after the name.
  • The leading visual is decorative. Use a 40px KeyIcon, Avatar or a logo your app supplies.

Variants and sizes

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

Types (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.

Text options

New

A summary of your progress every Monday.

PartMeasurement
CardFills its container (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 Checkbox at the trailing edge, top-aligned

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 (checked)Bg/White with a 1px State/Primary/Base stroke; the checkbox 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, the same as Radio Card.

State tokens

Set on .nu-choice-card, shared with Radio Card.

TokenValueUsed for
--nu-choice-card-bgBg/WhiteDefault, checked, disabled
--nu-choice-card-bg-hoverBg/Weak-50Hover
--nu-choice-card-strokeStroke/Soft-200Default and disabled stroke
--nu-choice-card-stroke-checkedState/Primary/BaseChecked and focused stroke
--nu-choice-card-shadowregular-shadow/x-smallDefault shadow
--nu-choice-card-focus-shadowbuttons/primary-focusFocus halo (C5)

Figma discrepancies (pending a decision)

  • FC-20: Figma's disabled sublabel and description are Soft-400 (2.49:1) here but Sub-600 on Radio Card. Code uses Sub-600 for both (C49, 2026-10-14).
  • Disabled badges switch to Gray Light with a Soft-200 stroke in Figma. The badge is your element, so pass <Badge color="gray" appearance="stroke"> when the card is disabled.
  • The checkbox uses the darker unchecked frame approved in C48, not Figma's Soft-200.

Composition examples

Onboarding: study goals

A form step where students pick any number of goals. Each card submits its value under one name.

What do you want to achieve?

Timed practice tests and spaced review.

A weekly plan that fits your schedule.

Short daily lessons with hands-on tasks.

API reference

Props

Checkbox Card props
PropTypeDefaultDescription
labelrequiredReactNode—Figma Label. The accessible name; a click anywhere on the card toggles it.
sublabelReactNode—Figma Sublabel, e.g. "(Recommended)". 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).
checked · defaultCheckedboolean—Controlled or uncontrolled checked state.
onCheckedChange(checked: boolean) => void—Called with the new state. onChange still fires with the native event.
indeterminatebooleanfalseShows the dash and exposes aria-checked="mixed".
disabledbooleanfalseDisables the checkbox and dims the card.
invalidboolean—Marks the checkbox invalid. Inside a Field, this comes from error.
classNamestring—Class for the card.
…input propsInputHTMLAttributes—name, value, required, id and other attributes go to the native input. The ref points at the input.

Accessibility

Keyboard

KeyBehaviour
TabMoves focus to the card’s checkbox
SpaceToggles the checkbox

Screen readers

A native checkbox named by the label and sublabel, described by the description. The badge and leading visual are not announced as 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 checked stroke is State/Primary/Base, and the checkbox 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: give each card a unique, meaningful label, and name the set with a heading or a Field.

Figma mapping

Figma propertyFigma valuesCode
TypeBasic · Left Icon · Avatar · Card Provider · Brand · Companyleading (none for Basic)
StateDefault · Hover · Active · DisabledInteractive states, checked and disabled
Label · Sublabel · DescriptionText · boolean + text · textlabel · sublabel · description
BadgeBooleanbadge (pass a Badge)
Provider · Brand · CompanyInstance swapYour logo in leading

Guidelines and related components

Use Checkbox Card for

  • A few options that each need a description, price or visual
  • Onboarding choices, integrations or notification types

Don't use Checkbox Card for

  • Long lists or dense settings (use Checkbox)
  • Choosing exactly one option (use Radio Card)
  • Actions that apply instantly (use a toggle)

Do and don't

Download lessons to study without internet.

DoKeep the label short and move detail to the description People scan the labels first.
Don'tPut everything in the label Long labels are hard to scan and make a long accessible name.