Tabs
Tabs are UI elements for organizing and navigating between groups of related content.
Tabs are implemented using a collection of related components:
TabUnstyled
- the tab element itself. Clicking on a tab displays its corresponding panel.TabsListUnstyled
- the container that houses the tabs. Responsible for handling focus and keyboard navigation between tabs.TabPanelUnstyled
- the card that hosts the content associated with a tab.TabsUnstyled
- the top-level component that wrapsTabsListUnstyled
andTabPanelUnstyled
so that tabs and their panels can communicate with one another.
Basic tabs
import TabUnstyled from '@mui/base/TabUnstyled';
import TabsListUnstyled from '@mui/base/TabUnstyled';
import TabPanelUnstyled from '@mui/base/TabPanelUnstyled';
import TabsUnstyled from '@mui/base/TabsUnstyled';
By default, tabs and their corresponding panels are zero-indexed (i.e. the first tab has a value
of 0
, then 1
, 2
, etc.). Clicking on a given tab opens the panel with the same value
, which corresponds to the order in which each component is nested within its container.
Though not required, you can add the value
prop to TabUnstyled
and TabPanelUnstyled
to take control over how these components are associated with one another.
The following demo omits the value
prop from the TabUnstyled
components, and also defines 0
as the defaultValue
for TabsUnstyled
, which sets the first tab and panel as the defaults:
<TabsUnstyled defaultValue={0}>
<TabsListUnstyled>
<TabUnstyled>One</TabUnstyled>
<TabUnstyled>Two</TabUnstyled>
<TabUnstyled>Three</TabUnstyled>
</TabsListUnstyled>
<TabPanelUnstyled value={0}>First page</TabPanelUnstyled>
<TabPanelUnstyled value={1}>Second page</TabPanelUnstyled>
<TabPanelUnstyled value={2}>Third page</TabPanelUnstyled>
</TabsUnstyled>
Customizing the root element
By default, TabUnstyled
renders a native HTML <button>
element.
You can override this by setting the component
or components.Root
prop.
If a non-interactive element (such as a <span>
) is provided this way, the TabUnstyled
will take care of adding the necessary accessibility attributes.
The TabPanelUnstyled
renders a native <div>
element by default.
You can override this by setting the component
or components.Root
prop on the TabPanelUnstyled
.
<TabsUnstyled defaultValue={0}>
<TabsList>
<Tab>One</Tab>
<Tab>Two</Tab>
<Tab>Three</Tab>
</TabsList>
<TabPanel value={0}>First page</TabPanel>
<TabPanel value={1}>Second page</TabPanel>
<TabPanel value={2}>Third page</TabPanel>
</TabsUnstyled>
Third-party routing library
A common use case for tabs is to implement client-side navigation that doesn't require an HTTP round-trip to the server.
The TabUnstyled
component provides the component
prop to handle this use case—see the Material UI documentation on routing for more details.
Accessibility
(WAI-ARIA: https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/)
The following steps are necessary to make the tab component suite accessible to assistive technology:
- Label
TabsUnstyled
witharia-label
oraria-labelledby
. - Connect each
TabUnstyled
component to its correspondingTabPanelUnstyled
by setting the correctid
,aria-controls
andaria-labelledby
.
The demos below illustrate the proper use of ARIA labels.
Keyboard navigation
By default, when using keyboard navigation, the tab components open via manual activation—that is, the next panel is displayed only after the user activates the tab with either Space, Enter, or a mouse click.
This is the preferable behavior for tabs in most cases, acccording to the WAI-ARIA authoring practices.
Alternatively, you can set the panels to be displayed automatically when their corresponding tabs are in focus—this behavior of the selection following the focus is known as automatic activation.
To enable automatic activation, pass the selectionFollowsFocus
prop to the TabsUnstyled
component:
/* Tabs where selection follows focus */
<TabsUnstyled selectionFollowsFocus />
The following demo pair illustrates the difference between manual and automatic activation. Move the focus to a tab in either demo and navigate with the arrow keys to observe the difference:
Selection following focus:
Selection independent of focus (default behavior):