Skip to main content
In progress

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 />

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
namestringYesName attribute for grouping radio buttons
labelReact.ReactNodeYesLabel content for the radio button
status'success' | 'error'NoVisual status indicator
controlAlign'start' | 'end'NoAlignment of radio control
containerSize'sm' | 'md'NoSize of the choice container
iconReact.ReactNodeNoOptional icon to display
contentReact.ReactNodeNoAdditional content below control
isDisabledbooleanNofalseWhether the radio button is disabled
variant'primary' | 'secondary'No'primary'Visual style variant
valuestringNoValue attribute for form submission
hideLabelbooleanNofalseVisually hides the label
useUnderlaybooleanNotrueShows underlay effect

Type Definitions

export type ChoiceContainerStatus = 'success' | 'error';
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;
}

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