@reach/tabs
Tabs - TabList - Tab - TabPanels - TabPanel
- Source: https://github.com/reach/reach-ui/tree/master/packages/tabs
- WAI ARIA: https://www.w3.org/TR/wai-aria-practices-1.1/#tabs
An accessible tabs component.
The Tab
and TabPanel
elements are associated by their order in the tree. None of the components are empty wrappers, each is associated with a real DOM element in the document, giving you maximum control over styling and composition.
You can render any other elements you want inside of Tabs
, but TabList
should only render Tab
elements, and TabPanels
should only render TabPanel
elements.
one!
two!
three!
Check out the demos for ideas on how to style and compose.
Installation
npm install @reach/tabs
# or
yarn add @reach/tabs
And then import the components:
import { Tabs, TabList, Tab, TabPanels, TabPanel } from "@reach/tabs";
Tabs
The parent component of the tab interface.
Tabs CSS Selectors
Please see the styling guide.
[data-reach-tabs] { }
Tabs Props
Prop | Type | Required |
---|---|---|
children | node | true |
onChange | function | false |
defaultIndex | number | false |
index | number | false |
as | ComponentType | false |
rest | HTMLDivProps | false |
Tabs children
Type: node
Tabs expects <TabList>
and <TabPanels>
as children. The order doesn't matter, you can have tabs on the top or the bottom. In fact, you could have tabs on both the bottom and the top at the same time. You can have random elements inside as well.
Tabs onChange
Type: function
Calls back with the tab index whenever the user changes tabs, allowing your app to synchronize with it.
Tabs defaultIndex
Type: number
Starts the tabs at a specific index.
Tabs index
Type: number
Like form inputs, a tab's state can be controlled by the owner. Make sure to include an onChange
as well, or else the tabs will not be interactive.
Click the tabs or pull the slider around
Yeah yeah. What's up?
Oh, hello there.
Tabs as
Type: ComponentType
Tabs will render a div
unless you specify a different element.
Tabs rest
Type: rest
All other props are passed to the underlying div
(or component passed to as
).
TabList
The parent component of the tabs.
<TabList>
<Tab>Tacos</Tab>
<Tab>Tortas</Tab>
</TabList>
TabList CSS Selectors
Please see the styling guide.
[data-reach-tab-list] { }
TabList Props
Prop | Type | Required |
---|---|---|
children | node | false |
as | ComponentType | false |
rest | ForwardedProps | false |
TabList children
TabList
expects multiple Tab
elements as children.
<TabList>
<Tab>One</Tab>
<Tab>Two</Tab>
</TabList>
But, you can also wrap Tab
as long as you forward the props (because data is passed from TabList
to Tab
via cloneElement
).
const RedTab = props => <Tab {...props} style={{ color: "red" }} />;
const TabPage = () => (
<Tabs>
<TabList>
<RedTab>This is red</RedTab>
<Tab>This is normal</Tab>
</TabList>
<TabPanels>
<TabPanel>...</TabPanel>
<TabPanel>...</TabPanel>
</TabPanels>
</Tabs>
);
TabList as
Type: ComponentType
Tabs will render a div
unless you specify a different element.
<TabList as={View} />
TabList rest
Type: rest
All other props are passed to the underlying div
(or component passed to as
).
TabPanels
The parent component of the panels.
<TabPanels>
<TabPanel>My favorite</TabPanel>
<TabPanel>My other favorite</TabPanel>
</TabPanels>
TabPanels CSS Selectors
Please see the styling guide.
[data-reach-tab-panels] { }
TabPanels Props
Prop | Type | Required |
---|---|---|
children | node | false |
as | ComponentType | false |
rest | HTMLDivProps | false |
TabPanels children
TabPanels
expects multiple TabPanel
elements as children.
<TabPanels>
<TabPanel>One</TabPanel>
<TabPanel>Two</TabPanel>
</TabPanels>
But, you can also wrap TabPanel
as long as you forward the props (because data is passed from TabPanels
to TabPanel
via cloneElement
).
const BoldPanel = props => <Tab {...props} style={{ fontWeight: "bold" }} />;
const TabPage = () => (
<Tabs>
<TabList>
<Tab>...</Tab>
<Tab>...</Tab>
</TabList>
<TabPanels>
<BoldPanel>...</BoldPanel>
<TabPanel>...</TabPanel>
</TabPanels>
</Tabs>
);
TabPanels as
Type: ComponentType
Tabs will render a div
unless you specify a different element.
<TabPanels as={View} />
TabPanels rest
Type: rest
All other props are passed to the underlying div
(or component passed to as
).
Tab
The interactive element that changes the selected panel.
<Tab>Coconut Korma</Tab>
Tab CSS Selectors
Please see the styling guide.
/* styles all tabs */
[data-reach-tab] { }
/* styles only the selected tab */
[data-reach-tab][data-selected] { }
Tab Props
Prop | Type | Required |
---|---|---|
children | node | false |
disabled | boolean | false |
as | ComponentType | false |
rest | rest | false |
Tab Clone Props
Prop | Type | Required |
---|---|---|
isSelected | boolean | false |
Tab children
Tab
can receive any type of children.
<Tab>
<HouseIcon /> Home
</Tab>
Tab disabled
Disables a tab when true. Clicking will not work and keyboard navigation will skip over it.
<Tab disabled />
Tab as
Type: ComponentType
Tab will render a button
unless you specify a different element.
<Tab as={ReactNativeWebButton} />
Tab rest
Type: rest
All other props are passed to the underlying button
(or component passed to as
).
Tab isSelected
Type: number
- cloned
Because TabList needs to know the order of the children, we use cloneElement
to pass state internally. If you want to know if a tab is active, you can wrap it, and then inspect clone props passed in. Note that any props that start with _
are not public API, so don't use them :)
TabPanel
The panel that displays when it's corresponding tab is active.
<TabPanel>
<h2>The Best Food</h2>
<p>The best food is either Mexican or Indian.</p>
</TabPanel>
TabPanel CSS Selectors
Please see the styling guide.
/* styles all tabs */
[data-reach-tab-panel] { }
TabPanel Props
Prop | Type | Required |
---|---|---|
children | node | false |
as | ComponentType | false |
rest | rest | false |
TabPanel children
TabPanel
can receive any type of children.
<TabPanel>
<h2>Whatever you want</h2>
<p>In here</p>
</TabPanel>
TabPanel as
Type: ComponentType
TabPanel will render a div
unless you specify a different element.
<Tab as={View} />
TabPanel rest
Type: rest
All other props are passed to the underlying div
(or component passed to as
).
Demos
These demos show off how you can add quite a bit of behavior to your Tabs interfaces.
DataTabs
If you'd like to drive your tabs with data you can create a DataTabs
component.
Animation
With a little composition we can animate the selected tab bar.
Check it out! It's ~animated~
Yeah yeah. What's up?
Oh, hello there.