Menu


Choice card


One choice drawn as a card, with a label and a line under it: picked like a radio, or ticked like a checkbox.

Customize the preview


Choices
Show
Flags
View

Options


Choice card options
ChoiceValuesDefaultWhat it does
marksmbk-choice-card--mark-<value>radiocheckboxradio
A radio when one card of a group is picked; a checkbox when several can be.
errorsmbk-choice-card--errorOn or offOff
The choice is invalid, such as a required question left empty. The card takes the danger edge, and its mark its error look.

Partssmbk-choice-card__textsmbk-choice-card__labelsmbk-choice-card__description

Examples


Usage

Cards picked like radios: the whole card is the target, the mark and the brand edge show the choice.

Delivery

Checkboxes

With a checkbox mark, several cards can be picked.

Add to the order

Without a line

A title alone, for short choices.

Theme

Error

The danger edge on every card, and the group’s message says what to do.

Delivery

Disabled

Dimmed onto the disabled surface; a chosen card keeps its edge in the disabled color.

Delivery

Guidelines


Purpose

One choice drawn as a card: a title, a line under it, and the radio's circle or the checkbox's box. The whole card is the label of one real radio or checkbox, so it is picked by a press anywhere on it. It gives a few choices that each need explaining more room and a larger target than a radio row.

When to use

  • Two to five choices that each need a line of explanation: a plan, a delivery speed, a look.
  • With the checkbox mark, a few add-ons that can each be picked.

When not to use

  • Many choices, or short ones. Use radios, or the select.
  • An answer that should be sent the moment it is pressed. Use buttons: arrow keys move the choice in a set of radios and would send every choice they pass.

Usage rules

Do

  • Keep the title to a few words and the line to one sentence.
  • Pre-select the most common choice when there is one.

Don't

  • Put buttons or links inside a card: a press anywhere picks it.
  • Show more than about five cards in one group.
Plan
Do

Use cards for a few choices that each need a line of explanation.

Country
Don't

A long list of cards pushes the rest of the form out of sight; a select holds many choices in one line.

Anatomy

  • The block, the card: a label element holding everything, on the default surface with a hairline edge and a lift. It also carries the radio's or the checkbox's classes, which draw the mark.
  • The mark, the radio's circle or the checkbox's box, on the title's first line. It always shows, so being picked is never told by color alone.
  • The text part, the title over the line.
  • The label part, the title.
  • The description part, an optional line under the title.

Behavior

Picking a card checks its control and draws the brand edge at the emphasis width, inside the card so it keeps its size, with the mark filled. Under the pointer the card lifts onto the raised surface; pressed, it sinks onto the sunken surface. With error, every card takes the danger edge, picked or not. Disabled, the card sits on the disabled surface with its words dimmed; a picked disabled card keeps its edge in the disabled border color.

The radio mark is the default; with the checkbox mark, several cards can be picked. Inside a field group a card takes the group's name, error and required state, and a radio card follows the chosen value when the group holds it.

Accessibility


What it does for you

  • The control is a real radio or checkbox, named by the title and described by the line, so a screen reader says the title, radio or checkbox, picked or not, then the line.
  • Radios in one group take one stop for the Tab key and the arrow keys move the choice; Space picks.
  • The focus ring goes around the whole card.

What you must do

  • Put a set of cards in a field group, whose legend names it.

How to test

  • Tab to a set of radio cards: one stop takes focus, with the ring around the whole card in both themes and in a forced-color mode. Move with the arrow keys, then press Space to pick.
  • With a screen reader, a card is read as its title, a radio or a checkbox, picked or not, then its line, and the set by its legend.
  • With text at 200% and the page 320 pixels wide, the title and line wrap and the card stays whole.

Keyboard

Choice card keys
KeyWhat it does
Tab
Moves focus to the card. Radios in one group take one stop.
Up ArroworDown ArroworLeft ArroworRight Arrow
Moves the choice to the next or previous radio card in the group.
Space
Picks a radio card, or toggles a checkbox card.

Source


