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.

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