Skip to main content

ChoiceButton

ChoiceButton is a radio button wrapped in a card-like container. It's used in question/answer scenarios where it's useful to show additional information for each option.

Code example
import { ChoiceButton } from '@yleisradio/yds-components-react';

<ChoiceButton name="choice-1" label="Option 1" />

Why to use​

ChoiceButton gives you a consistent, accessible way to present single-select options in a card layout. It extends Radio with an optional icon, extra content below the label, and right/wrong answer indicator — so you can highlight options or show results without building custom layouts.

When to use​

Use ChoiceButton when options need a card-style container: each choice has an icon, a short description, or should stand out visually. Use plain Radio (and RadioGroup) when options are simple labels in a list.

Do
  • Use for question/answer patterns.
Don't
  • Don't use as a regular form component. Use Radio instead.

Content guidelines​

Keep labels short and parallel. Put longer explanations in the content prop or in a group description.

Do
  • Use the optional icon and status to tell the user if the answer is correct or incorrect.
  • Use content for brief supporting text, not for the main choice label.
Don't
  • Don't use long sentences as the main label — move detail into content or description.

Key ChoiceButton Props​

Use these props to configure the ChoiceButton component.

label​

Label text or content for the radio button.

TypeExampleDescription
React.ReactNode
Label content for the radio button
Code example
<ChoiceButton name="option-group" label="Option 1" />
<ChoiceButton name="option-group" label={<strong>Bold Option</strong>} />

status​

Visual status indicator for the choice button.

ValueExampleDescription
success
Success status styling
error
Error status styling
Code example
<ChoiceButton name="option-group" label="Option" status="success" />
<ChoiceButton name="option-group" label="Option" status="error" />

controlAlign​

Alignment of the radio control relative to the content.

ValueExampleDescription
start
Aligns control to the start
end
Aligns control to the end
Code example
<ChoiceButton name="option-group" label="Option" controlAlign="start" />
<ChoiceButton name="option-group" label="Option" controlAlign="end" />

containerSize​

Size of the choice container.

ValueExampleDescription
sm
Small container size
md
Medium container size (default)
Code example
<ChoiceButton name="option-group" label="Option" containerSize="sm" />
<ChoiceButton name="option-group" label="Option" containerSize="md" />

icon​

Optional icon to display in the choice container.

TypeExampleDescription
React.ReactNode
Icon element to display
Code example
import { Check } from '@yleisradio/yds-icons-react';

<ChoiceButton name="option-group" label="Option" icon={<Check />} />

content​

Additional content to display below the radio button and icon.

info

The content area has no built-in padding. Handle spacing and layout yourself when showing extra content such as text. This keeps images flush with the edges when they are used as content.

TypeExampleDescription
React.ReactNode

Some additional content

Additional content below the control
Code example
<ChoiceButton
name="option-group"
label="Option"
content={<p style={{ margin: 16 }}>Some additional content</p>}
/>

isDisabled​

Whether the radio button is disabled.

TypeExampleDescription
boolean
Disables the radio button
Code example
<ChoiceButton name="option-group" label="Option" isDisabled />

variant​

Visual style variant of the radio button.

ValueExampleDescription
primary
Primary variant (default)
secondary
Secondary variant
Code example
<ChoiceButton name="option-group" label="Option" variant="primary" />
<ChoiceButton name="option-group" label="Option" variant="secondary" />

useUnderlay​

Whether to show an underlay effect.

TypeExampleDescription
boolean
Shows underlay effect
Code example
<ChoiceButton name="option-group" label="Option" useUnderlay />

background​

Background style variant of the choice container.

TypeExampleDescription
default
Default background
variant
Variant background
Code example
<ChoiceButton name="option-group" label="Option" background="default" />
<ChoiceButton name="option-group" label="Option" background="variant" />

Behavior​

  • All ChoiceButtons in a group share the same name; only one can be selected at a time.
  • Selection is controlled via checked / defaultChecked and onChange, or via a parent like RadioGroup.
  • The container has an underlay by default (useUnderlay={true}).
  • status="success" or status="error" applies visual feedback.
  • Disabled options are non-interactive but remain visible.

