Radio

Radio Buttons allow a user to select one value from a predefined list of 7 or fewer options.

yarn add @workday/canvas-kit-preview-react
Install
yarn add @workday/canvas-kit-preview-react

Radio (Main) vs. Radio (Preview)

We recommend you use the Radio component in the Preview package (@workday/canvas-kit-preview-react) documented here on this page. The Radio component in the Main package (@workday/canvas-kit-react) will eventually be replaced with the Radio component in the Preview package.

Radio (Main) Documentation

Anatomy

Image of a Radio Group in its default state.

  1. Form Field Label: The Form Field Label describes all of the Radio in the Radio group and functions as a header.
  2. Radio Button: Radio Buttons are vertically aligned and in close proximity to its own label.
  3. Radio Label: Radio Labels give information about what to select.

Usage Guidance

  • The Form Field Label can be positioned in two places; above or left of Radio group for LTR languages. Form Field Labels are aligned to the right of Radio group for RTL languages.
  • Radio Labels are positioned to the right of Radio Buttons for LTR languages or to the left of Radio Buttons for RTL languages.
  • You can configure one Radio Button in the group preselected by default. This default option should be the safest option presenting the least risk to the user, or be the option most commonly selected.
  • If the user is allowed to not select any of the options, provide a “None” option.
  • If the list doesn't encompass all possible values in 7 or less options, provide a Radio Button marked “Other.”

When to Use

  • Use Radio Buttons when a user is only allowed to select 1 value from a list of 7 or less options.

When to Use Something Else

  • Consider using a Switch if the only options are yes or no.
  • If a user is allowed to select 0, 1, or multiple values from a predefined list of 7 or less options, consider using Checkboxes or a Select to select one option.
  • Use a Prompt when the number of list items is large or unknown. Prompts have search capabilities and folders which provide users with the means to browse options. Prompts can be configured to support single or multi-select.

Examples

Basic Example

Our radio component includes a RadioGroup container and RadioGroup.RadioButton, which renders an individual radio button. Nest related RadioGroup.RadioButton buttons within a RadioGroup and provide a name prop to the RadioGroup to group the radio buttons together. Each RadioGroup.Radio must have a unique value. This value is used in conjunction with the value prop set on the RadioGroup to determine which radio button is selected. To tie it all together, provide an onChange handler to the RadioGroup to track the selected value as it changes.

RadioGroup should be used in tandem with Form Field where the useFieldset prop is set to true to meet accessibility standards. This ensures the label text from FormField is attached to the RadioGroup and read out as a group for voiceover.

Choose Your Pizza Crust
Value selected: deep-dish

Our example uses React state to track the value of the RadioGroup.

RadioGroup and RadioGroup.Radio support keyboard navigation through the proper use of WAI-ARIA properties.

Inverse

Set the variant prop of RadioGroup.RadioButton to inverse to ensure proper contrast on dark backgrounds.

Choose Your Pizza Crust

Radio Group with No Value

Omit the value prop from RadioGroup to render the group with no selected RadioGroup.RadioButton.

Choose Your Pizza Crust

Ref Forwarding

RadioGroup.RadioButton supports ref forwarding. It will forward ref to its underlying <input type="radio"> element.

Choose Your Pizza Crust

Label Position

Set the labelPosition prop of the wrapping FormField to designate the position of the label relative to the RadioGroup. labelPosition accepts the following values:

  • FormField.LabelPosition.Top (Default)
  • FormField.LabelPosition.Left
Choose Your Pizza Crust

Required

Set the required prop of the wrapping FormField to true to indicate that the field is required. Labels for required fields are suffixed by a red asterisk.

Choose Your Pizza Crust

You must choose a crust

Disabled

Set the disabled prop of RadioGroup.RadioButton to prevent users from interacting with it. Be careful not to disable a pre-selected radio button as this will block keyboard access to the entire RadioGroup.

Choose Your Pizza Crust

Custom Radio Button

Use RadioGroup.Label instead of RadioGroup.RadioButton if you need direct access to the label and the radio input. This will allow you to apply custom styling to the text and radio input.

Choose Your Pizza Crust
Value selected: deep-dish

Standalone Radio Button

Use StyledRadioButton when you want a styled radio button on its own without using RadioGroup. You will need to handle behavior and accessibility.

Choose Your Pizza Crust
Value selected: deep-dish

Use RadioGroup.Label when you want more control styling the text and radio input but still want some behavior handled for you.

Error States

Set the error prop of the wrapping FormField to FormField.ErrorType.Alert or FormField.ErrorType.Error to set the RadioGroup to the alert or error state, respectively. You will also need to set the hintId and hintText props on the FormField to meet accessibility standards. You must set an aria-describedby attribute on the RadioGroup element that matches the value of hintId set on the FormField element. These attributes ensure that the alert message is associated to the RadioGroup and read out by voiceover.

Alert

Use the alert state when a selection is valid but there is additional information.

Choose Your Pizza Crust

Alert: Deep dish is an extra $2.99.

Error

Use the error state when the selection is no longer valid.

Choose Your Pizza Crust

Error: Deep dish is currently sold out.

React Hook Form

Using a form library like React Hook Form is a common use case. Reference this CodeSandbox on how to use RadioGroup with React Hook Form.

Component API

RadioGroup

Use RadioGroup to group a collection of RadioGroup.RadioButton components under a common name.

