Radio
Overview
The Radio component provides a Bulma-styled radio button input with flexible labels and helper classes.
Use it for mutually exclusive choices in forms—either standalone or grouped (with the same name).
Import
import { Radio, Radios, Control } from '@allxsmith/bestax-bulma';
Usage
Mutually Exclusive Radios (Only One Can Be Selected)
This example shows how to use the Radio component for mutually exclusive choices. Assign the same name prop to each Radio in a group to ensure only one can be selected at a time. Use within a Control for proper Bulma styling.
<Control> <Radio name="mutuallyExclusive"> Yes </Radio> <Radio name="mutuallyExclusive"> No </Radio> <Radio name="mutuallyExclusive"> Maybe </Radio> </Control>
Default Selected Radio
Set the defaultChecked prop on a Radio to make it selected by default. This is useful for pre-selecting a common or recommended option in a group.
<Control> <Radio name="pet"> Cat </Radio> <Radio name="pet" defaultChecked> {' '} Dog{' '} </Radio> </Control>
Disabled Radios
Use the disabled prop to render radios that cannot be selected. This is helpful for indicating unavailable options in a group.
<Control> <Radio name="response" disabled> {' '} Attend{' '} </Radio> <Radio name="response" disabled> {' '} Decline{' '} </Radio> <Radio name="response" disabled> {' '} Tentative{' '} </Radio> </Control>
List of Radios (Grouped with the Radios Wrapper)
Render a list of radios using the Radios wrapper component. This is useful for grouping related radio buttons together, especially when they share the same name prop. In this example, all radios are disabled.
<Radios> <Radio name="event" disabled> {' '} Attend{' '} </Radio> <Radio name="event" disabled> {' '} Decline{' '} </Radio> <Radio name="event" disabled> {' '} Tentative{' '} </Radio> </Radios>
Valid Colors and Sizes
The values color and size accept are exported as readonly tuples, radioColors and radioSizes. The prop types are built from them, so they hold the same values as the Props table below. Map over them to build a color or size picker, as the two groups below do, or check a value that arrives at runtime (from a CMS or a query string, say) before you pass it in: a value outside the tuple adds no modifier class. Import them from the package root. The valid value constants page covers the typing and validation idioms.
import { Radio, Radios } from '@allxsmith/bestax-bulma'; import { radioColors, radioSizes } from '@allxsmith/bestax-bulma'; function example() { return ( <> <Radios label="Accent color" name="accent" defaultValue="primary"> {radioColors.map(color => ( <Radio key={color} value={color} color={color}> {color} </Radio> ))} </Radios> <Radios label="Size" name="accent-size" defaultValue="normal"> {radioSizes.map(size => ( <Radio key={size} value={size} size={size}> {size} </Radio> ))} </Radios> </> ); }
Circle Size
The circle is --bulma-radio-size across, 1.25em by default, so it grows with the label's font size and the size prop. It doesn't go below 24px, whatever that variable says: the stylesheet gives the circle a min-width and min-height of 24px, the minimum size WCAG 2.2 sets for a target (2.5.8, Target Size (Minimum)), so a circle with no label text beside it is still easy to hit. With Bulma's default font sizes, 1.25em comes out under 24px at the default and small sizes, so those two circles are both 24px.
For a smaller circle, lower the floor along with the size, on a class you pass through className. Name .styled-radio beside your class in each selector, so the rules win whatever order the stylesheets load in, and use .bestax-styled-radio and .bestax-check under the prefixed flavor:
.styled-radio.compact-radio {
--bulma-radio-size: 20px;
}
.styled-radio.compact-radio .check {
min-width: 0;
min-height: 0;
}
<Radio name="plan" value="basic" className="compact-radio">
Basic
</Radio>
Keep the label text inside the Radio when you shrink the circle. The whole label is the click target, so it stays easy to hit when the circle alone is small.
Accessibility
- Each
Radiois rendered as a<label>wrapping an<input type="radio">and the label text, for optimal accessibility. - Use the same
nameprop for a group of radios to ensure only one can be selected. - The circle is at least 24px across, the minimum size WCAG 2.2 sets for a target (2.5.8), whatever
--bulma-radio-sizesays. Circle Size shows how to make it smaller, and why to keep the label text inside theRadiowhen you do. - An unchecked radio shows only its ring,
--bulma-radio-border-color. It defaults to--bulma-text-weak, which holds the 3:1 contrast WCAG asks of a control's boundary (non-text contrast) on Bulma's page and card surfaces in light and dark. Set a replacement on a class you pass throughclassName, sincestylegoes to the<input>, naming the label's class too (.styled-radio.my-radio) so load order can't undo it, and hold it to 3:1 as well.
Related Components
Radios: For grouped radio buttons.Field: For labeled/grouped form fields.- Helper Props
Additional Resources
Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger' | — | Color of the radio button. |
size | 'small' | 'normal' | 'medium' | 'large' | — | Size of the radio button. |
textColor | Bulma color | 'inherit' | 'current' | — | Text color helper. |
disabled | boolean | false | Whether the radio is disabled. |
className | string | — | Additional CSS classes, on the outer <label>. That's the element that declares the --bulma-radio-* variables, so a class is how to set one: style and the other input attributes go to the <input>. Name .styled-radio beside your class in the selector, so it beats the label's own declaration whatever order the stylesheets load in. A color prop declares the active color again on .styled-radio.is-<color>, which ties that selector, so leave color unset when a class sets it. |
children | React.ReactNode | — | The label/content for the radio. |
ref | React.Ref<HTMLInputElement> | — | Forwarded to the underlying element. |
... | All standard <input> attributes and Bulma helper props | — | Helper props go on the outer <label>, with className. The other attributes go on the <input>. See Helper Props |
CSS & Sass Variables
Radio registers these variables on its own .styled-radio element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.
| CSS Variable | Sass Variable | Default |
|---|---|---|
--bulma-radio-size | $radio-size | 1.25em |
--bulma-radio-border-width | $radio-border-width | 2px |
--bulma-radio-border-color | $radio-border-color | var(--bulma-text-weak) |
--bulma-radio-background | $radio-background | transparent |
--bulma-radio-dot-color | $radio-dot-color | var(--bulma-scheme-main) |
--bulma-radio-active-color | $radio-active-color | var(--bulma-primary) |
--bulma-radio-label-gap | $radio-label-gap | 0.5em |
--bulma-radio-focus-shadow-size | $radio-focus-shadow-size | 0 0 0 0.125em |
--bulma-radio-transition-duration | $radio-transition-duration | var(--bulma-duration) |
--bulma-radio-size has a floor: the circle doesn't render smaller than 24px, whatever the variable says. Circle Size says why, and how to go below it.