import { Tabs } from "@chakra-ui/react"
import { LuFolder, LuSquareCheck, 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">
<LuSquareCheck />
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
使用 variant
属性更改标签的视觉样式。
¥Use the variant
prop to change the visual style of the tabs.
import { For, SimpleGrid, Tabs } from "@chakra-ui/react"
import { LuFolder, LuSquareCheck, 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">
<LuSquareCheck />
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
使用 lazyMount
和/或 unmountOnExit
属性仅在标签页处于活动状态时渲染内容。这对于性能优化非常有用。
¥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
渲染 Tabs.Indicator
组件以显示活动选项卡的视觉指示。
¥Render the Tabs.Indicator
component to display a visual indicator of the
active tab.
import { Tabs } from "@chakra-ui/react"
import { LuFolder, LuSquareCheck, 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">
<LuSquareCheck />
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
将 asChild
属性传递给 Tabs.Trigger
组件以将链接渲染为选项卡。点击标签页时,将导航至相应的链接。
¥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>
)
}
使用自定义路由链接时,需要在 Tabs.Root
组件上设置 navigate
属性。
¥When using custom router links, you need to set the navigate
prop on the
Tabs.Root
component.
"use client"
import { Tabs } from "@chakra-ui/react"
import { useNavigate } from "react-router-dom"
const Demo = () => {
const navigate = useNavigate()
return (
<Tabs.Root navigate={({ value, node }) => navigate(`/${value}`)}>
{/* ... */}
</Tabs.Root>
)
}
适合
¥Fitted
使用 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
使用 value
和 onValueChange
属性控制活动选项卡。
¥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>
)
}
商店
¥Store
控制选项卡的另一种方法是使用 RootProvider
组件和 useTabs
存储钩子。
¥An alternative way to control the tabs is to use the RootProvider
component
and the useTabs
store hook.
这样,你就可以从选项卡外部访问选项卡的状态和方法。
¥This way you can access the tabs state and methods from outside the tabs.
selected: members
"use client"
import { Code, Stack, Tabs, useTabs } from "@chakra-ui/react"
import { LuFolder, LuSquareCheck, LuUser } from "react-icons/lu"
const Demo = () => {
const tabs = useTabs({
defaultValue: "members",
})
return (
<Stack align="flex-start">
<Code>selected: {tabs.value}</Code>
<Tabs.RootProvider value={tabs}>
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuSquareCheck />
Tasks
</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.RootProvider>
</Stack>
)
}
已禁用标签页
¥Disabled Tab
在 Tabs.Trigger
组件上设置 disabled
属性以禁用选项卡。
¥Set the disabled
prop on the Tabs.Trigger
component to disable a tab.
import { Tabs } from "@chakra-ui/react"
import { LuFolder, LuSquareCheck, 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">
<LuSquareCheck />
Settings
</Tabs.Trigger>
</Tabs.List>
{/* content */}
</Tabs.Root>
)
}
手动激活
¥Manual activation
默认情况下,按下箭头键时会选中选项卡。通过将 activationBehavior
属性设置为 manual
来禁用此行为。
¥By default, the tabs are selected when the arrow keys are pressed. Disable this
behavior by setting the activationBehavior
prop to manual
.
在此模式下,只有点击或按下 Enter 键时才会选中标签页。
¥In this mode, the tabs will only be selected when clicked or the enter key is pressed.
import { Tabs } from "@chakra-ui/react"
import { LuFolder, LuSquareCheck, 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">
<LuSquareCheck />
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, CloseButton, Heading, Tabs, Text } from "@chakra-ui/react"
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>
)
}
动画
¥Animation
使用 _open
和 _close
条件属性为标签添加动画效果。
¥Use the _open
and _close
conditional props to animate the tabs.
import { Box, Flex, Tabs } from "@chakra-ui/react"
const items = [
{
title: "1",
content: "Dolore ex esse laboris elit magna esse sunt",
},
{
title: "2",
content:
"Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex.",
},
]
const Demo = () => {
return (
<Flex minH="dvh">
<Tabs.Root defaultValue="1" width="full">
<Tabs.List>
{items.map((item, index) => (
<Tabs.Trigger key={index} value={item.title}>
Tab {item.title}
</Tabs.Trigger>
))}
</Tabs.List>
<Box pos="relative" minH="200px" width="full">
{items.map((item, index) => (
<Tabs.Content
key={index}
value={item.title}
position="absolute"
inset="0"
_open={{
animationName: "fade-in, scale-in",
animationDuration: "300ms",
}}
_closed={{
animationName: "fade-out, scale-out",
animationDuration: "120ms",
}}
>
{item.content}
</Tabs.Content>
))}
</Box>
</Tabs.Root>
</Flex>
)
}
属性
¥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' 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 |
as | React.ElementType The underlying element to render. | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | boolean Whether to remove the component's style. | |
composite | boolean Whether the tab is composite | |
defaultValue | string The initial selected tab value when rendered. Use when you don't need to control the selected tab value. | |
deselectable | boolean Whether the active tab can be deselected when clicking on it. | |
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. | |
navigate | (details: NavigateDetails) => void Function to navigate to the selected tab when clicking on it. Useful if tab triggers are anchor elements. | |
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 controlled selected tab value | |
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. |