The files the choice card is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
choice-card.css
/* smbk-choice-card — Choice card. Figma "Choice card" 7105:1911 (State: Default, Hover, Pressed, Focus, Disabled, Error × Selected).
 * One choice drawn as a card: the radio's circle or the checkbox's box, then a
 * label in Label MD over an optional line in Body SM, the whole card the
 * label of one native radio or checkbox. Built on the radio and the checkbox:
 * the card carries their block and size classes, so the mark's own looks
 * (hover, chosen, error, disabled) are theirs, and this stylesheet adds only
 * the card: its surface, its edge, its padding and the focus ring around it.
 * The label over its line, and the mark on the label's first line, are the
 * rules every choice shares, in choice/choice.css.
 * Chosen, the edge turns the brand color at the emphasis width, drawn inside
 * so the card keeps its size, and the mark shows the choice as a shape too. */

/* Two classes, so the card wins over the radio's and the checkbox's own row whichever stylesheet loads first. */
.smbk-choice-card:is(.smbk-radio, .smbk-checkbox) {
  box-sizing: border-box;
  display: flex;
  align-items: flex-start;
  gap: var(--smbk-space-inline-md);
  width: 100%;
  padding: calc(var(--smbk-space-inset-xl) - var(--smbk-border-width-hairline));
  border: var(--smbk-border-width-hairline) solid var(--smbk-color-border-rim);
  border-radius: var(--smbk-radius-container-md);
  background: var(--smbk-color-surface-default);
  box-shadow: var(--smbk-elevation-control);
  color: var(--smbk-color-text-default);
  font-family: var(--smbk-typography-label-md-font-family);
  font-size: var(--smbk-typography-label-md-font-size);
  font-weight: var(--smbk-typography-label-md-font-weight);
  line-height: var(--smbk-typography-label-md-line-height);
  letter-spacing: var(--smbk-typography-label-md-letter-spacing);
}

@media (hover: hover) {
  .smbk-choice-card:is(.smbk-radio, .smbk-checkbox):hover:has(:enabled) {
    background: var(--smbk-color-surface-raised);
  }
}

/* Pressed: the card sinks onto the sunken surface and drops its lift. */
.smbk-choice-card:is(.smbk-radio, .smbk-checkbox):active:has(:enabled) {
  background: var(--smbk-color-surface-sunken);
  box-shadow: none;
}

/* Chosen: the brand edge at the emphasis width, the hairline border plus the rest drawn inside. */
.smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:checked) {
  border-color: var(--smbk-color-border-brand);
  box-shadow: inset 0 0 0 calc(var(--smbk-border-width-emphasis) - var(--smbk-border-width-hairline)) var(--smbk-color-border-brand), var(--smbk-elevation-control);
}

/* Pressed while chosen keeps the brand edge, not the lift; in error the danger edge below stays. */
.smbk-choice-card:not(.smbk-choice-card--error, :has([aria-invalid="true"])):is(.smbk-radio, .smbk-checkbox):active:has(:enabled:checked) {
  box-shadow: inset 0 0 0 calc(var(--smbk-border-width-emphasis) - var(--smbk-border-width-hairline)) var(--smbk-color-border-brand);
}

/* Error, chosen or not: the danger edge at the emphasis width; its control marked aria-invalid="true" draws the same. */
.smbk-choice-card.smbk-choice-card--error:is(.smbk-radio, .smbk-checkbox):has(:enabled),
.smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:enabled[aria-invalid="true"]) {
  border-color: var(--smbk-color-feedback-danger-border);
  box-shadow: inset 0 0 0 calc(var(--smbk-border-width-emphasis) - var(--smbk-border-width-hairline)) var(--smbk-color-feedback-danger-border), var(--smbk-elevation-control);
}

/* The focus ring goes around the whole card, not the mark. */
.smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:focus-visible) {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: var(--smbk-focus-ring-offset);
}

.smbk-choice-card :is(.smbk-radio__control, .smbk-checkbox__control):focus-visible + :is(.smbk-radio__circle, .smbk-checkbox__box) {
  outline: none;
}

.smbk-choice-card .smbk-radio__control:not(:checked):focus-visible + .smbk-radio__circle {
  background: transparent;
}

/* Disabled: the disabled surface with no lift; chosen, the edge keeps its width in the disabled border color. */
.smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:disabled) {
  background: var(--smbk-color-surface-disabled);
  box-shadow: none;
}

.smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:disabled:checked) {
  border-color: var(--smbk-color-action-disabled-border);
  box-shadow: inset 0 0 0 calc(var(--smbk-border-width-emphasis) - var(--smbk-border-width-hairline)) var(--smbk-color-action-disabled-border);
}

/* ---- high contrast (forced colors) ---- */
/* In Windows high-contrast mode the browser drops shadows, so the chosen card's edge is the border alone:
   Highlight, as the chosen mark is. Nothing here applies outside that mode. */

@media (forced-colors: active) {
  .smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:checked) {
    border-color: Highlight;
  }

  .smbk-choice-card:is(.smbk-radio, .smbk-checkbox):has(:disabled) {
    border-color: GrayText;
  }
}
Tokens it reads
Choice card tokens
Token and CSSValuePreviewFoundation
space.text.label--smbk-space-text-label0pxSpacing
size.selection.md--smbk-size-selection-md20pxSize
color.text.subtlest--smbk-color-text-subtlestlight: #606a75dark: #7c8692changes with themeColor
typography.body-sm--smbk-typography-body-sm-font-family--smbk-typography-body-sm-font-size--smbk-typography-body-sm-font-weight--smbk-typography-body-sm-line-height--smbk-typography-body-sm-letter-spacing--smbk-typography-body-sm-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
color.text.disabled--smbk-color-text-disabledlight: #7c8692dark: #606a75changes with themeColor
space.inline.md--smbk-space-inline-mdcomfortable: 8pxcompact: 6pxchanges with densitySpacing
space.inset.xl--smbk-space-inset-xlcomfortable: 16pxcompact: 12pxchanges with densitySpacing
border-width.hairline--smbk-border-width-hairline1pxBorder width
color.border.rim--smbk-color-border-rimlight: #ffffffe6dark: #ffffff0dchanges with themeColor
radius.container.md--smbk-radius-container-md12pxRadius
color.surface.default--smbk-color-surface-defaultlight: #f3f5f8dark: #181a1cchanges with themeColor
elevation.control--smbk-elevation-controllight: 0px 0px 1px 0px #373d430d, 0px 1px 2px 0px #373d431a, 0px 2px 4px 0px #373d430ddark: 0px 0px 1px 0px #0000001a, 0px 1px 2px 0px #00000026, 0px 2px 4px 0px #0000001aElevation
color.text.default--smbk-color-text-defaultlight: #232527dark: #e7ebf0changes with themeColor
typography.label-md--smbk-typography-label-md-font-family--smbk-typography-label-md-font-size--smbk-typography-label-md-font-weight--smbk-typography-label-md-line-height--smbk-typography-label-md-letter-spacing--smbk-typography-label-md-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 500lineHeight: 1.4letterSpacing: 0px

The quick brown fox

Typography
color.surface.raised--smbk-color-surface-raisedlight: #f9fafbdark: #232527changes with themeColor
color.surface.sunken--smbk-color-surface-sunkenlight: #373d430ddark: #00000066changes with themeColor
color.border.brand--smbk-color-border-brand#cc0d0dColor
border-width.emphasis--smbk-border-width-emphasis2pxBorder width
color.feedback.danger.border--smbk-color-feedback-danger-border#f34336Color
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
focus.ring.offset--smbk-focus-ring-offset2pxFocus
color.surface.disabled--smbk-color-surface-disabledlight: #e7ebf0dark: #373d43changes with themeColor
color.action.disabled.border--smbk-color-action-disabled-borderlight: #c4cdd8dark: #2d3237changes with themeColor
Manifest
choice-card.manifest.json
{
  "name": "choice-card",
  "block": "smbk-choice-card",
  "summary": "One choice drawn as a card, with a label and a line under it: picked like a radio, or ticked like a checkbox.",
  "adapt": "css",
  "axes": {
    "mark": {
      "values": [
        "radio",
        "checkbox"
      ],
      "default": "radio",
      "description": "A radio when one card of a group is picked; a checkbox when several can be."
    }
  },
  "flags": {
    "error": {
      "description": "The choice is invalid, such as a required question left empty. The card takes the danger edge, and its mark its error look."
    }
  },
  "parts": [
    "text",
    "label",
    "description"
  ],
  "figmaNodeId": "7105:1911"
}