Radio
Radio Buttons allow a user to select one value from a predefined list of 7 or fewer options.
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.
Anatomy

- Form Field Label: The Form Field Label describes all of the Radio in the Radio group and functions as a header.
- Radio Button: Radio Buttons are vertically aligned and in close proximity to its own label.
- 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.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
import {Flex} from '@workday/canvas-kit-react/layout';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';
const formfieldInputStyles = createStyles({
width: px2rem(200),
});
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<Flex flexDirection="column">
<FormFieldGroup>
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.Field>
<FormFieldGroup.List
cs={formfieldInputStyles}
as={RadioGroup}
name="pizza-crust"
onChange={handleChange}
value={value}
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free">
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="custom">
Butter - the best thing to put on bread
</FormFieldGroup.Input>
</FormFieldGroup.List>
</FormFieldGroup.Field>
</FormFieldGroup>
Value selected: {value}
</Flex>
);
};
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.
import React from 'react';
import {Box} from '@workday/canvas-kit-react/layout';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const styleOverrides = {
containerStyles: createStyles({
backgroundColor: system.color.bg.primary.default,
padding: system.space.x4,
}),
formFieldStyles: createStyles({
legend: {
color: system.color.text.inverse,
},
}),
};
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<Box cs={styleOverrides.containerStyles}>
<RadioGroup name="crust-inverse" onChange={handleChange} value={value}>
<RadioGroup.RadioButton variant="inverse" value="deep-dish">
Deep dish
</RadioGroup.RadioButton>
<RadioGroup.RadioButton variant="inverse" value="thin">
Thin
</RadioGroup.RadioButton>
<RadioGroup.RadioButton variant="inverse" value="gluten-free">
Gluten free
</RadioGroup.RadioButton>
<RadioGroup.RadioButton variant="inverse" value="cauliflower">
Cauliflower
</RadioGroup.RadioButton>
</RadioGroup>
</Box>
);
};
Radio Group with No Value
Omit the value prop from RadioGroup to render the group with no selected
RadioGroup.RadioButton.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>(0);
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<FormFieldGroup>
<FormFieldGroup.Label as="legend">Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.List
as={RadioGroup}
name="crust-no-value"
onChange={handleChange}
value={value}
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free">
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
</FormFieldGroup>
);
};
Ref Forwarding
RadioGroup.RadioButton supports ref forwarding.
It will forward ref to its underlying <input type="radio"> element.
import React from 'react';
import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const glutenFreeRef = React.useRef(null);
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
const handleClick = () => {
glutenFreeRef.current.click();
};
return (
<>
<FormFieldGroup>
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.List as={RadioGroup} name="crust-ref" onChange={handleChange} value={value}>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free" ref={glutenFreeRef}>
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
</FormFieldGroup>
<PrimaryButton onClick={handleClick}>Select Gluten Free</PrimaryButton>
</>
);
};
Label Position
Set the orientation prop of the Form Field to designate the position of the label relative to the
input component. By default, the orientation will be set to vertical.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<FormFieldGroup orientation="horizontalStart">
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.Field>
<FormFieldGroup.List
as={RadioGroup}
name="crust-label"
onChange={handleChange}
value={value}
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free">
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
</FormFieldGroup.Field>
</FormFieldGroup>
);
};
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.
You must choose a crust
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>('');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<FormFieldGroup isRequired={true}>
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.List
as={RadioGroup}
name="crust-required"
onChange={handleChange}
value={value}
aria-describedby="choose-crust"
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free">
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
<FormFieldGroup.Hint>You must choose a crust</FormFieldGroup.Hint>
</FormFieldGroup>
);
};
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.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<FormFieldGroup>
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.Field>
<FormFieldGroup.List
as={RadioGroup}
name="crust-disabled"
onChange={handleChange}
value={value}
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} disabled value="gluten-free">
Gluten free (sold out)
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
</FormFieldGroup.Field>
</FormFieldGroup>
);
};
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.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
import {Flex} from '@workday/canvas-kit-react/layout';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const styleOverrides = {
formfieldInputStyles: createStyles({
width: px2rem(200),
}),
radioGroupLabelTextStyles: createStyles({
color: system.color.fg.default,
}),
};
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<Flex flexDirection="column">
<FormFieldGroup>
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.Field>
<FormFieldGroup.List
as={RadioGroup}
name="pizza-crust-custom"
onChange={handleChange}
cs={styleOverrides.formfieldInputStyles}
value={value}
>
<RadioGroup.Label>
<FormFieldGroup.Input as={RadioGroup.Label.Input} value="deep-dish" />
<RadioGroup.Label.Text cs={styleOverrides.radioGroupLabelTextStyles}>
Deep dish
</RadioGroup.Label.Text>
</RadioGroup.Label>
<RadioGroup.Label>
<FormFieldGroup.Input as={RadioGroup.Label.Input} value="gluten-free" />
<RadioGroup.Label.Text cs={styleOverrides.radioGroupLabelTextStyles}>
Gluten free
</RadioGroup.Label.Text>
</RadioGroup.Label>
<RadioGroup.Label>
<FormFieldGroup.Input as={RadioGroup.Label.Input} value="cauliflower" />
<RadioGroup.Label.Text cs={styleOverrides.radioGroupLabelTextStyles}>
Cauliflower
</RadioGroup.Label.Text>
</RadioGroup.Label>
</FormFieldGroup.List>
</FormFieldGroup.Field>
</FormFieldGroup>
Value selected: {value}
</Flex>
);
};
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.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {StyledRadioButton} from '@workday/canvas-kit-preview-react/radio';
import {Flex} from '@workday/canvas-kit-react/layout';
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<Flex flexDirection="column">
<FormFieldGroup as="fieldset">
<FormFieldGroup.Label as="legend">Choose Your Pizza Crust</FormFieldGroup.Label>
<Flex gap="m">
<Flex as="label" gap="xs">
<FormFieldGroup.Input
as={StyledRadioButton}
onChange={handleChange}
value="deep-dish"
name="pizza-crust-standalone"
checked={value === 'deep-dish'}
/>
Deep dish
</Flex>
<Flex as="label" gap="xs">
<FormFieldGroup.Input
as={StyledRadioButton}
onChange={handleChange}
value="gluten-free"
checked={value === 'gluten-free'}
name="pizza-crust-standalone"
/>
Gluten free
</Flex>
</Flex>
</FormFieldGroup>
Value selected: {value}
</Flex>
);
};
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 "caution" or
"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.
Caution
Use the alert state when a selection is valid but there is additional information.
Deep dish is an extra $2.99.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<FormFieldGroup error="caution" id="hint-alert">
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.Field>
<FormFieldGroup.List
as={RadioGroup}
name="crust-alert"
onChange={handleChange}
value={value}
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free">
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
<FormFieldGroup.Hint>Deep dish is an extra $2.99.</FormFieldGroup.Hint>
</FormFieldGroup.Field>
</FormFieldGroup>
);
};
Error
Use the error state when the selection is no longer valid.
Deep dish is currently sold out.
import React from 'react';
import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
import {RadioGroup} from '@workday/canvas-kit-preview-react/radio';
export default () => {
const [value, setValue] = React.useState<string | number>('deep-dish');
const handleChange = (e: React.ChangeEvent) => {
const target = e.currentTarget;
if (target instanceof HTMLInputElement) {
setValue(target.value);
}
};
return (
<FormFieldGroup error="error">
<FormFieldGroup.Label>Choose Your Pizza Crust</FormFieldGroup.Label>
<FormFieldGroup.Field>
<FormFieldGroup.List
as={RadioGroup}
name="crust-error"
onChange={handleChange}
value={value}
>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="deep-dish">
Deep dish
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="thin">
Thin
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="gluten-free">
Gluten free
</FormFieldGroup.Input>
<FormFieldGroup.Input as={RadioGroup.RadioButton} value="cauliflower">
Cauliflower
</FormFieldGroup.Input>
</FormFieldGroup.List>
<FormFieldGroup.Hint>Deep dish is currently sold out.</FormFieldGroup.Hint>
</FormFieldGroup.Field>
</FormFieldGroup>
);
};
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.
Custom Styles
Radio and its subcomponents support custom styling via the cs prop. For more information, check
our
“How To Customize Styles”.
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 div. Changing the as prop will change the element interface.
Props extend from . If a model is passed, props from RadioModelConfig are ignored.
| Name | Type | Description | Default |
|---|---|---|---|
error | | The type of error associated with the RadioGroup (if applicable). | |
theme | | ||
cs | | The | |
children | ReactNode | ||
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
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 | ( | 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.RadioButton 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 and its sub components 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.
| Name | Type | Description | Default |
|---|---|---|---|
children | ReactNode | The Radio input and label children of RadioLabel | |
theme | | ||
cs | | The | |
disabled | boolean | undefined | ||
variant | 'inverse' | undefined | ||
value | string | number | ||
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | input |
ref | React.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 | |
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 | ( | 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.
| Name | Type | Description | Default |
|---|---|---|---|
children | ReactNode | The Radio input and label children of RadioLabel | |
theme | | ||
cs | | The | |
disabled | boolean | undefined | ||
variant | 'inverse' | undefined | ||
value | string | number | ||
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | label |
ref | React.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 | |
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 | ( | 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.
| Name | Type | Description | Default |
|---|---|---|---|
children | ReactNode | The Radio input and label children of RadioLabel | |
theme | | ||
cs | | The | |
disabled | boolean | undefined | ||
variant | 'inverse' | undefined | ||
value | string | number | ||
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | input |
ref | React.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 | |
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 | ( | 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:
useRadioInputRadioGroup.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.
| Name | Type | Description | Default |
|---|---|---|---|
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 | ( | 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.
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 buttonsSpace: select focused radio buttonDown ArroworRight Arrow: select the next radio buttonUp ArroworLeft 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
requiredattribute 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 aforattribute referencing the uniqueidvalue 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
disabledattribute 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.
Anatomy

- Container: Main container of the Radio Button.
- Dot: Circular shape used to indicate if the item is selected or unselected.
- Radio Label: Radio Labels give information about what to select.
Interaction States

- Mobile Radio Buttons support Inactive, Pressed, Selected, and Disabled states.
Usage Guidance
- 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 a list to be pre-selected by default. This default option should be the safest option presenting the least risk to the user.
- Alternatively, this default can be the option most commonly selected.
- If the user is allowed to not select any of the options, provide a “None”,“Not Applicable”, or “I prefer not to answer” 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 for binary options such as yes/no or active/disabled.
- 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 exceeds 8+ options or is 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.
Mobile Guidance
- Ensure a minimum tap target of 48dp to ensure that they are easy to interact with. For Radio Buttons, an additional 12dp of tappable horizontal and vertical padding are added to meet the minimum touch target.

Do
Use a minimum tap target of 48dp to ensure the Radio button is easy to interact with.

Don't
Use a tap target height smaller than 48dp, even if the Radio button might appear smaller visually.
API Guidelines
Component Definition
RadioButton
public struct RadioButton: ViewWD-Standard Radio Button component, a custom SwiftUI view.
Properties
body
public var body: some ViewMethods
init(isSelected:context:accessibilityLabel:content:)
public init<Content: View>(
isSelected: Binding<Bool>,
context: SemanticContext = .default,
accessibilityLabel: String = "",
@ViewBuilder content: @escaping () -> Content
)Creates an instance of Radio Button.
Parameters
| Name | Description |
|---|---|
| isSelected | Whether or not the radio button is selected by default. |
| context | SemanticContext of the field. |
| accessibilityLabel | accessibility label of the button, already localized. |
| content | The view content to be displayed to the right of the button. |
init(isSelected:context:accessibilityText:localizer:content:)
public init<Content: View>(
isSelected: Binding<Bool>,
context: SemanticContext = .default,
accessibilityText: String = "",
localizer: LocalizationAdapting,
@ViewBuilder content: @escaping () -> Content
)Creates an instance of Radio Button.
Parameters
| Name | Description |
|---|---|
| isSelected | Whether or not the radio button is selected by default. |
| context | SemanticContext of the field. |
| accessibilityText | accessibility text of the button content. |
| localizer | localizer used for localizing the radio button’s accessibility info. |
| content | The view content to be displayed to the right of the button. |
Accessibility Guidelines
Refreshed mobile guidelines will be coming soon!
Content Guidelines
- The Radio Label for each individual selection is 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.
Anatomy

- Container: Main container of the Radio Button.
- Dot: Circular shape used to indicate if the item is selected or unselected.
- Radio Label: Radio Labels give information about what to select.
Interaction States

- Mobile Radio Buttons support Inactive, Pressed, Selected, and Disabled states.
Usage Guidance
- 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 a list to be pre-selected by default. This default option should be the safest option presenting the least risk to the user.
- Alternatively, this default can be the option most commonly selected.
- If the user is allowed to not select any of the options, provide a “None”,“Not Applicable”, or “I prefer not to answer” 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 for binary options such as yes/no or active/disabled.
- 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 exceeds 8+ options or is 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.
Mobile Guidance
- Ensure a minimum tap target of 48dp to ensure that they are easy to interact with. For Radio Buttons, an additional 12dp of tappable horizontal and vertical padding are added to meet the minimum touch target.

Do
Use a minimum tap target of 48dp to ensure the Radio button is easy to interact with.

Don't
Use a tap target height smaller than 48dp, even if the Radio button might appear smaller visually.
API Guidelines
Component Definition
@Composable
fun NonInteractivePillUiComponent(
modifier: Modifier = Modifier,
selected: Boolean,
onClick: () -> Unit,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: RadioButtonUiComponentColors = RadioButtonUiComponentDefaults.colors())
) {Parameters
All undocumented parameters are native Android Compose types that can be found in the developer documentation.
| Name | Description |
|---|---|
| modifier | Modifier to be applied to the RadioButton |
| selected | whether this radio button is selected or not. |
| onClick | callback to be invoked when the RadioButton is clicked. If null, then this RadioButton will not handle input events, and only act as a visual indicator of selected state. |
| enabled | Controls the enabled state of the RadioButton. When false, this button will not be selectable and appears disabled. |
| interactionSource | the MutableInteractionSource representing the stream of Interactions for this RadioButton. You can create and pass in your own remembered MutableInteractionSource if you want to observe Interactions and customize the appearance / behavior of this RadioButton in different Interactions. |
| colors | RadioButtonUiComponentColors is used to resolve the color used for this RadioButton in different states. |
Accessibility Guidelines
Refreshed mobile guidelines will be coming soon!
Content Guidelines
- The Radio Label for each individual selection is 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. For further information, contact the #ask-canvas-design or #ask-canvas-kitchannels on Slack.