Tabs
Tabs group related page content to enable the quick discovery of information.

Element | Purpose |
---|---|
Scroll button | View hidden tabs to the left or right. |
Tab text | Describes the content within a tab. |
Overflow | A fade behavior that appears when there are too many tabs to fit horizontally in a view. |
Active tab indicator | A Guava-500 border under the tab text that indicates which tab is active. |
Divider | A component used to make consistent divider lines. |
- Tab Panels mount immediately
- Consider leveraging Tab state to delay queries for inactive tabs
Resize these examples to preview mobile behavior.
Tabs adapt to viewports of different widths by determining the available space. As the UI is condensed, the tab’s container will adjust accordingly into an overflow container.
Tabs comply with WAI-ARIA authoring guides. They are accessible to screen readers and operable from a keyboard using automatic activation.
Keys | Action |
---|---|
Tab | When not focused on the tab container, place focus on the first tab. When focused on a tab button, focus will be placed on its corresponding tab panel. |
Left arrow | Change focus to the previous tab. If focus is on the first tab, move focus to the last tab. |
Right arrow | Change focus to the next tab. If focus is on the last tab, move focus to the first tab. |
The IconButton component within tabs is removed from the tab order and hidden from screen readers.
Tabs is made up of four sub-components.
Subcomponent | Purpose |
---|---|
Tabs | The outermost container and parent of the Tab , TabList , and TabPanel sub-components. This sub-component matches each Tab with its corresponding TabPanel based on written order. |
TabList | The direct parent of all Tab elements. This sub-component is responsible for scroll behavior when screen space is limited, for event listening (clicking and focusing), as well as for the sliding highlight animation. |
Tab | Each Tab has a corresponding TabPanel , which becomes visible when the Tab is selected.A Tab is a button, so it can be hovered, clicked, and disabled. |
TabPanel | Each TabPanel has a corresponding Tab , and the TabPanel becomes visible when its Tab is selected. |
Tabs Props
Name | Type | Default | Description |
---|---|---|---|
children | ReactNode | The content of the Tabs container. | |
value | string | The value of the controlled selected Tab. |
TabList Props
Name | Type | Default | Description |
---|---|---|---|
children | ReactNode | The content of the TabList. | |
aria-label Required | string | A breakdown of what these tabs are about, used for screen reader accessibility. |
Tab Props
Name | Type | Default | Description |
---|---|---|---|
children | ReactNode | The content of the tab. | |
id | string | Custom ID for the Tab; used to associate it with its corresponding TabPanel. | |
value | string | An indexing value to be used by Tabs value prop to indicate controlled selection. | |
onClick | function | A function to handle controlled selected tab change. |
TabPanel Props
Name | Type | Default | Description |
---|---|---|---|
children | ReactNode | The content of the tab. | |
id | string | Custom ID for the TabPanel; used to associate it with its corresponding Tab. |
The following testing snippet(s) offer suggestions for testing the component using React Testing Library with occasional help from Jest.
const TestTabs = () => {return (<Tabs><TabList aria-label="Payroll and HR info"><Tab>Employees (12)</Tab><Tab>Departments (2)</Tab><Tab>Contractors</Tab></TabList><TabPanel>Employees panel.</TabPanel><TabPanel>Departments panel.</TabPanel><TabPanel>Contractors panel.</TabPanel></Tabs>);};render(<TestTabs />);const tablist = screen.getByLabelText(/Payroll and HR info/);const employeesTab = within(tablist).getByRole('tab', { name: 'Employees (12)' });const departmentsTab = within(tablist).getByRole('tab', { name: 'Departments' });const contractorsTab = within(tablist).getByRole('tab', { name: 'Contractors (2)' });const employeesTabPanel = screen.getByRole('tabpanel', { name: /Employees/ });const departmentsTabPanel = screen.getByText(/Departments panel./);const contractorsTabPanel = screen.getByText(/Contractors panel./);// Click Employees tab, Employees tabpanel is visible amd Departments tabpanel is notact(() => {userEvent.click(employeesTab);});expect(employeesTabPanel).toBeVisible();expect(departmentsTabPanel).not.toBeVisible();expect(contractorsTabPanel).not.toBeVisible();// Click Departments tab, Departments tabpanel is visible amd Employees tabpanel is notact(() => {userEvent.click(departmentsTab);});expect(employeesTabPanel).not.toBeVisible();expect(departmentsTabPanel).toBeVisible();expect(contractorsTabPanel).not.toBeVisible();// Click Contractors tab, Departments tabpanel is visible amd Employees tabpanel is notact(() => {userEvent.click(contractorsTab);});expect(employeesTabPanel).not.toBeVisible();expect(departmentsTabPanel).not.toBeVisible();expect(contractorsTabPanel).toBeVisible();