import { Tabs } from "@chakra-ui/react"
import { LuCheckSquare, LuFolder, LuUser } from "react-icons/lu"
const Demo = () => {
return (
<Tabs.Root defaultValue="members">
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuCheckSquare />
Settings
</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="members">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="tasks">
Manage your tasks for freelancers
</Tabs.Content>
</Tabs.Root>
)
}
Usage
import { Tabs } from "@chakra-ui/react"
<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.
import { For, SimpleGrid, Tabs } from "@chakra-ui/react"
import { LuCheckSquare, LuFolder, LuUser } from "react-icons/lu"
const Demo = () => {
return (
<SimpleGrid columns={2} gap="14" width="full">
<For each={["line", "subtle", "enclosed", "outline", "plain"]}>
{(variant) => (
<Tabs.Root key={variant} defaultValue="members" variant={variant}>
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuCheckSquare />
Settings
</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="members">
Manage your team members
</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="tasks">
Manage your tasks for freelancers
</Tabs.Content>
</Tabs.Root>
)}
</For>
</SimpleGrid>
)
}
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.
"use client"
import { Tabs } from "@chakra-ui/react"
import { useEffect, useState } from "react"
const Demo = () => {
return (
<Tabs.Root lazyMount unmountOnExit defaultValue="tab-1">
<Tabs.List>
<Tabs.Trigger value="tab-1">Tab 1</Tabs.Trigger>
<Tabs.Trigger value="tab-2">Tab 2</Tabs.Trigger>
<Tabs.Trigger value="tab-3">Tab 3</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab-1">
Tab 1: Content <TickValue />
</Tabs.Content>
<Tabs.Content value="tab-2">
Tab 2: Content <TickValue />
</Tabs.Content>
<Tabs.Content value="tab-3">
Tab 3: Content <TickValue />
</Tabs.Content>
</Tabs.Root>
)
}
const TickValue = () => {
const [value, setValue] = useState(0)
useEffect(() => {
const intervalId = window.setInterval(() => {
setValue((v) => v + 1)
}, 1000)
return () => {
window.clearInterval(intervalId)
}
}, [])
return (
<span style={{ fontWeight: "bold", color: "tomato", padding: 4 }}>
{value}
</span>
)
}
Indicator
Render the Tabs.Indicator
component to display a visual indicator of the
active tab.
import { Tabs } from "@chakra-ui/react"
import { LuCheckSquare, LuFolder, LuUser } from "react-icons/lu"
const Demo = () => {
return (
<Tabs.Root defaultValue="members" variant="plain">
<Tabs.List bg="bg.muted" rounded="l3" p="1">
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuCheckSquare />
Settings
</Tabs.Trigger>
<Tabs.Indicator rounded="l2" />
</Tabs.List>
<Tabs.Content value="members">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="tasks">
Manage your tasks for freelancers
</Tabs.Content>
</Tabs.Root>
)
}
Links
Pass the asChild
to the Tabs.Trigger
component to render a link as a tab.
When a tab is clicked, the link will be navigated to.
import { Link, Tabs } from "@chakra-ui/react"
const Demo = () => {
return (
<Tabs.Root defaultValue="members">
<Tabs.List>
<Tabs.Trigger value="members" asChild>
<Link unstyled href="#members">
Members
</Link>
</Tabs.Trigger>
<Tabs.Trigger value="projects" asChild>
<Link unstyled href="#projects">
Projects
</Link>
</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="members">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
</Tabs.Root>
)
}
Fitted
Use the fitted
prop to make the tabs fit the width of the container.
import { Tabs } from "@chakra-ui/react"
const Demo = () => {
return (
<Tabs.Root variant="enclosed" maxW="md" fitted defaultValue={"tab-1"}>
<Tabs.List>
<Tabs.Trigger value="tab-1">Tab 1</Tabs.Trigger>
<Tabs.Trigger value="tab-2">Tab 2</Tabs.Trigger>
<Tabs.Trigger value="tab-3">Tab 3</Tabs.Trigger>
</Tabs.List>
</Tabs.Root>
)
}
Controlled
Use the value
and onValueChange
prop to control the active tab.
"use client"
import { Tabs } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [value, setValue] = useState<string | null>("first")
return (
<Tabs.Root value={value} onValueChange={(e) => setValue(e.value)}>
<Tabs.List>
<Tabs.Trigger value="first">First tab</Tabs.Trigger>
<Tabs.Trigger value="second">Second tab</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="first">First panel</Tabs.Content>
<Tabs.Content value="second">Second panel</Tabs.Content>
</Tabs.Root>
)
}
Disabled Tab
Set the disabled
prop on the Tabs.Trigger
component to disable a tab.
import { Tabs } from "@chakra-ui/react"
import { LuCheckSquare, LuFolder, LuUser } from "react-icons/lu"
const Demo = () => {
return (
<Tabs.Root defaultValue="members">
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects" disabled>
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuCheckSquare />
Settings
</Tabs.Trigger>
</Tabs.List>
{/* content */}
</Tabs.Root>
)
}
Manual activation
By default, the tabs are selected when the arrow keys are pressed. Disable this
behavior by setting the activationBehavior
prop to manual
.
In this mode, the tabs will only be selected when clicked or the enter key is pressed.
import { Tabs } from "@chakra-ui/react"
import { LuCheckSquare, LuFolder, LuUser } from "react-icons/lu"
const Demo = () => {
return (
<Tabs.Root defaultValue="members" activationMode="manual">
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects" disabled>
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuCheckSquare />
Settings
</Tabs.Trigger>
</Tabs.List>
{/* content */}
</Tabs.Root>
)
}
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.
Tab Content 2
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.
Tab Content 3
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.
Tab Content 4
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.
"use client"
import { Button, Heading, Tabs, Text } from "@chakra-ui/react"
import { CloseButton } from "@/components/ui/close-button"
import { useState } from "react"
import { LuPlus } from "react-icons/lu"
interface Item {
id: string
title: string
content: React.ReactNode
}
const items: Item[] = [
{ id: "1", title: "Tab", content: "Tab Content" },
{ id: "2", title: "Tab", content: "Tab Content" },
{ id: "3", title: "Tab", content: "Tab Content" },
{ id: "4", title: "Tab", content: "Tab Content" },
]
const uuid = () => {
return Math.random().toString(36).substring(2, 15)
}
const Demo = () => {
const [tabs, setTabs] = useState<Item[]>(items)
const [selectedTab, setSelectedTab] = useState<string | null>(items[0].id)
const addTab = () => {
const newTabs = [...tabs]
const uid = uuid()
newTabs.push({
id: uid,
title: `Tab`,
content: `Tab Body`,
})
setTabs(newTabs)
setSelectedTab(newTabs[newTabs.length - 1].id)
}
const removeTab = (id: string) => {
if (tabs.length > 1) {
const newTabs = [...tabs].filter((tab) => tab.id !== id)
setTabs(newTabs)
}
}
return (
<Tabs.Root
value={selectedTab}
variant="outline"
size="sm"
onValueChange={(e) => setSelectedTab(e.value)}
>
<Tabs.List flex="1 1 auto">
{tabs.map((item) => (
<Tabs.Trigger value={item.id} key={item.id}>
{item.title}{" "}
<CloseButton
as="span"
role="button"
size="2xs"
me="-2"
onClick={(e) => {
e.stopPropagation()
removeTab(item.id)
}}
/>
</Tabs.Trigger>
))}
<Button
alignSelf="center"
ms="2"
size="2xs"
variant="ghost"
onClick={addTab}
>
<LuPlus /> Add Tab
</Button>
</Tabs.List>
<Tabs.ContentGroup>
{tabs.map((item) => (
<Tabs.Content value={item.id} key={item.id}>
<Heading size="xl" my="6">
{item.content} {item.id}
</Heading>
<Text>
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.
</Text>
</Tabs.Content>
))}
</Tabs.ContentGroup>
</Tabs.Root>
)
}
Props
Root
Prop | Default | Type |
---|---|---|
activationMode | '\'automatic\'' | 'manual' | 'automatic' The activation mode of the tabs. Can be `manual` or `automatic` - `manual`: Tabs are activated when clicked or press `enter` key. - `automatic`: Tabs are activated when receiving focus |
lazyMount | false | boolean Whether to enable lazy mounting |
loopFocus | true | boolean Whether the keyboard navigation will loop from last tab to first, and vice versa. |
orientation | '\'horizontal\'' | 'horizontal' | 'vertical' The orientation of the tabs. Can be `horizontal` or `vertical` - `horizontal`: only left and right arrow key navigation will work. - `vertical`: only up and down arrow key navigation will work. |
unmountOnExit | false | boolean Whether to unmount on exit. |
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' | 'accent' The color palette of the component |
size | 'md' | 'sm' | 'md' | 'lg' The size of the component |
variant | 'line' | 'line' | 'subtle' | 'enclosed' | 'outline' | 'plain' The variant of the component |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
composite | boolean Whether the tab is composite | |
defaultValue | string The initial value of the tabs when it is first rendered. Use when you do not need to control the state of the tabs. | |
id | string The unique identifier of the machine. | |
ids | Partial<{
root: string
trigger: string
list: string
content: string
indicator: string
}> The ids of the elements in the tabs. Useful for composition. | |
onFocusChange | (details: FocusChangeDetails) => void Callback to be called when the focused tab changes | |
onValueChange | (details: ValueChangeDetails) => void Callback to be called when the selected/active tab changes | |
translations | IntlTranslations Specifies the localized strings that identifies the accessibility elements and their states | |
value | string The selected tab id | |
fitted | 'true' | 'false' The fitted of the component | |
justify | 'start' | 'center' | 'end' The justify of the component |
Trigger
Prop | Default | Type |
---|---|---|
value * | string The value of the tab | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
disabled | boolean Whether the tab is disabled |
Content
Prop | Default | Type |
---|---|---|
value * | string The value of the tab | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |