Skip to contentSkip to navigationSkip to topbar
Paste assistant Assistant
Figma
Star

Tabs

Version 8.2.1GithubStorybook

Tabs are labeled controls that allow users to switch between multiple views within a page.

Component preview theme
const HorizontalTabsExample = () => {
const selectedId = useUID();
return (
<Tabs selectedId={selectedId} baseId="horizontal-tabs-example">
<TabList aria-label="Horizontal product tabs">
<Tab>Programmable communications</Tab>
<Tab disabled>Super network</Tab>
<Tab id={selectedId}>Internet of things</Tab>
</TabList>
<TabPanels>
<TabPanel>
<Heading as="h3" variant="heading30">Programmable communications</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Messaging</Heading>
<Paragraph>Send and receive text messages from your app.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Voice</Heading>
<Paragraph>Make, receive, and control calls using code.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Super network</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Phone numbers</Heading>
<Paragraph>Choose from local or global numbers, Short Codes, Alphanumeric Sender IDs, etc.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Interconnect</Heading>
<Paragraph>Enable network-level security to protect communications.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Internet of things</Heading>
<Card>
<Heading as="h5" variant="heading50">Internet of things</Heading>
<Paragraph>Connect IoT devices to global cellular networks.</Paragraph>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
);
};
render(
<HorizontalTabsExample />
)

Guidelines

Guidelines page anchor

About Tabs

About Tabs page anchor

Tabs are labeled controls that allow users to switch between multiple views within a page. Tabs do not take the user to a new URL. To take users to a new URL, use In Page Navigation.

Panels within a set of Tabs should present different views of similar, parallel information. For example, these Twilio docs(link takes you to an external page) contain a block of code on the right side of the page with Tabs, allowing users to view the code in different languages. Reddit also uses tabs(link takes you to an external page), switching the user’s view between Posts, Communities, and Related Topics. The Tabs in both of these examples control views; they don’t direct to a new page. Conversely, the Github website(link takes you to an external page) demonstrates how some interactions may seem like Tabs, but are actually in-page navigation. Clicking on one of the sections at the top, like Code or Pull Requests, changes the URL.

Distinguishing between the two components (Tabs and In Page Navigation) leads to an improved user experience by visually communicating that interacting will lead to different behaviors. Selecting the correct component based on your use case also gives users of assistive technologies a better idea of where the interaction will lead.

Choose Tabs when users don’t need to see content from multiple views simultaneously. When thinking through what type of content to put in your Tabs, remember that the content should be parallel across the board. What lives in one Tab should be a different view of what lives in another Tab.


The Tabs component contains the following elements:

  • Tab: Clickable element that causes a selection within a tabset
  • TabPanel: Contains the content associated with the selected Tab
  • TabList: A collection of Tabs
  • TabPanels: A collection of TabPanels
  • Tabset (or Tabs): Composition of TabList and TabPanels

A Tab should never contain an interactive element, as doing so makes it difficult for users of assistive technologies to focus or click on the Tabs. Interactive elements may live within the TabPanels.

When the user is focused on a tab in a TabList, the following keyboard interactions apply:

  • Horizontal Tabs: Right and Left arrow keys move the user between Tabs and open the currently focused Tab's panel
  • Vertical Tabs: Up and Down arrow keys move between Tabs and open the currently focused Tab's panel
  • If the currently focused Tab is disabled, the TabPanel does not open

Tabs vs. In Page Navigation

Tabs vs. In Page Navigation page anchor

Tabs are used to layer related pieces of information together and display one layer at a time on the same URL. Use Tabs to alternate between views within the same context. In Page Navigation is a collection of anchors, rather than buttons. Use In Page Navigation to switch between different, related pages. Tabs replace the entire view based on the selected tab. In Page Navigation links navigate the user to a new page.

Use Horizontal Tabs in most cases, as they most realistically mimic a physical tab, and they catch the user’s attention because they live directly above the content.

Component preview theme
const HorizontalTabsExample = () => {
const selectedId = useUID();
return (
<Tabs selectedId={selectedId} baseId="horizontal-tabs-example">
<TabList aria-label="Horizontal product tabs">
<Tab>Programmable communications</Tab>
<Tab disabled>Super network</Tab>
<Tab id={selectedId}>Internet of things</Tab>
</TabList>
<TabPanels>
<TabPanel>
<Heading as="h3" variant="heading30">Programmable communications</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Messaging</Heading>
<Paragraph>Send and receive text messages from your app.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Voice</Heading>
<Paragraph>Make, receive, and control calls using code.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Super network</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Phone numbers</Heading>
<Paragraph>Choose from local or global numbers, Short Codes, Alphanumeric Sender IDs, etc.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Interconnect</Heading>
<Paragraph>Enable network-level security to protect communications.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Internet of things</Heading>
<Card>
<Heading as="h5" variant="heading50">Internet of things</Heading>
<Paragraph>Connect IoT devices to global cellular networks.</Paragraph>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
);
};
render(
<HorizontalTabsExample />
)

