Radio Button
- Usage
- Styling
- States
- Orientation
- Custom Item Presentation
- Basic Features
- Style Variants
- Best Practices
- Related Components
Radio Button Group allows users to select one value among multiple choices.
new tab
RadioButtonGroup<String> radioGroup = new RadioButtonGroup<>();
radioGroup.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL);
radioGroup.setLabel("Travel class");
radioGroup.setItems("Economy", "Business", "First Class");
add(radioGroup);
States
Read-Only
Use read-only when content needs to be accessible but not editable. Read-only elements can’t be edited, but they’re part of the tabbing order and can thus receive focus. The content of a read-only input can be selected and copied.
new tab
RadioButtonGroup<String> radioGroup = new RadioButtonGroup<>();
radioGroup.setLabel("Status");
radioGroup.setItems("In progress", "Done", "Cancelled");
radioGroup.setValue("In progress");
radioGroup.setReadOnly(true);
add(radioGroup);
Disabled
Disable a field to mark it as currently unavailable. The disabled state is used for fields that aren’t editable and don’t need to be readable. Disabled elements can’t be focused and may be inaccessible to assistive technologies such as screen readers.
Disabling can be preferable to hiding an element to prevent changes in layout when the element’s visibility changes, and to make users aware of its existence even when it’s currently unavailable.
new tab
RadioButtonGroup<String> radioGroup = new RadioButtonGroup<>();
radioGroup.setLabel("Status");
radioGroup.setItems("In progress", "Done", "Cancelled");
radioGroup.setValue("In progress");
radioGroup.setEnabled(false);
add(radioGroup);
Orientation
The component’s default orientation is horizontal. However, vertical orientation is recommended whenever possible, since it’s generally easier for the user to scan a vertical list of options:
new tab
RadioButtonGroup<String> radioGroup = new RadioButtonGroup<>();
radioGroup.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL);
radioGroup.setLabel("Status");
radioGroup.setItems("Pending", "Submitted", "Confirmed");
radioGroup.setValue("Pending");
add(radioGroup);
In cases where vertical space needs to be conserved, horizontal orientation can be used. However, it’s recommended that there be no more than three options:
new tab
RadioButtonGroup<String> radioGroup = new RadioButtonGroup<>();
radioGroup.setLabel("Status");
radioGroup.setItems("Pending", "Submitted", "Confirmed");
radioGroup.setValue("Pending");
add(radioGroup);
In cases where more options are needed, the Select component can be used instead.
Custom Item Presentation
Items can be customized to include more than a single line of text:
new tab
RadioButtonGroup<Card> radioGroup = new RadioButtonGroup<>();
radioGroup.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL);
radioGroup.setLabel("Payment method");
List<Card> cards = DataService.getCards();
radioGroup.setItems(cards);
radioGroup.setValue(cards.get(0));
radioGroup.setRenderer(new ComponentRenderer<>(card -> {
Image logo = new Image(card.getPictureUrl(), card.getName());
logo.setHeight("1em");
Span number = new Span(new Text(card.getAccountNumber()));
Text expiryDate = new Text("Expiry date:" + card.getExpiryDate());
return new Div(new HorizontalLayout(logo, number),
new Div(expiryDate));
}));
add(radioGroup);
Basic Features
The following features, common to most input field components, are supported:
Label
The label is used to identify the input field. It supports plain-text content, and its length is limited to the width of the field. Helpers and Tooltips can be used to provide additional information that doesn’t fit into the label.
Visible labels are strongly recommended for all input fields. In cases where the built-in label cannot be used, an external element can be associated as the field’s label through the aria-labelledby
attribute. Fields without any visible label should include an invisible label for assistive technologies with the aria-label
attribute.
Helper
Helpers are used to provide additional information that the user may need to enter in the field, such as format requirements or explanations of the field’s purpose below the field.
A style variant is available for rendering the helper above the field.
In addition to plain text, helpers can contain components and HTML elements. However, complex and interactive content is likely to have accessibility issues.
Tooltip
Tooltips are small text pop-ups displayed on hover, and on keyboard-focus. They can be used to provide additional information about a field. This can be useful in situations where an always visible Helper is not appropriate. Helpers are generally recommended in favor of tooltips, though, as they provide much better discoverability and mobile support. See the Tooltip documentation for more information.
External & Invisible Labels (ARIA)
Visible labels are strongly recommended for all input fields. In situations where the built-in label cannot be used, an external element can be associated as the field’s label through its element id
. Fields without any visible label should be provided an invisible label for assistive technologies like screen readers.
<!-- Associates external element as label: -->
<label id="external-label">This is the label</label>
<vaadin-radio-button-group accessible-name-ref="external-label">...
<!-- Invisible label for screen readers: -->
<vaadin-radio-button-group accessible-name="This is the label">...
new tab
RadioButtonGroup<String> field = new RadioButtonGroup<>();
field.setLabel("Label");
field.setHelperText("Helper text");
field.setTooltipText("Tooltip text");
Style Variants
The following style variants can be applied:
Helper Above Field
The helper can be rendered above the field, and below the label.
Borders
Borders can be applied to the field surface by providing a value (e.g., 1px
) to the --vaadin-input-field-border-width
CSS property. This can be applied globally to all input fields using the html
selector, or to individual component instances. Borders are required to achieve WCAG 2.1 level AA conformant color contrast with the default Lumo styling of fields.
You can override the default border color with the --vaadin-input-field-border-color
property.
new tab
RadioButtonGroup<String> field = new RadioButtonGroup<>();
field.addThemeVariants(RadioGroupVariant.LUMO_HELPER_ABOVE_FIELD);
field.getStyle().set("--vaadin-input-field-border-width", "1px");
Best Practices
Group Labels
It’s important to provide labels for Radio Button Groups to distinguish them from each other, especially with multiple adjacent groups.
new tab
RadioButtonGroup<String> jobTitleGroup = new RadioButtonGroup<>();
jobTitleGroup.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL);
jobTitleGroup.setLabel("Job title");
jobTitleGroup.setItems("Analyst", "Administrator", "Engineer");
jobTitleGroup.setValue("Analyst");
add(jobTitleGroup);
RadioButtonGroup<String> departmentGroup = new RadioButtonGroup<>();
departmentGroup.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL);
departmentGroup.setLabel("Department");
departmentGroup.setItems("Engineering", "Human Resources", "Marketing");
departmentGroup.setValue("Engineering");
add(departmentGroup);
Custom Option
To enable the user to enter a custom option instead of picking one from the list, use an "Other" radio button choice at the bottom of the list with an associated Text Field for entry. The field should be hidden or disabled until the "Other" option is selected.
new tab
RadioButtonGroup<Card> radioGroup = new RadioButtonGroup<>();
radioGroup.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL);
radioGroup.setLabel("Payment method");
List<Card> cards = new ArrayList<>(DataService.getCards());
Card other = new Card();
other.setId(-1);
cards.add(other);
radioGroup.setItems(cards);
radioGroup.setValue(cards.get(0));
radioGroup.setRenderer(new ComponentRenderer<>(card -> {
if (other.equals(card)) {
return new Text("Other");
} else {
Image logo = new Image(card.getPictureUrl(), card.getName());
logo.setHeight("1em");
Span number = new Span(new Text(card.getAccountNumber()));
return new HorizontalLayout(logo, number);
}
}));
TextField textField = new TextField("Card number");
textField.setVisible(false);
radioGroup.addValueChangeListener(
e -> textField.setVisible(other.equals(e.getValue())));
add(radioGroup, textField);
Default Value & Blank Option
It’s recommended that you set the most common option as the default value for Radio Button Groups. Place the default option at the top of the list.
In cases where it’s important that the user make a conscious choice, the Radio Button Group should be blank by default.
In situations where the user isn’t required to select a value, use a "blank" option:
new tab
<RadioGroup label="Repeat" theme="vertical" value="none">
<RadioButton value="none" label="None" checked />
<RadioButton value="daily" label="Daily" />
<RadioButton value="weekly" label="Weekly" />
<RadioButton value="monthly" label="Monthly" />
</RadioGroup>
Alternative to Checkbox
Two Radio Buttons can sometimes be a good alternative to a single Checkbox. If the Checkbox doesn’t represent a simple yes/no choice, and its label can’t clearly communicate the meaning of its unchecked state, it’s better to use a Radio Button Group with two options:
new tab
<Checkbox checked>
<label slot="label">Reply All by default (unchecked state not clear)</label>
</Checkbox>
<RadioGroup label="Default reply behavior" value="Reply">
<RadioButton label="Reply" checked value="Reply" />
<RadioButton label="Reply to all" value="Reply to all" />
</RadioGroup>
In a Horizontal Layout, Radio Button Groups also align better with other input fields than a single checkbox.
Related Components
Component | Usage Recommendation |
---|---|
A drop-down field for selecting an item from a list of options. Recommended when there is insufficient space for a Radio Button Group. | |
A filterable, lazy-loading alternative to Select. Recommended for ten or more items. | |
A scrollable list of options. Supports single and multi-select. | |
A corresponding component for multi-select options. |
E1E617CE-F935-451D-885F-CEF94EC0E53A