Tabs
Reduce visual complexity of long forms using tabs.
Use TabNav for navigation links styled as tabs.
Use Segmented Control for switching between views or modes of the same content.
Example
Usage
Decorators: counts, tooltips, and status indicators
Add the following props to a Tab to add decorations to the tab:
- Add the
countprop to display a gray badge with the count within the Tab. - Add the
countFormatterprop to change the way the count is rendered. - Add the
badgeVariantprop to change the variant of the badge within the Tab. - Add the
tooltipprop to add a tooltip to the text. - Add the
statusIndicatorprop to add an extra indicator to the right of the Tab text.
Use these instead of directly rendering additional components within the Tab itself.
Controlled
There are cases when state of tabs is managed elsewhere. For example, when tabs are switched based on the current URL.
Loading
Tabs have their own loading state when used with the Skeleton component.
Guidelines
When to use
- When there are many related sections and one section needs to be shown at a time.
- When each tab leads to distinct content sectioned into its own panel — for example, "Overview" vs. "Messages" vs. "Configuration". The user is choosing what to look at.
- When tabs benefit from decorators such as counts, badges, or status indicators (for example, an unread message count or an error state on a section).
When not to use
- When content from multiple tabs needs to be shown at the same time.
- As a way to indicate progress of filling out a form or a similar component.
- As a way to filter content.
- When switching tabs should navigate to a different URL. Use Tab Nav instead.
- When each option is a different view or mode of the same content — for example, rendering one dataset as a list, table, or heatmap, or toggling a chart between daily, weekly, and monthly granularity. Use a Segmented Control instead — the user is choosing how the content renders, not what to look at.
Tabs vs. Segmented Control
Both components present a row of mutually exclusive options, but they differ semantically and for assistive technology:
- Tabs — different content, sectioned into panels. Each panel is its own thing; the user is choosing a destination. Screen readers announce tabs as a navigable tab list with associated panels.
- Segmented Control — same content, different lens. Switching is instant, cheap, and stateless-feeling. It is semantically a radio group styled as buttons — mutually exclusive settings, not destinations — and screen readers announce it as a set of options rather than as navigation.
If you're unsure, ask: "Is the user picking what to see, or how to see it?" Use Tabs for what, Segmented Control for how.
Content
- Use sentence case for tab titles.
- Keep tab titles to 3 words max.
Accessibility
It is important to directly nest Tab within the parent TabList. Any intermediate elements will break a11y compliance.
Props
Tabs
Inherits margin props.
| Name | Default | Description |
|---|---|---|
children | — | ReactNodeTab list and panels. |
index | — | numberIndex of selected tab. |
onChange | — | (index: number) => voidCallback for when user selects a different tab. |
TabList
| Name | Default | Description |
|---|---|---|
children | — | ReactNodeTabs. |
Tab
| Name | Default | Description |
|---|---|---|
badgeVariant | — | BadgeProps["variant"]The variant of the badge if a count is provided. |
children | — | stringTab title. |
count | — | numberOptional count to display near the title. |
countFormatter | — | (count: number) => string | numberOptional function to format the count. |
tooltip | — | Omit<TooltipProps, "children">Optional tooltip to add to the text. |
statusIndicator | — | ReactNodeOptional status indicator to place to the right of the text. |
isDisabled | false | booleanIf tab is disabled. |
TabPanels
| Name | Default | Description |
|---|---|---|
children | — | ReactNodeTab panels. |
TabPanel
| Name | Default | Description |
|---|---|---|
children | — | ReactNodeTab content. |