Skip to content
Protocore Design Systemv1.6.9

/// Inputs

CardInput

Selectable option cards for plan / tier / layout pickers — radio single-choice or checkbox multi-choice, selection inverting to an accent ring.

import { CardInput } from "@protocore/pds";
View as Markdown

Single choice

Wrap CardInput.Options in a CardInput.Group. The default type="single" gives radio semantics — one value, arrow-key navigation — and the selected card takes the accent ring.

Multiple choice

Set type="multiple" for checkbox semantics: the group owns a string[] and each card toggles independently.

Standalone toggle

A lone CardInput.Option (no Group) behaves as a checkbox card, controllable via checked / onCheckedChange — good for a single opt-in.

When to use it

Use CardInput when each option carries enough content — a title, a description, a price — that a plain radio or checkbox row would feel cramped, and seeing the options side by side aids the choice. For terse, equal-weight options use RadioGroup / CheckboxGroup; for a compact view-mode toggle use SegmentedControl.

Usage

Do

  • Give the group an accessible name via `aria-label` or a wrapping `Field`.
  • Keep each card's title and description parallel across options.
  • Set a `name` on the group when the value participates in a native form.

Don't

  • Don't nest other interactive controls inside a card — the whole card is the control.
  • Don't use single-choice cards where more than one can apply — set `type="multiple"`.
  • Don't rely on color alone; the selected card also shows a checked marker.

Accessibility

KeysAction
TabMove focus into the group (single: the selected card).
Arrow keysMove and select between cards in single mode.
SpaceToggle the focused card in multiple mode.
  • Each card is a `<label>` wrapping a real radio/checkbox, so selection is native and screen-reader-correct.
  • The group is a `role="radiogroup"` (single) or `role="group"` (multiple).
  • Focus draws the standard accent ring on the card surface via the hidden input's `:focus-visible`.

CardInput.Group props

PropTypeDefaultDescription
aria-labelstringAccessible name for the group.
classNamestring
defaultValuestring | string[]Initial selection when uncontrolled.
disabledbooleanDisable every card in the group.
namestringShared `name` for the underlying inputs — required for radio grouping in single mode.
onValueChange((value: string | string[]) => void)Fires with the next selection: a string in single mode, string[] in multiple.
orientationenumhorizontalLayout of the cards. Default `"horizontal"` (wrapping row).
styleCSSProperties
typeenumsingle`"single"` = radio semantics (one value), `"multiple"` = checkbox (array). Default `"single"`.
valuestring | string[]Controlled selection — a string (single) or string[] (multiple).

CardInput.Option props

PropTypeDefaultDescription
checkedbooleanControlled checked state when used standalone (no Group).
childrenReactNodeExtra content below the description.
classNamestring
defaultCheckedbooleanInitial checked state when used standalone and uncontrolled.
descriptionReactNodeSecondary line under the title (muted).
disabledbooleanDisable just this card.
iconReactNodeOptional leading icon slot.
onCheckedChange((checked: boolean) => void)Fires with the next checked state when used standalone.
styleCSSProperties
titleReactNodePrimary label (sans, ink).
valuestringThis option's value — required inside a `CardInput.Group`.

Related

  • RadioGroupOne-of-many selection with sharp square markers; the active option carries the accent fill.
  • CheckboxGroupA set of checkboxes sharing one array value — the multi-select counterpart to RadioGroup.
  • SegmentedControlCompact single-select toggle — a bordered row of mono uppercase segments where the active one inverts to a solid fill.
  • CardA surface block with a hairline border and sharp corners — flat title/subtitle/action props or compound Card.Header/Body/Footer.