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.
Tab 1
Tab 2
Tab 3
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.
Tab 1
Tab 2
Tab 3
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.
Tab 1
Tab 2
Tab 3
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.
Tab 1
Tab 2
Tab 3
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.
Tab 1
Tab 2
Tab 3
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;