Tabs
The Tabs component organizes related content into separate views that can be switched between without leaving the current page.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="home" tabId="basic">
<Tabs class="mb-2">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<TabPanel value="home" tabIndex={0}>
Welcome to the home page.
</TabPanel>
<TabPanel value="profile" tabIndex={0}>
View and manage your profile.
</TabPanel>
<TabPanel value="settings" tabIndex={0}>
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}Usage
Wrap the Tabs and TabPanel components in a TabsContext. Each Tab
must have a unique value, and its corresponding TabPanel must use
the same value.
<TabsContext defaultValue="home">
<Tabs>
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<TabPanel value="home">
Home content
</TabPanel>
<TabPanel value="profile">
Profile content
</TabPanel>
<TabPanel value="settings">
Settings content
</TabPanel>
</TabsContext>When a tab is selected, the TabPanel with the matching value is
displayed.
Examples
Controlled
Use the value prop on TabsContext to control the active tab. Use
onChange to respond when the user selects a different tab.
import { createSignal } from "solid-js";
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
const [activeTab, setActiveTab] = createSignal("home");
return (
<div class="max-w-5xl w-full">
<TabsContext
value={activeTab()}
onChange={(_event, tab) => setActiveTab(tab)}
tabId="controlled"
>
<Tabs class="mb-2">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<TabPanel value="home">
Welcome to the home page.
</TabPanel>
<TabPanel value="profile">
View and manage your profile.
</TabPanel>
<TabPanel value="settings">
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}Default Value
Use defaultValue to specify the tab that should be active initially
without controlling the active tab.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="profile" tabId="default-value">
<Tabs class="mb-2">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<TabPanel value="home">
Welcome to the home page.
</TabPanel>
<TabPanel value="profile">
This tab is selected by default.
</TabPanel>
<TabPanel value="settings">
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}Orientation
Use the orientation prop to arrange tabs horizontally or vertically.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full grid grid-cols-[100px_1fr] gap-4">
<TabsContext defaultValue="home" tabId="orientation">
<Tabs orientation="vertical">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<div>
<TabPanel value="home">
Welcome to the home page.
</TabPanel>
<TabPanel value="profile">
View and manage your profile.
</TabPanel>
<TabPanel value="settings">
Manage your account settings.
</TabPanel>
</div>
</TabsContext>
</div>
);
}Centered
Use the centered prop to center the tabs within the available space.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="home" tabId="centered">
<Tabs centered class="mb-3">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<TabPanel value="home">
Welcome to the home page.
</TabPanel>
<TabPanel value="profile">
View and manage your profile.
</TabPanel>
<TabPanel value="settings">
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}Icons
Use the icon prop to display an icon alongside a tab label.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="home" tabId="icons">
<Tabs class="mb-2">
<Tab
icon={<HomeIcon />}
iconPosition="top"
label="Home"
value="home"
/>
<Tab
icon={<ProfileIcon />}
iconPosition="start"
label="Profile"
value="profile"
/>
<Tab
icon={<SettingsIcon />}
iconPosition="end"
label="Settings"
value="settings"
/>
</Tabs>
<TabPanel value="home">
Welcome to the home page.
</TabPanel>
<TabPanel value="profile">
View and manage your profile.
</TabPanel>
<TabPanel value="settings">
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}
function HomeIcon() {
return (
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden={true}
>
<path d="m3 10 9-7 9 7" />
<path d="M5 9v11h14V9" />
<path d="M9 20v-6h6v6" />
</svg>
);
}
function ProfileIcon() {
return (
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden={true}
>
<circle cx="12" cy="8" r="4" />
<path d="M4 21a8 8 0 0 1 16 0" />
</svg>
);
}
function SettingsIcon() {
return (
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden={true}
>
<path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z" />
<path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1-1.7 1.7-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.6v.1h-2.4v-.1a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L8 17l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.6-1H6.7v-2.4h.1a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L8 8.6l1.7-1.7.1.1a1.7 1.7 0 0 0 1.9.3 1.7 1.7 0 0 0 1-1.6v-.1h2.4v.1a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1 1.7 1.7-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1h.1V14h-.1a1.7 1.7 0 0 0-1.6 1Z" />
</svg>
);
}Icon Position
Use the iconPosition prop to control where an icon appears relative to
the tab label.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="top" tabId="icon-position">
<Tabs class="mb-2">
<Tab
icon={<Icon />}
iconPosition="top"
label="Top"
value="top"
/>
<Tab
icon={<Icon />}
iconPosition="bottom"
label="Bottom"
value="bottom"
/>
<Tab
icon={<Icon />}
iconPosition="start"
label="Start"
value="start"
/>
<Tab
icon={<Icon />}
iconPosition="end"
label="End"
value="end"
/>
</Tabs>
<TabPanel value="top">
Icon positioned above the label.
</TabPanel>
<TabPanel value="bottom">
Icon positioned below the label.
</TabPanel>
<TabPanel value="start">
Icon positioned to the start of the label.
</TabPanel>
<TabPanel value="end">
Icon positioned to the end of the label.
</TabPanel>
</TabsContext>
</div>
);
}
function Icon() {
return (
<span aria-hidden="true">●</span>
);
}Disabled
Use the disabled prop to prevent users from selecting a tab.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="home" tabId="disabled-example">
<Tabs class="mb-2">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" disabled />
</Tabs>
<TabPanel value="home" tabIndex={0}>
Welcome to the home page.
</TabPanel>
<TabPanel value="profile" tabIndex={0}>
View and manage your profile.
</TabPanel>
<TabPanel value="settings" tabIndex={0}>
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}Tab ID
Use the tabId prop to automatically associate each tab with its corresponding tab panel.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
export default function Example() {
return (
<div class="max-w-5xl w-full">
<TabsContext defaultValue="home" tabId="basic">
<Tabs class="mb-2">
<Tab label="Home" value="home" />
<Tab label="Profile" value="profile" />
<Tab label="Settings" value="settings" />
</Tabs>
<TabPanel value="home" tabIndex={0}>
Welcome to the home page.
</TabPanel>
<TabPanel value="profile" tabIndex={0}>
View and manage your profile.
</TabPanel>
<TabPanel value="settings" tabIndex={0}>
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}The tabId prop generates the accessibility attributes needed to link each role="tab" with its corresponding role="tabpanel", including id, aria-controls, and aria-labelledby.
Provide a unique tabId for each TabsContext instance when using multiple tab groups on the same page.
If you do not provide tabId, you can set these accessibility attributes manually. Give each tab and tab panel a unique id, then use aria-controls on the tab and aria-labelledby on the corresponding tab panel.
<Tab
label="Home"
value="home"
id="home-tab"
aria-controls="home-panel"
/>
<TabPanel
value="home"
tabIndex={0}
id="home-panel"
aria-labelledby="home-tab"
>
Welcome to the home page.
</TabPanel>Custom Styling
Use the class prop to customize the appearance of TabsContext, Tabs,
Tab, and TabPanel components. Use slotProps on Tab when you need
to customize individual tab slots.
import Tab from "rocksolidjs/Tab";
import TabsContext from "rocksolidjs/TabsContext";
import TabPanel from "rocksolidjs/TabPanel";
import Tabs from "rocksolidjs/Tabs";
import { createSignal } from "solid-js";
export default function Example() {
const [activeTab, setActiveTab] = createSignal("home");
const getClass = (tab: string) => (`
shadow-none
${activeTab() === tab ? `
text-white
bg-blue-500 dark:bg-blue-500
hover:bg-blue-600 hover:dark:bg-blue-400
active:bg-blue-600/80 active:dark:bg-blue-400/80
` : ""}
`);
return (
<div class="w-full">
<TabsContext
value={activeTab()}
onChange={(_event, tab) => setActiveTab(tab)}
tabId="custom-styled"
>
<Tabs
class="border-none grid grid-cols-3 bg-neutral-100 dark:bg-neutral-800"
>
<Tab
class={getClass("home")}
label="Home"
value="home"
/>
<Tab
class={getClass("profile")}
label="Profile"
value="profile"
/>
<Tab
class={getClass("settings")}
label="Settings"
value="settings"
/>
</Tabs>
<TabPanel class="p-4" value="home">
Welcome to the home page.
</TabPanel>
<TabPanel class="p-4" value="profile">
View and manage your profile.
</TabPanel>
<TabPanel class="p-4" value="settings">
Manage your account settings.
</TabPanel>
</TabsContext>
</div>
);
}Accessibility
- Associate each
Tabwith its correspondingTabPanelso assistive technologies can understand the relationship between the tab and its content. - Ensure every
Tabhas a correspondingTabPanelwith a matchingvalue. - Keep tab labels concise and meaningful.
- Use the
orientationprop to reflect the visual arrangement of the tabs. - Use the
disabledprop when a tab is temporarily unavailable, rather than relying only on visual styling to communicate its state. - Do not rely on icons alone to communicate the purpose of a tab when a text label can provide clearer context.
- Ensure tab and panel content remains accessible when switching between tabs.
API
TabsContext
TabsContext manages the active tab and provides the selected value to
its child Tabs and TabPanel components.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| children | JSXElement |
No | — | The Tabs and TabPanel components rendered within the context. |
| defaultValue | string |
No | — | Sets the initially active tab when the component is uncontrolled. |
| onChange | (event: Event, activeTab: string) => void |
No | — | Called when the active tab changes. Receives the event and the newly active tab value. |
| value | string |
No | — | Controls the currently active tab. When provided, the active tab is controlled by the parent. |
| tabId | string |
No | — | A unique identifier used to associate tabs with their corresponding tab panels through accessibility attributes such as id, aria-controls, and aria-labelledby. |
Tabs
Tabs renders the tab navigation and supports horizontal or vertical
layouts, centered positioning, and custom styling.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| centered | boolean |
No | false |
Centers the tabs within the available space. |
| class | string |
No | — | Adds custom CSS classes to the tabs container. |
| orientation | "horizontal" | "vertical" |
No | "horizontal" |
Controls the direction in which the tabs are displayed. |
Tab
Tab represents an individual selectable tab. Use value to associate
the tab with a TabPanel. Tabs can optionally display a label and icon.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| class | string |
No | — | Adds custom CSS classes to the tab. |
| icon | JSXElement |
No | — | Displays an icon within the tab. |
| iconPosition | "top" | "bottom" | "start" | "end" |
No | "top" |
Controls the position of the icon relative to the tab label. |
| label | string |
No | — | The text displayed as the tab label. |
| value | string |
Yes | — | Identifies the tab and associates it with a TabPanel that has the same value. |
| slotProps | { icon?: object } |
No | — | Provides additional props for customizing individual tab slots.
|
TabPanel
TabPanel contains the content associated with a specific tab. Its
value must match the value of the corresponding Tab.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| class | string |
No | — | Adds custom CSS classes to the tab panel. |
| value | string |
Yes | — | Identifies the panel and associates it with a Tab that has the same value. |
| children | JSXElement |
No | — | The content to display inside the tab panel. |