Tabs
Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.
Content
TabList
follows the Collection Components API, accepting both static and dynamic collections. This example shows a dynamic collection, passing a list of objects to the items
prop, and a function to render the children.
import {ActionButton, ActionButtonGroup, Tabs, TabList, Tab, TabPanel, Collection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useState} from 'react';
function Example() {
let [tabs, setTabs] = useState([
{id: 1, title: 'Tab 1', content: 'Tab body 1'},
{id: 2, title: 'Tab 2', content: 'Tab body 2'},
{id: 3, title: 'Tab 3', content: 'Tab body 3'}
]);
let addTab = () => {
setTabs(tabs => [
...tabs,
{
id: tabs.length + 1,
title: `Tab ${tabs.length + 1}`,
content: `Tab body ${tabs.length + 1}`
}
]);
};
let removeTab = () => {
if (tabs.length > 1) {
setTabs(tabs => tabs.slice(0, -1));
}
};
return (
<Tabs aria-label="Tabs" styles={style({width: 'full'})}>
<div className={style({display: 'flex', alignItems: 'center'})}>
<TabList
items={tabs}
styles={style({flexShrink: 1, flexGrow: 1, flexBasis: 'auto'})}>
{item => <Tab>{item.title}</Tab>}
</TabList>
<ActionButtonGroup density="compact" size="S">
<ActionButton onPress={addTab}>Add tab</ActionButton>
<ActionButton onPress={removeTab}>Remove tab</ActionButton>
</ActionButtonGroup>
</div>
<Collection items={tabs}>
{item => <TabPanel>{item.content}</TabPanel>}
</Collection>
</Tabs>
)
}
Icons
Tag
supports icons and text as children. Text is always required, but can be hidden when the tabs are expanded using the labelBehavior
prop.
Overflow behavior
Horizontal tabs automatically collapse into a Picker when space is limited.
import {Tabs, TabList, Tab, TabPanel} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
<div
className={style({
width: 320,
padding: 16,
borderWidth: 1,
borderStyle: 'solid',
borderColor: 'gray-300',
borderRadius: 'default',
overflow: 'hidden'
})}
style={{resize: 'horizontal'}}>
<Tabs aria-label="Tabs">
<TabList>
<Tab id="home">Home</Tab>
<Tab id="profile">Profile</Tab>
<Tab id="contact">Contact</Tab>
<Tab id="about">About</Tab>
</TabList>
<TabPanel id="home">
Welcome home
</TabPanel>
<TabPanel id="profile">
View your profile
</TabPanel>
<TabPanel id="contact">
Find your contacts
</TabPanel>
<TabPanel id="about">
Learn more
</TabPanel>
</Tabs>
</div>
Selection
Use the defaultSelectedKey
or selectedKey
prop to set the selected tab. The selected key corresponds to the id
prop of a <Tab>
. Tabs can be disabled with the isDisabled
prop. See the selection guide for more details.
Selected tab: files
import {Tabs, TabList, Tab, TabPanel, type Key} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import Home from '@react-spectrum/s2/illustrations/gradient/generic2/Home';
import Folder from '@react-spectrum/s2/illustrations/gradient/generic2/FolderOpen';
import Search from '@react-spectrum/s2/illustrations/gradient/generic2/Search';
import Settings from '@react-spectrum/s2/illustrations/gradient/generic1/GearSetting';
import {useState} from 'react';
function Example() {
let [tab, setTab] = useState<Key>("files");
return (
<div>
<Tabs
aria-label="Tabs"
selectedKey={tab}
onSelectionChange={setTab}
>
<TabList aria-label="Tabs">
<Tab id="home">Home</Tab>
<Tab id="files">Files</Tab>
<Tab id="search" isDisabled>Search</Tab>
<Tab id="settings">Settings</Tab>
</TabList>
<TabPanel id="home">
<div className={style({size: 'full', display: 'flex', alignItems: 'center', justifyContent: 'center'})}>
<Home />
</div>
</TabPanel>
<TabPanel id="files">
<div className={style({size: 'full', display: 'flex', alignItems: 'center', justifyContent: 'center'})}>
<Folder />
</div>
</TabPanel>
<TabPanel id="search">
<div className={style({size: 'full', display: 'flex', alignItems: 'center', justifyContent: 'center'})}>
<Search />
</div>
</TabPanel>
<TabPanel id="settings">
<div className={style({size: 'full', display: 'flex', alignItems: 'center', justifyContent: 'center'})}>
<Settings />
</div>
</TabPanel>
</Tabs>
<p>Selected tab: {tab}</p>
</div>
);
}
API
<Tabs>
<TabList>
<Tab />
</TabList>
<TabPanel />
</Tabs>
Tabs
Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.
Name | Type | Default |
---|---|---|
styles | StylesPropWithHeight | Default: — |
Spectrum-defined styles, returned by the style() macro. | ||
children | ReactNode | Default: — |
The content to display in the tabs. | ||
density | 'compact' | 'regular' | Default: 'regular'
|
The amount of space between the tabs. | ||
labelBehavior | 'show' | 'hide' | Default: 'show'
|
Defines if the text within the tabs should be hidden and only the icon should be shown. The text is always visible when the item is collapsed into a picker. | ||
isDisabled | boolean | Default: — |
Whether the TabList is disabled. Shows that a selection exists, but is not available in that circumstance. | ||
keyboardActivation | 'automatic' | 'manual' | Default: 'automatic'
|
Whether tabs are activated automatically on focus or manually. | ||
orientation | Orientation | Default: 'horizontal'
|
The orientation of the tabs. | ||
selectedKey | Key | null | Default: — |
The currently selected key in the collection (controlled). | ||
defaultSelectedKey | Key | Default: — |
The initial selected key in the collection (uncontrolled). | ||
onSelectionChange |
| Default: — |
Handler that is called when the selection changes. | ||
disabledKeys | Iterable | Default: — |
The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. | ||
TabList
Name | Type | |
---|---|---|
styles | StylesProp | |
Spectrum-defined styles, returned by the style() macro. | ||
children | ReactNode | | |
The content to display in the tablist. | ||
items | Iterable | |
Item objects in the collection. | ||
dependencies | ReadonlyArray | |
Values that should invalidate the item cache when using dynamic collections. | ||
Tab
Name | Type | |
---|---|---|
children | ReactNode | |
The content to display in the tab. | ||
id | Key | |
The unique id of the tab. | ||
isDisabled | boolean | |
Whether the tab is disabled. | ||
styles | StylesProp | |
Spectrum-defined styles, returned by the style() macro. | ||
TabPanel
Name | Type | Default |
---|---|---|
styles | StylesPropWithHeight | Default: — |
Spectrum-defined styles, returned by the style() macro. | ||
children | ReactNode | Default: — |
The content to display in the tab panels. | ||
shouldForceMount | boolean | Default: false
|
Whether to mount the tab panel in the DOM even when it is not currently selected. Inactive tab panels are inert and cannot be interacted with. They must be styled appropriately so this is clear to the user visually. | ||
id | Key | Default: — |
The unique id of the tab. | ||