Tabs

Tabs are used to organize content by grouping similar information on the same page.

Neutral selected states

When the platform-dst-tokens-finesse feature flag is enabled, this component uses the new neutral treatment for selected states.

Default

The default form of tabs.

This is the content area of the first tab.
import { type ReactNode } from 'react'; import { css, jsx } from '@compiled/react'; import Tabs from '@atlaskit/tabs/tabs'; import Tab from '@atlaskit/tabs/tab'; import TabList from '@atlaskit/tabs/tab-list'; import TabPanel from '@atlaskit/tabs/tab-panel'; import { token } from '@atlaskit/tokens'; const panelStyles = css({ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', flexGrow: 1, backgroundColor: token('color.background.neutral'), borderRadius: token('radius.small', '3px'), color: token('color.text.subtlest'), font: token('font.heading.xxlarge'), marginBlockEnd: token('space.100'), marginBlockStart: token('space.200'), paddingBlockEnd: token('space.400'), paddingBlockStart: token('space.400'), paddingInlineEnd: token('space.400'), paddingInlineStart: token('space.400'), }); export const Panel: ({ children, testId, }: { children: ReactNode; testId?: string; }) => JSX.Element = ({ children, testId }: { children: ReactNode; testId?: string }) => ( <div css={panelStyles} data-testid={testId}> {children} </div> ); export default function TabsDefaultExample(): JSX.Element { return ( <Tabs onChange={(index) => console.log('Selected Tab', index + 1)} id="default"> <TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanel> <Panel>This is the content area of the first tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the second tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the third tab.</Panel> </TabPanel> </Tabs> ); }

Controlled

Tabs can be used as a controlled component.

This is the content area of the first tab.
import { type ReactNode, useCallback, useState } from 'react'; import { css, jsx } from '@compiled/react'; import Button from '@atlaskit/button/default/button'; import { Box } from '@atlaskit/primitives/compiled'; import Tabs from '@atlaskit/tabs/tabs'; import Tab from '@atlaskit/tabs/tab'; import TabList from '@atlaskit/tabs/tab-list'; import TabPanel from '@atlaskit/tabs/tab-panel'; import { type SelectedType } from '@atlaskit/tabs/types'; import { token } from '@atlaskit/tokens'; const panelStyles = css({ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', flexGrow: 1, backgroundColor: token('color.background.neutral'), borderRadius: token('radius.small', '3px'), color: token('color.text.subtlest'), font: token('font.heading.xxlarge'), marginBlockEnd: token('space.100'), marginBlockStart: token('space.200'), paddingBlockEnd: token('space.400'), paddingBlockStart: token('space.400'), paddingInlineEnd: token('space.400'), paddingInlineStart: token('space.400'), }); export const Panel: ({ children, testId, }: { children: ReactNode; testId?: string; }) => JSX.Element = ({ children, testId }: { children: ReactNode; testId?: string }) => ( <div css={panelStyles} data-testid={testId}> {children} </div> ); export default function TabsControlledExample(): JSX.Element { const [selected, setSelected] = useState(0); const handleUpdate = useCallback((index: SelectedType) => setSelected(index), [setSelected]); return ( <Box> <Tabs onChange={handleUpdate} selected={selected} id="controlled"> <TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanel> <Panel>This is the content area of the first tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the second tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the third tab.</Panel> </TabPanel> </Tabs> <Button isDisabled={selected === 2} onClick={() => handleUpdate(2)}> Select the last tab </Button> </Box> ); }

Customizing tab

Wrapping tab

You can wrap a tab in other presentational components. In this example we have added a tooltip to each tab.

This is the content area of the first tab.
import { type ReactNode } from 'react'; import { css, jsx } from '@compiled/react'; import Tabs from '@atlaskit/tabs/tabs'; import Tab from '@atlaskit/tabs/tab'; import TabList from '@atlaskit/tabs/tab-list'; import TabPanel from '@atlaskit/tabs/tab-panel'; import { token } from '@atlaskit/tokens'; import Tooltip from '@atlaskit/tooltip/Tooltip'; const panelStyles = css({ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', flexGrow: 1, backgroundColor: token('color.background.neutral'), borderRadius: token('radius.small', '3px'), color: token('color.text.subtlest'), font: token('font.heading.xxlarge'), marginBlockEnd: token('space.100'), marginBlockStart: token('space.200'), paddingBlockEnd: token('space.400'), paddingBlockStart: token('space.400'), paddingInlineEnd: token('space.400'), paddingInlineStart: token('space.400'), }); export const Panel: ({ children }: { children: ReactNode }) => JSX.Element = ({ children, }: { children: ReactNode; }) => <div css={panelStyles}>{children}</div>; const TooltipTab = ({ label, tooltip }: { label: string; tooltip: string }) => ( <Tooltip content={tooltip}> <Tab>{label}</Tab> </Tooltip> ); const TabTooltipExample: () => JSX.Element = () => ( <Tabs id="tooltip-tabs"> <TabList> <TooltipTab label="Tab 1" tooltip="Tooltip for tab 1" /> <TooltipTab label="Tab 2" tooltip="Tooltip for tab 2" /> <TooltipTab label="Tab 3" tooltip="Tooltip for tab 3" /> </TabList> <TabPanel> <Panel>This is the content area of the first tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the second tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the third tab.</Panel> </TabPanel> </Tabs> ); export default TabTooltipExample;

Custom tab

To customize a tab, call useTab and spread those attributes onto the custom tab.

This is the content area of the first tab.
import { type ReactNode } from 'react'; import { css } from '@compiled/react'; import { cssMap, jsx } from '@atlaskit/css'; import { Box } from '@atlaskit/primitives/compiled'; import Tabs from '@atlaskit/tabs/tabs'; import TabList from '@atlaskit/tabs/tab-list'; import TabPanel from '@atlaskit/tabs/tab-panel'; import useTab from '@atlaskit/tabs/use-tab'; import { token } from '@atlaskit/tokens'; const styles = cssMap({ customTab: { font: token('font.body.small'), }, }); const panelStyles = css({ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', flexGrow: 1, backgroundColor: token('color.background.neutral'), borderRadius: token('radius.small', '3px'), color: token('color.text.subtlest'), font: token('font.heading.xxlarge'), marginBlockEnd: token('space.100'), marginBlockStart: token('space.200'), paddingBlockEnd: token('space.400'), paddingBlockStart: token('space.400'), paddingInlineEnd: token('space.400'), paddingInlineStart: token('space.400'), }); export const Panel: ({ children }: { children: ReactNode }) => JSX.Element = ({ children, }: { children: ReactNode; }) => <div css={panelStyles}>{children}</div>; const CustomTab = ({ label }: { label: string }) => { const tabAttributes = useTab(); return ( <Box xcss={styles.customTab} {...tabAttributes}> {label} </Box> ); }; const TabCustomExample: () => JSX.Element = () => ( <Tabs id="custom-tabs"> <TabList> <CustomTab label="Tab 1" /> <CustomTab label="Tab 2" /> <CustomTab label="Tab 3" /> </TabList> <TabPanel> <Panel>This is the content area of the first tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the second tab.</Panel> </TabPanel> <TabPanel> <Panel>This is the content area of the third tab.</Panel> </TabPanel> </Tabs> ); export default TabCustomExample;

Customizing tab panel

To customize a tab panel, call useTabPanel and spread those attributes onto the custom tab panel.

One

Body of tab one

import { css, jsx } from '@compiled/react'; import { Box } from '@atlaskit/primitives/compiled'; import Tabs from '@atlaskit/tabs/tabs'; import Tab from '@atlaskit/tabs/tab'; import TabList from '@atlaskit/tabs/tab-list'; import useTabPanel from '@atlaskit/tabs/use-tab-panel'; import { token } from '@atlaskit/tokens'; const customPanelStyles = css({ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', flexGrow: 1, backgroundColor: token('color.background.neutral'), borderRadius: token('radius.small', '3px'), color: token('color.text.subtlest'), font: token('font.heading.xxlarge'), marginBlockEnd: token('space.100'), marginBlockStart: token('space.200'), paddingBlockEnd: token('space.400'), paddingBlockStart: token('space.400'), paddingInlineEnd: token('space.400'), paddingInlineStart: token('space.400'), '&&': { paddingBlockEnd: token('space.400'), paddingBlockStart: token('space.400'), paddingInlineEnd: token('space.400'), paddingInlineStart: token('space.400'), }, }); const CustomTabPanel = ({ heading, body }: { heading: string; body: string }) => { const tabPanelAttributes = useTabPanel(); return ( <div css={customPanelStyles} {...tabPanelAttributes}> <Box as="span">{heading}</Box> <p>{body}</p> </div> ); }; const TabPanelCustomExample: () => JSX.Element = () => ( <Tabs id="custom-panel"> <TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <CustomTabPanel heading="One" body="Body of tab one" /> <CustomTabPanel heading="Two" body="Body of tab two" /> <CustomTabPanel heading="Three" body="Body of tab three" /> </Tabs> ); export default TabPanelCustomExample;
Was this page helpful?
We use this feedback to improve our documentation.
© 2026 AtlassianTrademark, (opens new window)Privacy, (opens new window)License