Tabs
Switches between related panels on the same page
import { Tabs } from "@nyte-ai/ui/tabs";One list of tabs, one panel visible at a time. Reach for it when the panels are peers and the reader only needs one of them at a time. No Nyte styling here.
Usage
- Each
Tabs.Taband eachTabs.Panelneeds a matchingvalue. WithoutdefaultValueon the root, the first tab starts active. - Tabs activate on Enter or Space.
activateOnFocuson the list activates them on arrow key focus instead. valuewithonValueChangecontrols the root.value={null}leaves no tab active.Tabs.Indicatoris optional. Position it from the--active-tab-*CSS variables it publishes.- A panel carries
data-starting-styleanddata-ending-stylewhile it animates.data-activation-directionsays where the newly active tab sits relative to the previous one, so a panel can slide in from the matching side. - A hidden panel unmounts unless you pass
keepMounted.
Anatomy
<Tabs.Root>
<Tabs.List>
<Tabs.Tab />
<Tabs.Indicator />
</Tabs.List>
<Tabs.Panel />
</Tabs.Root>Examples
Basic
<Tabs.Root defaultValue="overview">
<Tabs.List>
<Tabs.Tab value="overview">Overview</Tabs.Tab>
<Tabs.Tab value="activity">Activity</Tabs.Tab>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Panel value="overview">Three heads, two of them running.</Tabs.Panel>
<Tabs.Panel value="activity">Last run finished 2 minutes ago.</Tabs.Panel>
</Tabs.Root>Links
To render a tab as an anchor, pass the element to render and set nativeButton={false}.
<Tabs.Root>
<Tabs.List>
<Tabs.Tab nativeButton={false} render={<a href="/overview" />} value="overview">
Overview
</Tabs.Tab>
</Tabs.List>
</Tabs.Root>Props
The reference tables below come from Base UI, MIT, © Material-UI SAS.
Root
Groups the tabs and the corresponding panels.
Renders a <div> element.
Root Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | Tabs.Tab.Value | 0 | The default value. Use when the component is not controlled.
When the value is null, no Tab will be active. |
| value | Tabs.Tab.Value | - | The value of the currently active Tab. Use when the component is controlled.
When the value is null, no Tab will be active. |
| onValueChange | ((value: Tabs.Tab.Value, eventDetails: Tabs.Root.ChangeEventDetails) => void) | - | Callback invoked when new value is being set. The event reason is 'none' for user-initiated changes, such as a click
or keyboard navigation; 'initial' for the first automatic selection or
fallback in uncontrolled roots when defaultValue is omitted or
undefined, including when the implicit initial value is disabled or
missing; 'disabled' for automatic fallback when the selected tab becomes
disabled in uncontrolled roots; or 'missing' for automatic fallback when
the selected tab is removed, or when an explicit defaultValue never
matches a mounted tab in uncontrolled roots. For automatic changes, the selected value can be null when no enabled Tab
is available as a fallback. Automatic changes cannot be canceled; calling eventDetails.cancel() for
'initial', 'disabled', or 'missing' has no effect. |
| orientation | Tabs.Root.Orientation | 'horizontal' | The component orientation (layout flow direction). |
| className | string | ((state: Tabs.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Tabs.Root.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Tabs.Root.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Root Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the tabs. |
| data-activation-direction | 'left' | 'right' | 'up' | 'down' | 'none' | Indicates the direction of the activation (based on the previous active tab). |
List
Groups the individual tab buttons.
Renders a <div> element.
List Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| activateOnFocus | boolean | false | Whether to automatically change the active tab on arrow key focus. Otherwise, tabs will be activated using Enter or Space key press. |
| loopFocus | boolean | true | Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys. |
| className | string | ((state: Tabs.List.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Tabs.List.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Tabs.List.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
List Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the tabs. |
| data-activation-direction | 'left' | 'right' | 'up' | 'down' | 'none' | Indicates the direction of the activation (based on the previous active tab). |
Tab
An individual interactive tab button that toggles the corresponding panel.
Renders a <button> element.
Tab Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | Tabs.Tab.Value | - | The value of the Tab. |
| nativeButton | boolean | true | Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (for example, <div>). |
| disabled | boolean | - | Whether the Tab is disabled. If a first Tab on a <Tabs.List> is disabled, it won't initially be selected.
Instead, the next enabled Tab will be selected.
However, it does not work like this during server-side rendering, as it is not known
during pre-rendering which Tabs are disabled.
To work around it, ensure that defaultValue or value on <Tabs.Root> is set to an enabled Tab's value. |
| className | string | ((state: Tabs.Tab.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Tabs.Tab.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Tabs.Tab.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Tab Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the tabs. |
| data-disabled | - | Present when the tab is disabled. |
| data-activation-direction | 'left' | 'right' | 'up' | 'down' | 'none' | Indicates the direction of the activation (based on the previous active tab). |
| data-active | - | Present when the tab is active. |
Indicator
A visual indicator that can be styled to match the position of the currently active tab.
Renders a <span> element.
Indicator Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| renderBeforeHydration | boolean | false | Whether to render itself before React hydrates. This minimizes the time that the indicator isn't visible after server-side rendering. |
| className | string | ((state: Tabs.Indicator.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Tabs.Indicator.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Tabs.Indicator.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Indicator Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the tabs. |
| data-activation-direction | 'left' | 'right' | 'up' | 'down' | 'none' | Indicates the direction of the activation (based on the previous active tab). |
Indicator CSS Variables:
| Variable | Type | Description |
|---|---|---|
--active-tab-bottom | number | Indicates the distance on the bottom side from the parent's container if the tab is active. |
--active-tab-height | number | Indicates the height of the tab if it is active. |
--active-tab-left | number | Indicates the distance on the left side from the parent's container if the tab is active. |
--active-tab-right | number | Indicates the distance on the right side from the parent's container if the tab is active. |
--active-tab-top | number | Indicates the distance on the top side from the parent's container if the tab is active. |
--active-tab-width | number | Indicates the width of the tab if it is active. |
Panel
A panel displayed when the corresponding tab is active.
Renders a <div> element.
Panel Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | Tabs.Tab.Value | - | The value of the TabPanel. It will be shown when the Tab with the corresponding value is active. |
| className | string | ((state: Tabs.Panel.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Tabs.Panel.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| keepMounted | boolean | false | Whether to keep the HTML element in the DOM while the panel is hidden. |
| render | ReactElement | ((props: HTMLProps, state: Tabs.Panel.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Panel Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the tabs. |
| data-activation-direction | 'left' | 'right' | 'up' | 'down' | 'none' | Indicates the direction of the activation (based on the previous active tab). |
| data-hidden | - | Present when the panel is hidden. |
| data-index | - | Indicates the index of the tab panel. |
| data-starting-style | - | Present when the panel begins animating in. |
| data-ending-style | - | Present when the panel is animating out. |
Accessibility
- The parts render
role="tablist",role="tab", androle="tabpanel". The indicator rendersrole="presentation". - Label
Tabs.Listwitharia-labeloraria-labelledby. - Arrow keys move focus along the list. Focus wraps at the end unless you pass
loopFocus={false}. - Enter and Space activate the focused tab, unless
activateOnFocusactivates it on focus. - A disabled first tab is skipped and the next enabled tab is selected. Server rendering does not
know which tabs are disabled, so set
defaultValueorvalueto an enabled tab. - The focus ring is yours to draw. See Focus.