A tabbed interface supporting local state and URL-based navigation.
import { Tabs, TabList, Tab, TabPanel } from '@backstage/ui';
<Tabs>
<TabList>
<Tab id="tab1">Tab 1</Tab>
<Tab id="tab2">Tab 2</Tab>
</TabList>
<TabPanel id="tab1">Content 1</TabPanel>
<TabPanel id="tab2">Content 2</TabPanel>
</Tabs>Container that groups the tab list and panels.
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | horizontalvertical | horizontal | Layout direction. Use horizontal for top navigation, vertical for sidebar-style. |
| selectedKey | string | - | The currently selected tab key (controlled). |
| defaultSelectedKey | string | - | The default selected tab key (uncontrolled). |
| onSelectionChange | (key: Key) => void | - | Handler called when the selected tab changes. |
| isDisabled | boolean | false | Disables all tabs. Use when an entire section is unavailable. |
| disabledKeys | Iterable<Key> | - | Keys of tabs that should be disabled. |
| children | ReactNode | - | |
| className | string | - | Additional CSS class name for custom styling. |
Inherits all React Aria Tabs props.
Container for the tab buttons.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | - | |
| className | string | - | Additional CSS class name for custom styling. |
Inherits all React Aria TabList props.
Individual tab button. Add href to enable URL-based tab selection.
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | - | Unique identifier matching the corresponding TabPanel. |
| href | string | - | URL to navigate to. When set, tab selection is controlled by the current route. |
| matchStrategy | exactprefix | exact | URL matching strategy. Use exact for leaf routes, prefix for parent routes. |
| isDisabled | boolean | false | Disables this tab. Use for temporarily unavailable options. |
| children | ReactNode | - | |
| className | string | - | Additional CSS class name for custom styling. |
Inherits all React Aria Tab props.
Content panel associated with a tab.
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | - | Unique identifier matching the corresponding Tab. |
| children | ReactNode | - | |
| className | string | - | Additional CSS class name for custom styling. |
Inherits all React Aria TabPanel props.
<Tabs defaultSelectedKey="tab2">
<TabList>
<Tab id="tab1">Tab 1</Tab>
<Tab id="tab2">Tab 2</Tab>
<Tab id="tab3">Tab 3</Tab>
</TabList>
<TabPanel id="tab1">Content 1</TabPanel>
<TabPanel id="tab2">Content 2</TabPanel>
<TabPanel id="tab3">Content 3</TabPanel>
</Tabs><Tabs>
<TabList>
<Tab id="tab1">Tab 1</Tab>
<Tab id="tab2" isDisabled>Tab 2 (Disabled)</Tab>
<Tab id="tab3">Tab 3</Tab>
</TabList>
<TabPanel id="tab1">Content 1</TabPanel>
<TabPanel id="tab2">Content 2</TabPanel>
<TabPanel id="tab3">Content 3</TabPanel>
</Tabs><Tabs orientation="vertical">
<TabList>
<Tab id="tab1">Tab 1</Tab>
<Tab id="tab2">Tab 2</Tab>
<Tab id="tab3">Tab 3</Tab>
</TabList>
<TabPanel id="tab1">Content 1</TabPanel>
<TabPanel id="tab2">Content 2</TabPanel>
<TabPanel id="tab3">Content 3</TabPanel>
</Tabs>Add href to Tab components to enable URL-based tab selection. The active tab is determined by the current route.
<Tabs>
<TabList>
<Tab id="overview" href="/settings/overview">Overview</Tab>
<Tab id="profile" href="/settings/profile">Profile</Tab>
<Tab id="security" href="/settings/security">Security</Tab>
</TabList>
<TabPanel id="overview">Overview content</TabPanel>
<TabPanel id="profile">Profile content</TabPanel>
<TabPanel id="security">Security content</TabPanel>
</Tabs>Our theming system is based on a mix between CSS classes, CSS variables and data attributes. If you want to customise this component, you can use one of these class names below.
bui-Tabsbui-TabListbui-TabListWrapperbui-Tabbui-TabActivebui-TabHoveredbui-TabPanelBreaking Changed className prop behavior to augment default styles instead of being ignored or overriding them.
If you were passing custom className values to any of these components that relied on the previous behavior, you may need to adjust your styles to account for the default classes now being applied alongside your custom classes. #31496