bq-radio-group to connect the options and manage state.
Always wrap
bq-radio elements inside a bq-radio-group. The group manages selection state, keyboard navigation, form association, and accessibility — an isolated bq-radio cannot do this on its own.When to use
Use radio buttons when
- Users must select exactly one option from a short list (2–7 items)
- All available options need to be visible so users can compare them before choosing
- The choice persists until the user actively changes it
- An option needs to trigger a visible change in the surrounding form or UI
Patterns
Default
By default, a radio button remains unchecked, implying it remains inactive until selected.
Selected
Once a radio button is selected, it becomes active, signifying its chosen status.
Anatomy
| Part | Element | Description |
|---|---|---|
| 1 | Icon (selected) | The filled circular control shown when the radio is the active choice in the group |
| 2 | Label text | The <span> that holds the option text and extends the clickable area |
| 3 | Icon (unselected) | The empty circular control shown when the radio is not the active choice |
Design guidelines
Usage
Default
Wrapbq-radio elements inside a bq-radio-group. Set a matching value on the group to pre-select one option. The group handles all state synchronization.
Options
Disabled
Setdisabled on the group to prevent all interaction. You can also disable individual bq-radio elements when only specific options are unavailable.
Horizontal
Useorientation="horizontal" to arrange options side by side. Best for short labels and a small number of choices where vertical space is limited.
Fieldset
Add thefieldset attribute to render a visible border and legend around the group. Use this when the radio group is one of several distinct sections in a form that need visual separation.
Background on hover
Setbackground-on-hover on the group (or on individual bq-radio elements) to show a filled highlight on the label row when the user hovers. This increases the perceived click area in spacious layouts.
Best practices
DoAlways provide a group label via the
label slot on bq-radio-group so screen readers announce the question or field name when focus enters the group.Don’tLeave the
label slot empty — users relying on assistive technology will not know what the radio group is asking.DoPre-select a sensible default by setting
value on the group so the form always has a valid starting state and users understand which option is active on first view.Don’tLeave all options unselected when one choice is always required — an empty radio group can cause confusing form validation errors on submit.
DoWrite option labels as nouns or short phrases that clearly describe each choice so users can compare them at a glance.
Don’tUse vague labels like “Option 1” or “Yes/No” when more descriptive text would make the choice immediately understandable without additional context.
DoUse
disabled on the entire group when the choice is unavailable in the current context, and explain why it is locked via nearby helper text.Don’tDisable individual radio options without a visible explanation — users will not know whether the option is temporarily locked or permanently unavailable.
Accessibility
- Built in:
bq-radio-grouprenders as a<fieldset>(whenfieldsetis set) with a<legend>linked to thelabelslot, giving screen readers a proper group label for the set. - Built in: each
bq-radionative<input type="radio">carriesaria-checked,aria-disabled, andaria-labelledbypointing to its visible label element. - Built in: arrow-key navigation is handled by the group —
ArrowDown/ArrowRightmove to the next radio,ArrowUp/ArrowLeftmove to the previous one, wrapping at the ends. This matches the ARIA radio group keyboard pattern. - Built in: only one radio in the group receives
tabindex="0"at a time (the selected or first enabled option), keeping the tab stop count low. - Your responsibility: always populate the
labelslot onbq-radio-group— thearia-labelledbyreference on the group requires a visible label element to give the fieldset an accessible name. - Your responsibility: provide meaningful text inside each
bq-radioslot — thearia-labelledbyon the native input points to the label span, so empty or icon-only labels are not announced. - Your responsibility: when you disable the group, add visible helper text nearby explaining why the options are unavailable.
API reference
bq-radio properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
backgroundOnHover | background-on-hover | If true, the radio displays a background highlight on hover | boolean | false |
checked | checked | If true, the radio input is checked | boolean | false |
disabled | disabled | If true, the radio input is disabled | boolean | false |
formId | form-id | The ID of the <form> element the radio is associated with | string | — |
name | name | Name of the form control, submitted as part of a name/value pair | string | — |
required | required | If true, the user must select a value before the form can be submitted | boolean | false |
value | value | The string value of the radio, submitted with the form | string | — |
bq-radio-group properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
backgroundOnHover | background-on-hover | If true, all radios in the group show a background on hover | boolean | false |
debounceTime | debounce-time | Delay in milliseconds before bqChange fires after a value change | number | 0 |
disabled | disabled | If true, all radio inputs in the group are disabled | boolean | false |
fieldset | fieldset | If true, the group renders a visible fieldset border with a legend | boolean | false |
name | name | Name of the form control, submitted with the selected radio’s value | string | — |
orientation | orientation | Layout direction of the radio inputs | 'horizontal' | 'vertical' | 'vertical' |
required | required | If true, the radio group is required | boolean | false |
requiredValidationMessage | required-validation-message | Native form validation message shown when the group is required and no option is selected | string | — |
value | value | The value of the currently selected radio | string | — |
bq-radio methods
| Method | Description |
|---|---|
vClick() | Simulates a click on the native <input> — use instead of element.click() |
vFocus() | Sets focus on the native <input> — use instead of element.focus() |
vBlur() | Removes focus from the native <input> — use instead of element.blur() |
getNativeInput() | Returns the native <input> HTML element used under the hood |
bq-radio events
| Event | Description |
|---|---|
bqClick | Emitted when the radio is clicked; detail is { value: string; target: HTMLBqRadioElement } |
bqFocus | Emitted when the radio receives focus |
bqBlur | Emitted when the radio loses focus |
bqKeyDown | Emitted when a key is pressed while the radio is focused; detail is { key: string; target: HTMLBqRadioElement } |
bq-radio-group events
| Event | Description |
|---|---|
bqChange | Emitted when the selected radio changes; detail is { value: string; target: HTMLBqRadioElement } |
bqBlur | Emitted when focus leaves the entire group |
bq-radio slots
| Slot | Description |
|---|---|
| (default) | The visible label text for the radio option |
bq-radio-group slots
| Slot | Description |
|---|---|
| (default) | The bq-radio elements that make up the group |
label | The group’s label text, rendered as a legend inside the fieldset |
bq-radio shadow parts
| Part | Description |
|---|---|
base | The <label> wrapper that contains the control and the label text |
input | The native <input type="radio"> element |
radio | The <div> that renders the visible circular ring |
label | The <span> that holds the option text content |
bq-radio-group shadow parts
| Part | Description |
|---|---|
base | The <fieldset> or <div> wrapper that contains the label and all radio inputs |
label | The <legend> that holds the group label slot content |
group | The <div> that lays out the radio inputs |
CSS custom properties
| Variable | Description | Default |
|---|---|---|
--bq-radio--size | Size (width and height) of the radio control circle | 24px |
--bq-radio--border-width | Border width of the radio control ring | var(--bq-stroke-m) |
Resources
Interactive playground
Explore Radio variants and states in Storybook
Source code
View the component source on GitHub