Tabs
Tabs organize content into multiple sections and allow users to navigate between them.
Home
Files
Search
Settings
orientation
keyboardActivation
isDisabled
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.
Tab 1
Tab 2
Tab 3
Tab body 1
import {Tabs, TabList, Tab, TabPanel} from './Tabs';
import {Button} from './Button';
import {Collection} from 'react-aria-components';
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 style={{width: '100%'}}>
<div style={{display: 'flex'}}>
<TabList
aria-label="Dynamic tabs"
items={tabs}
style={{flex: 1}}>
{item => <Tab>{item.title}</Tab>}
</TabList>
<div className="button-group">
<Button onPress={addTab}>Add tab</Button>
<Button onPress={removeTab}>Remove tab</Button>
</div>
</div>
<Collection items={tabs}>
{item => <TabPanel>{item.content}</TabPanel>}
</Collection>
</Tabs>
);
}
Links
Use the href
prop on a <Tab>
to create a link. See the client side routing guide to learn how to integrate with your framework. This example uses a simple hash-based router to sync the selected tab to the URL.
import {Tabs, TabList, Tab, TabPanel} from './Tabs';
import {useSyncExternalStore} from 'react';
export default function Example() {
let hash = useSyncExternalStore(subscribe, getHash, getHashServer);
return (
<Tabs selectedKey={hash}>
<TabList aria-label="Tabs">
<Tab id="#/" href="#/">Home</Tab>
<Tab id="#/shared" href="#/shared">Shared</Tab>
<Tab id="#/deleted" href="#/deleted">Deleted</Tab>
</TabList>
<TabPanel id="#/">Home</TabPanel>
<TabPanel id="#/shared">Shared</TabPanel>
<TabPanel id="#/deleted">Deleted</TabPanel>
</Tabs>
);
}
function getHash() {
return location.hash.startsWith('#/') ? location.hash : '#/';
}
function getHashServer() {
return '#/';
}
function subscribe(fn) {
addEventListener('hashchange', fn);
return () => removeEventListener('hashchange', fn);
}
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.
Home
Files
Search
Settings
Selected tab: files
import type {Key} from 'react-aria-components';
import {Tabs, TabList, Tab, TabPanel} from './Tabs';
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
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" style={{display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
<Home />
</TabPanel>
<TabPanel id="files" style={{display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
<Folder />
</TabPanel>
<TabPanel id="search" style={{display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
<Search />
</TabPanel>
<TabPanel id="settings" style={{display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
<Settings />
</TabPanel>
</Tabs>
<p>Selected tab: {tab}</p>
</div>
);
}