Use full-width Tabs to fill a parent element with a set width. Each Tab will equally expand and fit the width of the containing element. Full-width Tabs are recommended for compact spaces.

Component preview theme
const FullWidthTabsExample = () => {
const selectedId = useUID();
return (
<Tabs selectedId={selectedId} baseId="full-width-tabs-example" variant="full_width">
<TabList aria-label="Full width product tabs">
<Tab>Solutions</Tab>
<Tab id={selectedId}>Account security</Tab>
</TabList>
<TabPanels>
<TabPanel>
<Heading as="h3" variant="heading30">Solutions</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Flex</Heading>
<Paragraph>Build with the world's most flexible cloud contact center.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Task Router</Heading>
<Paragraph>Add intelligent task routing to assign tasks in your call center.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Account security</Heading>
<Card>
<Heading as="h5" variant="heading50">Verify</Heading>
<Paragraph>Verify your users with SMS, Voice, and email.</Paragraph>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
);
};
render(
<FullWidthTabsExample />
)

Use Vertical Tabs when the TabPanels are tall and narrow, or when users tend to swap views often as they scroll through the content.

Component preview theme
const VerticalTabsExample = () => {
const selectedId = useUID();
return (
<Tabs orientation="vertical" selectedId={selectedId} baseId="vertical-tabs-example">
<TabList aria-label="Vertical product tabs">
<Tab id={selectedId}>Developer tools</Tab>
<Tab>Marketplace</Tab>
<Tab>Solutions</Tab>
</TabList>
<TabPanels>
<TabPanel>
<Heading as="h3" variant="heading30">Developer tools</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Studio</Heading>
<Paragraph>Use a visual communications workflow builder for IVRs, reminders, etc.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Functions</Heading>
<Paragraph>Create serverless functions for custom logic and integrations.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Marketplace</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Add-ons</Heading>
<Paragraph>Choose add-ons to expand the functionality of your app.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Channels</Heading>
<Paragraph>Add Facebook Messenger channel.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Heading as="h3" variant="heading30">Solutions</Heading>
<Card>
<Heading as="h5" variant="heading50">Flex</Heading>
<Paragraph>Build with the world's most flexible cloud contact center.</Paragraph>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
);
};
render(
<VerticalTabsExample />
)

The state prop allows you to hook into, and keep in sync the state of the Tabs and the state of your application.

This will allow you to set the initial state and merge the returned state from the hook with the application state, and keep it in sync with user interactions.

You could use this if you want to add functionality to a Button within the Tab content. In the example below we're using the select function from the Tab state to advance to the next Tab, and go back to the previous Tab.

Component preview theme
const useButtonClickTabState = () => {
const tab = useTabState();
return {
...tab,
baseId: 'state-hook-tab-example',
};
};
const StateHookExample = () => {
const {...tab} = useButtonClickTabState();
return (
<Tabs state={tab}>
<TabList aria-label="State hook tabs">
<Tab>Programmable communications</Tab>
<Tab>Internet of things</Tab>
</TabList>
<TabPanels>
<TabPanel>
<Box marginBottom="space50">
<Button variant="primary" onClick={() => tab.select('state-hook-tab-example-2')}>
Go to internet of things tab
</Button>
</Box>
<Heading as="h3" variant="heading30">Programmable communications</Heading>
<Stack orientation="vertical" spacing="space60">
<Card>
<Heading as="h5" variant="heading50">Messaging</Heading>
<Paragraph>Send and receive text messages from your app.</Paragraph>
</Card>
<Card>
<Heading as="h5" variant="heading50">Voice</Heading>
<Paragraph>Make, receive, and control calls using code.</Paragraph>
</Card>
</Stack>
</TabPanel>
<TabPanel>
<Box marginBottom="space50">
<Button variant="primary" onClick={() => tab.select('state-hook-tab-example-1')}>
Go back to programmable communications tab
</Button>
</Box>
<Heading as="h3" variant="heading30">Internet of things</Heading>
<Card>
<Heading as="h5" variant="heading50">Internet of things</Heading>
<Paragraph>Connect IoT devices to global cellular networks.</Paragraph>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
);
};
render(
<StateHookExample />
)

Don't add interactive elements to a Tab, as doing so makes it difficult for users of assistive technologies to focus or click on the Tabs. Interactive elements may live within the TabPanels.

Tab labels should be short to improve readability. Users should be able to easily scan the Tabs and know what type of content to expect. Try to keep labels to 1-2 words each.

Labels should be parallel parts of speech. For example, all nouns (Documents, Images, Downloads).

Do

Use Tabs for displaying different views of similar information, such as one same block of code shown in different languages.

Don't

Don’t use Tabs when the selection of a new Tab will direct the user to a new URL.

Do

Keep Tab labels concise.

Don't

Don’t use more than 2 words in a Tab label, unless absolutely necessary.