Tabs

Used to display content in a tabbed interface

Manage your team members

Usage

import { Tabs } from "chakra-ui-solid";
<Tabs.Root>
  <Tabs.List>
    <Tabs.Trigger />
    <Tabs.Indicator />
  </Tabs.List>
  <Tabs.Content />
</Tabs.Root>

Examples

Variants

Use the variant prop to change the visual style of the tabs.

Manage your team members
Manage your team members
Manage your team members
Manage your team members
Manage your team members

Lazy Mounted

Use the lazyMount and/or unmountOnExit prop to only render the tab content when it is active. This can be useful for performance optimization.

Tab 1: Content 0

Indicator

Render the Tabs.Indicator component to display a visual indicator of the active tab.

Manage your team members

Custom Indicator

Customize the indicator appearance using CSS variables like --tabs-indicator-bg and --tabs-indicator-shadow.

Manage your team members

Pass the render prop to the Tabs.Trigger component to render a link as a tab. When a tab is clicked, the link will be navigated to.

Manage your team members

When using custom router links, you need to set the navigate prop on the Tabs.Root component.

import { useNavigate } from "@solidjs/router";
import { Tabs } from "chakra-ui-solid";
 
function Demo() {
  const navigate = useNavigate();
 
  return (
    <Tabs.Root navigate={(details) => navigate(`/${details.value}`)}>{/* ... */}</Tabs.Root>
  );
}

Fitted

Use the fitted prop to make the tabs fit the width of the container.

Controlled

Use the value and onValueChange prop to control the active tab.

First panel

Store

An alternative way to control the tabs is to use the RootProvider component and the createTabs store hook.

This way you can access the tabs state and methods from outside the tabs.

selected: members
Manage your team members

Disabled Tab

Set the disabled prop on the Tabs.Trigger component to disable a tab.

Manual activation

By default, the tabs are selected when the arrow keys are pressed. Disable this behavior by setting the activationMode prop to manual.

In this mode, the tabs will only be selected when clicked or the enter key is pressed.

Dynamic

Here’s an example of how to dynamically add and remove tabs.

Tab Content 1

Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit.

Animation

Use the _open and _closed conditional props to animate the tabs.

Dolore ex esse laboris elit magna esse sunt

Guide

Styling active tab

Use the _selected condition to style the active tab’s text and background.

<Tabs.Trigger
  _selected={{
    bg: "blue.500",
    color: "white",
  }}
>
  Tab
</Tabs.Trigger>

Props

Root

TabsRootProps
PropDefaultType
activationMode'automatic'
'manual' | 'automatic'

Whether an arrow key selects the tab it moves to, or only focuses it.

compositetrue
boolean

Whether the tabs form a composite widget — one tab stop for the whole list, and a focusable panel. Turning it off takes the triggers and the panels out of the tab order, for tabs nested inside another widget that owns the focus.

defaultValue—
string | null

The tab a fresh, uncontrolled set of tabs starts on.

deselectable—
boolean

Whether clicking the selected trigger clears the selection instead of doing nothing.

fitted—
ConditionalValue<boolean>

Whether the triggers stretch to fill the list.

id—
string

Seeds every id the machine hands out — the root is `tabs:{id}`, a trigger `tabs:{id}:trigger-{value}`, a panel `tabs:{id}:content-{value}`. Defaults to a generated id, and **does not become the root element's own `id`**: pass `ids` to control the attributes themselves.

ids—
TabsElementIds

Override individual element ids, for pointing an ARIA relationship at a specific one.

justify—
ConditionalValue<'start' | 'center' | 'end' | PresetVariant<'tabs', 'justify'>>

Where the triggers sit along the list when they do not fill it.

loopFocustrue
boolean

Whether arrow-key focus wraps from the last trigger back to the first.

navigate—
((details: TabsNavigateDetails) => void) | null

What to do when a selected trigger is an anchor — by default the machine clicks the link. Pass `null` to select the tab and navigate nowhere.

onFocusChange—
(details: TabsFocusChangeDetails) => void

Called whenever the focused tab changes, which under `manual` is not the selected one.

onValueChange—
(details: TabsValueChangeDetails) => void

Called whenever the selected tab changes, from either side.

orientation'horizontal'
'horizontal' | 'vertical'

Which arrow keys move between triggers. `horizontal` uses ←/→, `vertical` uses ↑/↓.

size'md'
ConditionalValue<'sm' | 'md' | 'lg' | PresetVariant<'tabs', 'size'>>

How much padding and type size the triggers carry.

translations—
TabsIntlTranslations

The `aria-label` the tablist carries.

value—
string | null

The controlled selected value. Pass `undefined` for uncontrolled.

variant'line'
ConditionalValue<'line' | 'subtle' | 'enclosed' | 'outline' | 'plain' | PresetVariant<'tabs', 'variant'>>

Which visual treatment marks the selected tab.

Plus everything in RenderStrategyProps, Omit<HTMLChakraProps<"div">, "id"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

Trigger

TabsTriggerProps
PropDefaultType
disabled—
boolean

Whether this tab can be selected or focused at all.

value*—
string

Which tab this trigger selects — it pairs the trigger with the `Tabs.Content` of the same value, and both ARIA relationships are built from it.

Plus Omit<HTMLChakraProps<"button">, "value" | "disabled"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

Content

TabsContentProps
PropDefaultType
value*—
string

Which tab shows this panel — it must match a `Tabs.Trigger`'s `value`.

Plus HTMLChakraProps<"div"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.