The Basics

What it is

RadioGroup enables users to choose a single option from 2+ mutually exclusive options. It’s essentially a list of multiple radio buttons.

How it works

  • The user clicks or activates an option’s radio button or clicks its text to select the option.
  • The user can deselect the option by clicking or activating another radio button or clicking another option’s text.
  • Once the user interacts with RadioGroup, an option always remains selected. The component can’t be reset to an unselected state.
  • The user’s selection usually isn’t saved until they take another action, like using a button (“Submit”).

When to use

  • To ask users to select a single option from a list
  • For short lists that can appear directly on the page, reducing the number of clicks

When not to use

  • For lists where users can select multiple options
  • For long lists that would take up too much vertical space on the page

What to use instead

List

Use selection style List if users can select multiple options.

Select

Use Select if the list of options would take up too much vertical space.

ToggleSwitch

Use ToggleSwitch for instant on/off settings.

How to use

RadioGroup can be used as a standalone component or with Form and FormField. Form provides a consistent, responsive layout, and FormField adds features like labels, error message handling, and hint text.

RadioGroup includes the interactive radio button element and its descriptive text. Both the radio button and the text can be clicked to select the option. This expands the clickable area, making the component more user friendly.

Default selection

In most cases, RadioGroup shouldn’t have an option selected by default. This is especially important in healthcare contexts. After the data is saved, it may not be clear if the user actively selected an option or forgot to answer and left the default selected. This can lead to problems with data integrity and even patient safety. For example, if “No known allergies” is selected by default, this could be saved incorrectly in the patient’s chart, potentially endangering the patient in the future.

Undoing a selection

Once a user selects any of RadioGroup’s options, one option always remains selected; the component can’t be reset to its unselected state. This is typical behavior for the HTML radio element on desktop apps (it varies in mobile interfaces). The only way to reset it completely is to refresh the page (and lose any data already entered).

This can be a problem if users need to be able to undo their selection and leave the RadioGroup blank. In this case, consider one of these approaches:

  • Using a different component. For example, Select limits users to a single option just like RadioGroup does, but it can be reset to have no option selected.
  • Including a tertiary Button near the RadioGroup that enables users to deselect all options. Use a Button name like Reset, Clear, or Undo.

As a last resort, you could include an option that doesn’t represent data, like “No response” or “Can’t answer”. For patient safety reasons, don’t use an option that could be interpreted as real data or a real response, like “None of the above”.

Saving user selections

In most cases, use a secondary action (like a “Next”, “Save”, or “Submit” button) to save user selections.

In certain cases, user selections have a real-time impact on the workflow. For example, billing flows often include RadioGroup options “My billing address is the same as my shipping address” and “I have a different shipping address”. Use this dynamic behavior only where it’s needed to help the workflow.

Style

Design details

RadioGroup’s layout changes automatically based on the number of options:

  • 2 options: horizontally aligned
  • 3+ options: vertically aligned

You can also set the layout manually, if these defaults don’t fit your design.

Required fields

Forge offers 3 options to indicate required form fields. See Form for details.

Spacing and size

The height of this component and the vertical space around it vary according to the form layout (i.e., medium, compact, super-compact). See Form for details.

Placement and hierarchy

No additional information for this component.

Content

Use sentence case for option text (“Procedure code”). If using a label that describes the set of options, make sure the label and radio button options work well together. For example:

  • Label: “Payment method”
  • Radio button options: “Debit card”, “Credit card”, and “Check”

Option text can contain custom formatting, so you can style the text.

Demos

Simple Options Share

Complex Options Share

Radio Children Share

Standalone Share

Coding

Developer tips

Each RadioGroup is required to have a unique ID in the context of a form. RadioGroup uses this identifier to further generate ID attributes for its children radio inputs and the radio inputs' labels.

RadioGroup generates its own ID automatically when used with FormField.

Required fields

Use the required prop to mark RadioGroup as required.

Forge offers 3 options to indicate required form fields. When using Form with this component, set Form’s requiredVariation prop. See Form for details.

Repository

Implementation links

RadioGroup directory in Bitbucket

Radio directory in Bitbucket

Implementation details

It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

Storybook files

Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook.

Testing library

Forge strongly encourages using testing-library to write tests for your application.

"The more your tests resemble the way your software is used, the more confidence they can give you."

If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

With that being said, many of Forge's components were not built with accessibility in mind. These components do break the recommendations listed above.

Import statements

In Nimbus applications

athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

import { RadioGroup, Radio } from '@athena/forge'

In standalone applications

Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

import RadioGroup from '@athena/forge/RadioGroup';
import Radio from '@athena/forge/Radio';

To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

{
"compilerOptions": {
"moduleResolution": "Node16",
}
}

If this setting doesn't work for your application, use this import statement instead:

import RadioGroup from '@athena/forge/dist/RadioGroup';
import Radio from '@athena/forge/dist/Radio';

Props