A radio group is a set of checkable buttons, known as radio buttons, where no more than one of the buttons can be checked at a time. Some implementations may initialize the set with all buttons in the unchecked state to force the user to check one of the buttons before moving past a certain point in the workflow.
Radios in HTML do not have a “group” concept, but they get grouped implicitly by the “name” attribute. This isn’t the case in Vue and most UI libraries, as they are grouped by the model name they mutate.
Formwerk follows the “group” concept to provide a consistent API for radio fields regardless of whether they are bound to the same model or if they have the same name or not.
This means radios are a compound field, meaning they require more than one composable to work properly, and by extension, you need to build more than one component to make them work.
For radios, you will use the useRadioGroup and useRadio composables to build radio components.
Features
You can build radio components using either the native HTML input[type="radio"] elements or other HTML elements. We provide the behavior, state, and accessibility implementation for both cases with the same API and features.
The following features are implemented:
Support for either input[type="radio"] or custom HTML elements as a base element for the radio component.
Labeling, descriptions, and error message displays are automatically linked to input and label elements with aria-* attributes.
Form management, data collection, and validation with native HTML5 validation or Standard Schema validation.
Support for orientation with horizontal and vertical values.
v-model support for radio groups.
Supported Keyboard features:
Key
Description
↓ArrowDown
Focuses the next radio item in the group.
→ArrowRight
Focuses the next radio item in the group. In RTL, focuses the previous item.
←Arrow Left
Focuses the previous radio item in the group.
↑Arrow Up
Focuses the previous radio item in the group. In RTL, focuses the next item.
⇥Tab
Focuses the selected item in the group. If none selected, focuses the first one.
⎵Space
Selects the focused radio item.
Anatomy
Choose Drink
Group Label
Tea
Coffee
Input
Water
Radio Label
Radio Group
Building a Radio Group Component
The useRadioGroup provides the behavior, state, and accessibility implementation for group components.
Unlike checkboxes, radio components MUST be grouped by a radio group component. This is why we will start by building a RadioGroup component as a prerequisite. We will be using this component in the following examples throughout this page.
Building a Radio Component
With the Radio Group component built, we can now build a RadioItem component. You will be using the useRadio composable to build it.
You can use either the native HTML input[type="radio"] element or custom HTML elements. It doesn’t matter which one you choose; both have the same exact API, and Formwerk does the work needed for each case behind the scenes.
The most important part is to bind the inputProps object to the base element, the element that you consider to be the radio button. We also provide the RadioProps type for you to use as your component props. You are not required to use it, but it is recommended to make use of the full feature set of the useRadio composable and, by extension, your component.
With the basics out of the way, let’s build a radio component with two common variations.
With input element as a base
You can use the useRadio composable to build a radio component with the input element as a base.
The style-ability of the last example is limited to the styling capabilities of the native input element. To work around that, check the styling section.
With custom HTML element as a base
For unlimited styling freedom, you don’t have to use the input element. With the same API, you can use custom HTML elements as a binding target for the inputProps object.
In the following example, we are using a span element as a base element for the radio. Try keyboard navigation, clicking, focusing, and other interactions to see how it behaves.
Validation
Radio components support validation with native HTML5 constraints or Standard Schema validation. However, the useRadioGroup is the one that accepts validation props.
HTML Constraint Validation
The following properties are supported on useRadioGroup and useRadio that use the input element as a base. Custom elements do not support these properties.
Name
Type
Description
required
boolean
Whether the number field is required.
Standard Schema
useRadioGroup also supports Standard Schema validation through the schema prop. This includes multiple providers like Zod, Valibot, Arktype, and more.
Here is an example of using zod as a Standard Schema to validate the radio group. We will be using the radio item component from the previous examples.
Usage
Disabled
You can disable individual radio items or the whole group with the disabled prop on either. Disabled radio items are not focusable. Disabled groups are not submitted and are not validated.
We made use of the styled radio component that we created above to make it clearer that the radio items are disabled.
If you need to prevent the user from interacting with the group while still allowing it to submit, consider using readonly instead.
Readonly
Only available on the group, the readonly prop prevents the user from interacting with the group while still allowing it to submit and be validated.
Orientation
Radio groups accept an orientation prop that can be set to horizontal or vertical. The orientation does not affect the focus order, but you can use it to layout the radio items in a row or column with CSS.
There is no default value assumed for the orientation, but if it is provided, the group element will have an aria-orientation attribute set to the value of the prop. So you can use that to style it.
RTL
The radio group accepts a dir prop that can be set to ltr or rtl. Unlike the orientation, the dir prop affects the focus order of the radio items as the Left and Right arrow keys will navigate the items in the opposite direction.
API
Most of the values expressed below are wrapped in Ref as they are reactive values.
Radio Group
Props
These are the properties that can be passed to the useRadioGroup composable.
Name
Type
Description
description
The description text for the radio group.
dir
The text direction of the radio group (ltr or rtl).
disabled
Whether the radio group is disabled.
disableHtmlValidation
Whether to disable HTML5 form validation.
label
The label text for the radio group.
modelValue
The v-model value of the radio group.
name
The name attribute for the radio group.
orientation
The orientation of the radio group (horizontal or vertical).
readonly
Whether the radio group is readonly.
required
Whether the radio group is required.
schema
Schema for radio group validation.
Returns
These are the properties in the object returned by the useRadioGroup composable.