Skip to content
lab components / Actions and controls

Content Switcher

Content Switchers are horizontal groups of two or more buttons that allow users to switch between alternate views of related content. There is only one content section displayed at a time.

This is a Lab component!

That means it doesn't satisfy our definition of done and may be changed or even deleted. For an exact status, please reach out to the Fancy team through the dev_fancy or ux_fancy channels.

import { ContentSwitcher } from "@siteimprove/fancylab";

#Examples

Use a ContentSwitcher as a content switcher. A ContentSwitcher looks and functions similarly to a button group. The difference is that a ContentSwitcher always has one option selected by default, and only one option can be selected at a time. Each option contains a required text label and an optional icon. The large variant has a required text description - as well as the required text label - and can use either an icon or an illustration.

A default option for a ContentSwitcher should be determined by its use.

  • Unselected options:

    selectable options for each view or item.
  • Selected option:

    Only one option can be selected at a time and one should always be selected in a default ContentSwitcher. If you do not want to display any of the options selected, use the Nothing selected variant.
  • Text label:

    the text label should clearly describe the content that appears below the ContentSwitcher.

#Default

const options: ContentSwitcherOption[] = [ { id: 1, label: "Option 1" }, { id: 2, label: "Option 2" }, { id: 3, label: "Option 3" }, ]; const [state, setState] = useState(options[0]); return <ContentSwitcher options={options} value={state} onChange={(item) => setState(item)} />;

#With Icons

const options: ContentSwitcherOption[] = [ { id: 1, label: "Option 1", icon: ( <Icon> <IconSettings /> </Icon> ), }, { id: 2, label: "Option 2", icon: ( <Icon> <IconEdit /> </Icon> ), }, { id: 3, label: "Option 3", icon: ( <Icon> <IconShare /> </Icon> ), }, ]; const [state, setState] = useState(options[0]); return <ContentSwitcher options={options} value={state} onChange={(item) => setState(item)} />;

#Large Variant

Each option in the large variant contains a required text label, a required text description, and an optional icon or illustration.

const options: LargeContentSwitcherOption[] = [ { id: 1, label: "Option 1", description: "Lorem ipsum dolor sit amet consectetur adipisicing elit.", }, { id: 2, label: "Option 2", icon: ( <Icon> <IconEdit /> </Icon> ), description: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos fuga totam numquam obcaecati rerum placeat voluptatibus nostrum ea ipsum.", }, { id: 3, label: "Option 3", icon: ( <Illustration src={IllustrationEducate} size={{ width: 32, height: 32 }} alt="Illustration with custom size" /> ), description: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Eos fuga totam numquam obcaecati rerum placeat voluptatibus nostrum ea ipsum, officia nesciunt natus animi, eveniet assumenda earum. Fugiat velit eaque quae.", }, ]; const [state, setState] = useState(options[0]); return ( <ContentSwitcher options={options} variant="large" value={state} onChange={(item) => setState(item)} /> );

#Nothing selected

Select none of the options by explicitly giving null as value (not just undefined).

const options: ContentSwitcherOption[] = [ { id: 1, label: "Option 1" }, { id: 2, label: "Option 2" }, { id: 3, label: "Option 3" }, ]; const [state, setState] = useState<ContentSwitcherOption | null>(null); return <ContentSwitcher options={options} value={state} onChange={(item) => setState(item)} />;

#Properties

PropertyDescriptionDefinedValue
valueRequired
| unknownValue of the form control
onChangeRequired
| functionCallback for onChange event
optionsRequired
| object[]Array of optional values for the group
nameOptional
stringName applied to the form control
idOptional
stringId applied to the form control
invalidOptional
booleanIs the form control invalid
onBlurOptional
functionCallback for onBlur event
aria-labelOptional
stringLabel of the form control
aria-describedbyOptional
stringID of an an element that describes what the form control is for
aria-labelledbyOptional
stringID of an an element that labels this form control
onInitOptional
functionExecute once content switcher has been initialized
inStaticModeOptional
"disable" | "hide" | "show"Specifies how content switcher looks in the static mode. Defaults to `disable`.
data-observe-keyOptional
stringUnique string, used by external script e.g. for event tracking
classNameOptional
stringCustom className that's applied to the outermost element (only intended for special cases)
styleOptional
objectStyle object to apply custom inline styles (only intended for special cases)
tabIndexOptional
numberTab index of the outermost HTML element of the component
onKeyDownOptional
functionCallback for onKeyDown event
onMouseDownOptional
functionCallback for onMouseDown event
onMouseEnterOptional
functionCallback for onMouseEnter event
onMouseLeaveOptional
functionCallback for onMouseLeave event
onFocusOptional
functionCallback for onFocus event
variantOptional
"default" | "large"Variant

#Guidelines

#Best practices

#General

Use ContentSwitcher when

  • the user can select only one option from a set of two to five related options or views.

#Placement

ContentSwitcher is typically used in the following place:

  • Cards

    The ContentSwitcher is often used in cards to help users display different options, states, or views. Be careful when writing a header for the card. The text label of a ContentSwitcher should stand out clearly from the Card header. To ensure a clear hierarchy of information, do not use the ContentSwitcher and Tabs in the same container-level component, such as Card, Modal or Side Panel. Tabs have a higher hierarchy level and allow navigation between groups of related content. Examples of ContentSwitcher in cards can be found in Analytics/Visitors/Summary.

#Style

  • On a desktop screen, there should be no more than five to seven options, and on narrow-width interfaces, such as side panels, there should be no more than five options.
  • An explanation for a content switcher should be provided as a header.
  • Keep the layout consistent by placing a content switcher in the centre and above the content, if it is possible.
  • Carefully consider where you position a content switcher with other components. When trying to switch between options, the user might accidentally click other components if they are too close.
  • A content switcher can only have one row. Do not break down the content switcher with a second row.

#Do not use when

  • the user can turn things on or off with an immediate effect. Use the Toggle Switch instead.
  • the content of the page is displayed separately without overlapping. In this case, use Tabs instead.
  • the user can take actions, such as adding, removing, or editing content. Use the Button group instead.
  • there are more than seven options. In this case, use Select instead.

#Accessibility

#For designers

  • If possible, always provide a visible label for ContentSwitcher. Alternatively, provide an aria-label to describe the purpose of ContentSwitcher.
  • Do not include tooltips or badges in the ContentSwitcher.
  • Make sure that the switch buttons and the related content is placed immediately after each other so that users can easily understand the connection between them.
  • Each switch button must have a unique text label that clearly describes the content of the switch button. This is especially helpful for assistive technology users so that they have the information they need to navigate the content efficiently.

#For developers

  • The ContentSwitcher has built-in accessibility. There are no additional requirements for developers. However, if a designer has specified an aria-label, that should be implemented.

Explore detailed guidelines for this component: Accessibility Specifications

#Writing

  • Use sentence case for a text label.
  • Keep text labels short — 1 to 3 words.
  • Text labels should make it clear which view users will see and what content the view contains.