<RadioGroup name="pizza-crust" value="thin">
<RadioGroup.RadioButton value="deep-dish">Deep dish</RadioGroup.RadioButton>
<RadioGroup.RadioButton value="thin">Thin</RadioGroup.RadioButton>
</RadioGroup>

Layout Component

RadioGroup supports all props from thelayout component.

Props

Props extend from . Changing the as prop will change the element interface.

Props extend from . If a model is passed, props from RadioModelConfig are ignored.

NameTypeDescriptionDefault
error

The type of error associated with the RadioGroup (if applicable).

theme
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

refReact.Ref<R = >

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

RadioGroup.RadioButton

RadioGroup.Radio renders an <input type="radio" /> and its associated <label> (using children as the label's contents). This component should satisfy most use cases; use RadioGroup.Label if you require more flexibility.

<RadioGroup name="pizza-crust" value="thin">
<RadioGroup.RadioButton value="deep-dish">Deep dish</RadioGroup.RadioButton>
<RadioGroup.RadioButton value="thin">Thin</RadioGroup.RadioButton>
</RadioGroup>

Layout Component

Radio supports all props from thelayout component.

Props

Props extend from input. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

The Radio input and label children of RadioLabel

theme
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
disabled boolean undefined
variant 'inverse' undefined
value string number
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

input
refReact.Ref<R = input>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

RadioGroup.Label

Use RadioGroup.Label instead of RadioGroup.Radio if you need direct access to the label and the radio input. This will render a <label> that wraps an <input type="radio" /> and a <span> for the label text.

<RadioGroup name"pizza-crust" value="deep-dish">
<RadioGroup.Label>
<RadioGroup.Label.Input value="deep-dish" />
<RadioGroup.Label.Text>Deep dish</RadioGroup.Label.Text>
</RadioGroup.Label>
</RadioGroup>

Layout Component

Radio.Label supports all props from thelayout component.

Props

Props extend from label. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

The Radio input and label children of RadioLabel

theme
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
disabled boolean undefined
variant 'inverse' undefined
value string number
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

label
refReact.Ref<R = label>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

RadioGroup.Label.Input

Use RadioGroup.Label.Input within a RadioGroup.Label to render the input portion of a radio button.

<RadioGroup name"pizza-crust" value="deep-dish">
<RadioGroup.Label>
<RadioGroup.Label.Input value="deep-dish" />
<RadioGroup.Label.Text>Deep dish</RadioGroup.Label.Text>
</RadioGroup.Label>
</RadioGroup>

Layout Component

RadioGroup.Label.Input supports all props from thelayout component.

Props

Props extend from input. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

The Radio input and label children of RadioLabel

theme
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
disabled boolean undefined
variant 'inverse' undefined
value string number
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

input
refReact.Ref<R = input>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useRadioInput

Basic type information:

useRadioInput

RadioGroup.Label.Text

Use RadioGroup.Label.Text within a RadioGroup.Label to render the label text portion of a radio button.

<RadioGroup name"pizza-crust" value="deep-dish">
<RadioGroup.Label>
<RadioGroup.Label.Input value="deep-dish" />
<RadioGroup.Label.Text>Deep dish</RadioGroup.Label.Text>
</RadioGroup.Label>
</RadioGroup>

Props

Props extend from span. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

Model

useRadioModel

useRadioModel (config: ):

Accessibility Guidelines

How Radio Buttons Impact the Accessible Experience

While associating labels to each radio button input is critical, radio buttons are used in groups of mutually exclusive choices. A group of choices requires context, such as, selecting your pizza crust. Designing a clear legend and building the context of the group is a key foundation for accessible radio buttons when users cannot visually perceive the layout.

Accessibility of Disabled Radio Buttons

Disabled radio buttons will not be accessible with the keyboard. While this is very standard, pre-selecting the disabled radio button will block keyboard access to the entire group of radio buttons. Furthermore, screen reader software will describe the total number of radio buttons in the group regardless of the disabled state.

Disabled Radio Example

Keyboard Interaction

Each Radio Button must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.

Radio Buttons must support the following keyboard interactions:

  • Tab: focus the group of radio buttons
  • Space: select focused radio button
  • Down Arrow or Right Arrow: select the next radio button
  • Up Arrow or Left Arrow: select the previous radio button

Screen Reader Interaction

Radio Buttons must communicate the following to users:

  • The name (Form Field Label) of the radio button grouping
  • The accessible name (label) of the focused radio button
  • Which Radio Button in the group is selected
  • The total number of radio buttons in the grouping

Design Annotations Needed

  • Write the context (legend) of the radio button grouping.

Implementation Markup Needed

  • Radio buttons must have a required attribute when the Radio Group is required for submission.
  • Radio buttons must have an aria-invalid=”true” attribute when the Radio Group has an error condition.
  • [Included in component] A <label> element is required with a for attribute referencing the unique id value of the associated radio button.
  • [Included in component] A <fieldset> element establishes the group of related Radio Buttons. The child <legend> element describes the context of the grouping.
  • [Included in component] A disabled attribute is set when the radio button is disabled.

Content Guidelines

  • Form Field Labels are written in title case.
  • The Radio Label for each individual selection are kept as concise as possible and written in sentence case.
  • When writing Radio Button labels, refer to the Radio Buttons section of the Content Style Guide.

Can't Find What You Need?

Check out our FAQ section which may help you find the information you're looking for.

FAQ Section