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.
Import#
Tabs#
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!
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.
Tab variants and color#
Tabs come in 6 different variants to style the tabs: line
,enclosed
,
enclosed-colored
, soft-rounded
, solid-rounded
one!
two!
Manually Activated Tabs#
By default, Tabs
are activated automatically. This means when you use the
arrow keys to change tabs, the tab is activated and focused.
The content of a TabPanel
should ideally be preloaded. However, if switching
to a tab panel causes a network request and possibly a page refresh, there might
be some notable latency and this might affect the experience for keyboard and
screen reader users.
In this scenario, you should use a manually activated tab, it moves focus without activating the tabs. With focus on a specifc tab, users can activate a tab by pressing Space or Enter.
one!
two!
Tab sizes#
You can change the size of the tab by passing size
prop. We support 3 sizes
sm
, md
, lg
one!
two!
Tab alignment#
You can change the alignment of the TabList
by passing align
prop. We
support 3 sizes start
, center
, end
.
one!
two!
Fitted Tabs#
Stretch the tab list to fit the container by passing isFitted
prop.
one!
two!
Tabs onChange#
Calls back with the tab index whenever the user changes tabs, allowing your app to synchronize with it.
Tabs defaultIndex#
Starts the tabs at a specific index.
Tabs Index#
Like form inputs, a tab's state can be controlled. 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.
Tab isSelected#
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.
Tab isDisabled#
When a Tab
is disabled, it's skipped from the keyboard navigations and not
clickable.
DataTabs#
If you'd like to drive your tabs with an array instead of using the granular components, you can create your own DataTabs component.
Accessibility#
Keyboard#
Key | Action |
---|---|
ArrowLeft | Moves focus to the next tab |
ArrowUp | Moves focus to the previous tab |
Tab | When focus moves into the tab list, places focus on the active tab element |
Space or Enter | Activates the tab if it was not activated automatically on focus |
Home | Moves focus to the first tab |
End | Moves focus to the last tab |
ARIA roles#
Component | Aria | Usage |
---|---|---|
Tab | role="tab" | Indicates that it's a tab |
aria-selected | Set to true a tab is selected and all other Tabs have it set to false . | |
aria-controls | Set to the id of its associated TabPanel | |
TabList | id | The id of the TabPanel that's referencd by its associated Tab |
aria-orientation | Set to vertical or horizontal based on the value of the orientation prop. | |
role="tablist" | Indicates that it's a tablist | |
aria-labelledby | Set to the id of the Tab that labels the TabPanel . |