Tabs

Organize related content into switchable panels readers can flip between.

Use <Tabs> to organize content into switchable panels. Add any number of <TabItem> children and include other content (code blocks, callouts, or lists) inside each panel.

Each <TabItem> needs a label (what readers see) and a value (a stable ID for defaults, sync, and persistence). Keep value fixed even if you rename the label.

mdx
<Tabs>
  <TabItem label="First" value="first">Content here</TabItem>
</Tabs>

Example

Welcome to the content inside the first tab.

You can nest other components inside tabs. For example, a code block:

js
export function greet(name) {
  return `Hello, ${name}!`;
}
mdx
<Tabs>
  <TabItem label="First tab" value="first">
    Welcome to the content inside the first tab.

    You can nest other components inside tabs. For example, a code block:

    ```js
    export function greet(name) {
      return `Hello, ${name}!`;
    }
    ```
  </TabItem>
  <TabItem label="Second tab" value="second">
    Panels can contain lists too:

    - Install dependencies
    - Configure your project
    - Deploy
  </TabItem>
  <TabItem label="Third tab" value="third">
    <Info>
      Callouts and other components work inside tabs as well.
    </Info>
  </TabItem>
</Tabs>

Properties

Tabs

defaultValuestringoptional

The tab to show on first load. Must match a TabItem value.

Defaults to the first tab.


groupIdstringoptional

A shared identifier for synchronized tab groups. Tabs with the same groupId stay in sync by matching value values across groups.

When set, the selected tab is stored in local storage and restored on reload. Preview mode uses the key preview:tabs:{groupId}; published docs use docs.page:tabs:{owner}/{repository}:{groupId}.

TabItem

labelstringrequired

The text shown on the tab trigger. Use short, scannable labels such as JavaScript or CLI.


valuestringrequired

A stable identifier for the tab within its group. Used by defaultValue and by groupId synchronization across tab groups.

Choose a value that won't change when you edit the label, for example label="JavaScript" with value="js".

Synchronization

Tab groups are independent by default. To keep multiple groups in sync, set the same groupId on each <Tabs> and use the same value on corresponding <TabItem> children.

Use this when the same options appear in more than one place, for example language-specific install steps and matching API examples.

The example below uses two groups that share groupId="language". Selecting JavaScript in either group selects JavaScript in both.

js
import axios from 'axios';
js
const response = await axios.get('https://example.com');
mdx
<Tabs groupId="language">
  <TabItem label="JavaScript" value="js">...</TabItem>
  <TabItem label="Dart" value="dart">...</TabItem>
</Tabs>

<Tabs groupId="language">
  <TabItem label="JavaScript" value="js">...</TabItem>
  <TabItem label="Dart" value="dart">...</TabItem>
</Tabs>

Behavior

ConditionResult
No valid <TabItem> childrenRenders nothing
Selected value is not in the current groupFalls back to defaultValue, then the first tab
defaultValue does not match any valueFalls back to the first tab
groupId omittedTab groups on the page operate independently
groupId setSelection syncs across groups and persists in local storage on reload

See also