Accessibility​

  • Every ChoiceButton must have a visible or programmatically associated label (use label or hideLabel with meaningful accessible name).
    (WCAG 3.3.2 — Labels or Instructions)
  • Group related options under a shared name and, when possible, a fieldset or group label so the relationship is clear.
    (WCAG 1.3.1 — Info and Relationships)
  • Keyboard: Tab/Shift+Tab move focus between options; Arrow keys move between radio buttons in the same group; Space selects the focused option.
    (WCAG 2.1.1 — Keyboard)

Implementation examples​

Abitreenit example​

Mikä seuraavista tekniiko ista on kemiallinen erotusmenetelmä?
Code example
import { useState } from 'react';
import { Check, Close } from '@yleisradio/yds-icons-react';
import { ChoiceButton as ChoiceButtonComponent } from '@yleisradio/yds-components-react';

export const ChoiceButton = () => {
const [choices, setChoices] = useState([
{
label: 'infrapunaspektroskopia',
correct: false,
icon: null,
status: null,
},
{
label: 'massaspektrometria',
correct: false,
icon: null,
status: null,
},
{
label: 'uuttaminen',
correct: true,
icon: null,
status: null,
},
{
label: 'sulamispisteen määritys',
correct: false,
icon: null,
status: null,
},
]);

const handleChoiceChange = (value: string) => {
setChoices((c) =>
c.map((choice) => {
if (choice.label === value) {
return {
...choice,
icon: choice.correct ? <Check /> : <Close />,
status: choice.correct ? 'success' : 'error',
};
}
if (choice.correct) {
return {
...choice,
icon: <Check />,
status: 'success',
};
}
return {
...choice,
icon: null,
status: null,
};
})
);
};

return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
Mikä seuraavista tekniiko ista on kemiallinen erotusmenetelmä?
{choices.map((choice) => (
<ChoiceButtonComponent
name="choice-1"
label={choice.label}
icon={choice.icon}
onChange={() => handleChoiceChange(choice.label)}
status={choice.status}
/>
))}
</div>
);
};

API Reference​

Props​

The ChoiceButton component accepts all standard HTML <input> attributes (except size) in addition to the following props:

PropTypeRequiredDefaultDescription
namestringYes—Name attribute for grouping radio buttons
labelReact.ReactNodeYes—Label content for the radio button
status'success' | 'error'No—Visual status indicator
controlAlign'start' | 'end'No—Alignment of radio control
containerSize'sm' | 'md'No—Size of the choice container
iconReact.ReactNodeNo—Optional icon to display
contentReact.ReactNodeNo—Additional content below control
isDisabledbooleanNofalseWhether the radio button is disabled
variant'primary' | 'secondary'No'primary'Visual style variant
valuestringNo—Value attribute for form submission
hideLabelbooleanNofalseVisually hides the label
useUnderlaybooleanNotrueShows underlay effect
background'default' | 'variant'No—Background style variant

Type Definitions​

export type ChoiceContainerStatus = 'success' | 'error';
export type ChoiceContainerBackground = 'default' | 'variant';
export type InputControlAlign = 'start' | 'end';
export type ChoiceContainerSize = 'sm' | 'md';
export type ChoiceHTMLInputAttributes = Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>;

export interface ChoiceButtonDSProps {
status?: ChoiceContainerStatus;
controlAlign?: InputControlAlign;
containerSize?: ChoiceContainerSize;
icon?: React.ReactNode;
content?: React.ReactNode;
background?: ChoiceContainerBackground;
}

export type RadioPropsNoError = Omit<RadioProps, 'error'>;

export type ChoiceButtonProps = ChoiceHTMLInputAttributes & ChoiceButtonDSProps & RadioPropsNoError;
  • Radio – Base radio component and RadioGroup that ChoiceButton extends
  • ChoiceBox – Card-style multi-select option (checkbox)
  • Checkbox – For multiple independent selections with CheckboxGroup