Tabs

Groups the tabs and the corresponding panels.

Tabs is a collection of React components that combine to render an ARIA-compliant tabs pattern.

import { Tabs } from '@wordpress/ui';

View on Storybook

View source on GitHub

PropsPermalink to this section

NameDefaultDescription
className

string

CSS class name to apply to the element.

style

React.CSSProperties

CSS style to apply to the element.

render

| ComponentRenderFn< HTMLAttributesWithRef > | React.ReactElement< Record< string, unknown > >

Replaces the component’s default HTML element using a given React element, or a function that returns a React element.

children

ReactNode

The content to be rendered inside the component.

ExamplesPermalink to this section

DefaultPermalink to this section

const Default = () => <Tabs.Root defaultValue="tab1">(<>
        <Tabs.List>
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;

MinimalPermalink to this section

const Minimal = () => <Tabs.Root>(<>
        <Tabs.List variant="minimal">
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;

Size And Overflow PlaygroundPermalink to this section

const SizeAndOverflowPlayground = function SizeAndOverflowPlayground( props ) {
    const [ fullWidth, setFullWidth ] = useState( false );
    return (
        <div>
            <div
                style={ {
                    maxWidth: '40rem',
                    marginBottom: '1rem',
                    color: 'var( --wpds-color-fg-content-neutral )',
                } }
            >
                <p>
                    This story helps understand how the TabList component
                    behaves under different conditions. The container below
                    (with the dotted red border) can be horizontally
                    resized, and it has a bit of padding to be out of the
                    way of the TabList.
                </p>
                <p>
                    The button will toggle between full width (adding{ ' ' }
                    <code>width: 100%</code>) and the default width.
                </p>
                <p>Try the following:</p>
                <ul>
                    <li>
                        <strong>Small container</strong> that causes tabs to
                        overflow with scroll.
                    </li>
                    <li>
                        <strong>Large container</strong> that exceeds the
                        normal width of the tabs.
                        <ul>
                            <li>
                                <strong>
                                    With <code>width: 100%</code>
                                </strong>{ ' ' }
                                set on the TabList (tabs fill up the space).
                            </li>
                            <li>
                                <strong>
                                    Without <code>width: 100%</code>
                                </strong>{ ' ' }
                                (defaults to <code>auto</code>) set on the
                                TabList (tabs take up space proportional to
                                their content).
                            </li>
                        </ul>
                    </li>
                </ul>
            </div>
            <button
                style={ { marginBottom: '1rem' } }
                onClick={ () => setFullWidth( ! fullWidth ) }
            >
                { fullWidth
                    ? 'Remove width: 100% from TabList'
                    : 'Set width: 100% in TabList' }
            </button>
            <Tabs.Root
                { ...props }
                style={ {
                    ...props.style,
                    width: '20rem',
                    border: '2px dotted red',
                    padding: '1rem',
                    resize: 'horizontal',
                    overflow: 'auto',
                } }
            >
                <Tabs.List
                    style={ {
                        maxWidth: '100%',
                        width: fullWidth ? '100%' : undefined,
                    } }
                >
                    <Tabs.Tab value="tab1">
                        Label with multiple words
                    </Tabs.Tab>
                    <Tabs.Tab value="tab2">Short</Tabs.Tab>
                    <Tabs.Tab value="tab3">
                        Hippopotomonstrosesquippedaliophobia
                    </Tabs.Tab>
                    <Tabs.Tab value="tab4">Tab 4</Tabs.Tab>
                    <Tabs.Tab value="tab5">Tab 5</Tabs.Tab>
                </Tabs.List>

                <Tabs.Panel value="tab1">
                    <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
                    <ThemedParagraph>
                        (Label with multiple words)
                    </ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab2">
                    <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
                    <ThemedParagraph>(Short)</ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab3">
                    <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
                    <ThemedParagraph>
                        (Hippopotomonstrosesquippedaliophobia)
                    </ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab4">
                    <ThemedParagraph>Selected tab: Tab 4</ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab5">
                    <ThemedParagraph>Selected tab: Tab 5</ThemedParagraph>
                </Tabs.Panel>
            </Tabs.Root>
        </div>
    );
};

VerticalPermalink to this section

const Vertical = () => <Tabs.Root
    orientation="vertical"
    style={{
        minWidth: '320px',
        display: 'grid',
        gridTemplateColumns: '120px 1fr',
        gap: '24px',
    }} />;

With Disabled TabPermalink to this section

const WithDisabledTab = () => <Tabs.Root defaultValue="tab3">(<>
        <Tabs.List>
            <Tabs.Tab value="tab1" disabled>
                Tab 1
            </Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;

With Tab Icons And TooltipsPermalink to this section

const WithTabIconsAndTooltips = () => <Tabs.Root>(<>
        <Tabs.List>
            { tabWithIconsData.map(
                ( { value, label, icon: Icon } ) => (
                    <Tooltip.Root key={ value }>
                        <Tooltip.Trigger
                            aria-label={ label }
                            render={ <Tabs.Tab value={ value } /> }
                        >
                            { /* TODO: potentially refactor with new Icon component */ }
                            <Icon
                                style={ {
                                    width: '20px',
                                    height: '20px',
                                } }
                            />
                        </Tooltip.Trigger>
                        <Tooltip.Popup
                            positioner={
                                <Tooltip.Positioner
                                    align="center"
                                    side="top"
                                />
                            }
                        >
                            { label }
                        </Tooltip.Popup>
                    </Tooltip.Root>
                )
            ) }
        </Tabs.List>
        { tabWithIconsData.map( ( { value, label } ) => (
            <Tabs.Panel value={ value } key={ value }>
                <ThemedParagraph>
                    Selected tab: { label }
                </ThemedParagraph>
            </Tabs.Panel>
        ) ) }
    </>)</Tabs.Root>;

With Panels Always MountedPermalink to this section

const WithPanelsAlwaysMounted = () => <Tabs.Root>(<>
        <Tabs.List>
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1" keepMounted>
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2" keepMounted>
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3" keepMounted>
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;

With Non Focusable PanelsPermalink to this section

const WithNonFocusablePanels = () => <Tabs.Root>(<>
        <Tabs.List>
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1" tabIndex={ -1 }>
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
            <ThemedParagraph>
                This tabpanel is not focusable, therefore tabbing into
                it will focus its first tabbable child.
            </ThemedParagraph>
            <button>Focus me</button>
        </Tabs.Panel>
        <Tabs.Panel value="tab2" tabIndex={ -1 }>
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
            <ThemedParagraph>
                This tabpanel is not focusable, therefore tabbing into
                it will focus its first tabbable child.
            </ThemedParagraph>
            <button>Focus me</button>
        </Tabs.Panel>
        <Tabs.Panel value="tab3" tabIndex={ -1 }>
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
            <ThemedParagraph>
                This tabpanel is not focusable, therefore tabbing into
                it will focus its first tabbable child.
            </ThemedParagraph>
            <button>Focus me</button>
        </Tabs.Panel>
    </>)</Tabs.Root>;