The Basics

What it is

SegmentedButton is an interactive element that enables users to take complex button actions. It can allow users to select and deselect multiple options from a group of buttons, like List; or select a single option from 2+ mutually exclusive options, like RadioGroup; or choose from a set of related actions at the same level of emphasis. If SegmentedButton has a Menu in it, the dropdown menu displays secondary actions.

How it works

  • SegmentedButton can act as a radio button, clearable radio button, a checkbox button,  traditional button, or a Split-primary button.
  • For radio style SegmentedButtons:
    • The user clicks or activates an option’s button in SegmentedButton, which selects the option and makes it active. The button style changes to selected.
    • The user can deselect the option by activating another option. The deselected button changes back to its default style.
    • Once the user interacts with SegmentedButton, an option will remain selected, but in clearable radio style SegmentedButtons, the component can be reset to an unselected state by clicking on the button segment again.
  • For checkbox style SegmentedButtons:
    • The user clicks or activates an option’s button in SegmentedButton, which selects the option and makes it active. The button style changes to selected.
      The user can deselect an option by clicking or activating the same button again. The button changes back to its default style.
      The user’s selections usually aren’t saved until they take another action, like using a button (“Submit”).
  • For button style SegmentedButtons:
    • The user clicks or activates a button in SegmentedButton, which triggers an action.
    • If SegmentedButton has a Menu in it, the dropdown menu displays secondary actions. These items should work like the buttons in the main button row: when clicked or activated, they trigger an action.
  • For split-primary style SegmentedButtons:
    • There are only two button segments.
    • The user clicks or activates the primary (left) button in SegmentedButton, which triggers an action.
    • The right button has Menu in it, the dropdown menu displays additional actions. These items should work like the primary button: when clicked or activated, they trigger an action.

When to use

  • To ask users to select a single option while saving vertical space
  • To ask users to select one or more options in a horizontal layout
  • To group related actions in a single, compact element
  • To provide a more tappable user experience on mobile devices
  • To set filters or select a value or values from a list of options
  • For lists of options that are up to 3 words long
  • To display a primary action and “hide” secondary, related actions in a menu

When not to use

  • For lists of options that are more than 3 words long
  • For lists with so many options that users need to filter them

What to use instead

Button

Use Button for multiple unrelated action buttons.

RadioGroup

Use RadioGroup to display options as a list

List

Use a selection style List for a list with checkboxes to select options

ToggleSwitch

Use ToggleSwitch for instant on/off states.

Select

Use Select for filtering long lists

How to use

Use radio function SegmentedButton to set filters or select values from a set of options. Its button form makes it more visual and tappable, but behind the scenes, it works like RadioGroup.

Use checkbox function SegmentedButton to set filters or select values from a list of options. Its button form is more visual and tappable, but behind the scenes, it works like List.

Use button style SegmentedButton when you have a set of buttons for related actions that should be grouped together, like buttons for related document actions (Download, Share, Print), instead of spread out. By visually grouping these actions in the same element, SegmentedButton shows that they’re related, while saving horizontal space.

Use split-primary style SegmentedButton when you have a single primary action, and a set of related actions that should be grouped in a menu.

 

Do:

Group related actions in the same SegmentedButton.

<p>Group related actions in the same SegmentedButton.</p>
Don't:

Group unrelated functions or actions.

<p>Group unrelated functions or actions.</p>

Use SegmentedButton with a Menu in it when there’s a primary action and related, secondary options that are used less frequently (like a Save button with a dropdown that contains options to “Save & Print” and “Save & Close”).

 

Default Selection

In most cases, radio style SegmentedButton 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 a radio option, it will remain selected unless a different option is selected. In clearable radios, selecting the option again resets the component to an unselected state.

Style

Design details

The SegmentedButton group consists of 2+ buttons that are displayed horizontally by default. When displayed horizontally, SegmentedButton can be aligned as a connected or separated group. On screens smaller than 640px, they automatically stack vertically and span the width of their container. 

Size

SegmentedButton is available in four sizes:

  • Small (22px H)
  • Medium (28px H)
  • Large (32px H)
  • Extra Large (56px H)

Icons are only available in Large and Extra Large SegmentedButtons.

 

Placement and hierarchy

No additional information for this component.

Content

For all styles of SegmentedButton, use sentence case for button text (“All appointments”, not “all appointments” or “All Appointments”).

When used as a group of related buttons, SegmentedButton is designed to trigger actions, so use verbs for button text, not adjectives. Keep it short (1-2 words) to avoid wrapping and use title case (“Save File”, not “Save file”).

When using the icon-only version of SegmentedButton, make sure the meaning of the icon is clear without any text. The Icons guidelines page lists all Forge icons, their usage, and whether a label is required.

When using SegmentedButton with a Menu in it, the button that opens the menu should include the Expand icon and/or explanatory copy, like “More Actions”, “See More”, or “Other”. Use title case for menu text (“More Options”, not “More options”).  In the case of split-primary, there is only an expand chevron and no text in the right-hand segment.

Demos

Segmented Button Basic Share

Segmented Button Separated Share

Segmented Button Split Primary Share

Segmented Button Icons In Anchor Element Share

Segmented Button Controlled Radio Share

Segmented Button Different Behaviors Share

Coding

Developer tips

SegmentedButton takes React elements as its children; these should be Button and/or Menu components. For documentation, see the SegmentedButton props table and the Menu component page.

SegmentedButton is a wrapper element used to coordinate styling of its Button or Menu children. This styling also prevents the internal corners of buttons from rounding over when placed directly side by side.

To customize individual segments of a SegmentedButton see the Button props table for the Button component. For example, disabling a single option can be done by adding the 'disabled' prop from Button to an individual segment.

###Behavior

SegmentedButton is a generic component, where the generic parameter affects the type of the value and onChange props. If behavior="radio", then value and the event.target.value parameter passed to onChange can be strings. Otherwise they are string[].

To get split-primary styling, there are no specific props to set other than alignment="connected" behavior="button", which are the defaults.

Instead, split-primary styling is automatically applied when the first child is a <Button> and the second child is a <Menu trigger={<Button />}. If the menu trigger Button has any text, then split primary styling is not applied.

Repository

Implementation links

SegmentedButton 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 accessability 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 { SegmentedButton } 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 SegmentedButton from '@athena/forge/SegmentedButton';

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 SegmentedButton from '@athena/forge/dist/SegmentedButton';

Props