跳到主要内容

Tabs 导航栏

按钮组件

演示

type

基础使用演示

Tab 1
Tab 2
Tab 3
Tab 4
Panel 1

renderIndicator自定义指示器,可以配合framer-motion等给指示器加上动画效果

Tab 1
Tab 2
Tab 3
Tab 4
Panel 1

beforeTabChange 可在 Tab 切换时进行拦截,当返回值为 true 时可正常切换,否则不进行切换。点击后请看控制台

Tab 1
Tab 2
Tab 3
Tab 4
Panel 1
基本使用
收起源代码
import { Tabs, Space, Icon, IconType } from '@dance-ui/ui'
import React from 'react'

const { Tab, TabPanel, TabList } = Tabs

const Demo = () => {
return (
<Space direction="vertical" gap={24}>
<section>
<p>基础使用演示</p>
<Tabs>
<TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
<Tab>Tab 4</Tab>
</TabList>
<TabPanel>
<div>Panel 1</div>
</TabPanel>
<TabPanel>
<div>Panel 2</div>
</TabPanel>
<TabPanel>
<div>Panel 3</div>
</TabPanel>
<TabPanel>
<div>Panel 4</div>
</TabPanel>
</Tabs>
</section>
<section>
<p>renderIndicator自定义指示器,可以配合framer-motion等给指示器加上动画效果</p>
<Tabs id="test1">
<TabList
renderIndicator={() => {
return (
<Space justify="center" className="absolute inset-x-0 h-5 text-center" style={{ bottom: '-20px' }}>
<Icon type={IconType.CLOSE} style={{ fontSize: 20 }} />
</Space>
)
}}>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
<Tab>Tab 4</Tab>
</TabList>
<TabPanel>
<div>Panel 1</div>
</TabPanel>
<TabPanel>
<div>Panel 2</div>
</TabPanel>
<TabPanel>
<div>Panel 3</div>
</TabPanel>
<TabPanel>
<div>Panel 4</div>
</TabPanel>
</Tabs>
</section>
<section>
<p>beforeTabChange 可在 Tab 切换时进行拦截,当返回值为 true 时可正常切换,否则不进行切换。点击后请看控制台</p>
<Tabs id="test2">
<TabList
beforeTabChange={async ({ event, idx }) => {
console.log('beforeTabChange args', { event, idx })
console.log('It will change after 1000 ms!')
return new Promise((resolve) =>
setTimeout(() => {
console.log('resolve!')
resolve(true)
}, 1000),
)
}}>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
<Tab>Tab 4</Tab>
</TabList>
<TabPanel>
<div>Panel 1</div>
</TabPanel>
<TabPanel>
<div>Panel 2</div>
</TabPanel>
<TabPanel>
<div>Panel 3</div>
</TabPanel>
<TabPanel>
<div>Panel 4</div>
</TabPanel>
</Tabs>
</section>
</Space>
)
}
export default Demo

组件源码

组件源码
import { ReactElement, cloneElement, useState } from 'react'
import Tab from './Tab'
import TabList from './TabList'
import TabPanel from './TabPanel'
import { twMerge } from 'tailwind-merge'

export type TabsProps = {
id?: string
className?: string
children?: ReactElement[]
}
function Tabs({ id = 'default', className, children }: TabsProps) {
const [selected, setSelected] = useState(0)
const [tabList, ...tabPanels] = children ?? []

if (!children?.length || children?.length <= 1) throw new Error('Tabs must have at least 2 children')
return (
<div className={twMerge('flex flex-col items-center justify-center gap-3', className)}>
{cloneElement(tabList, {
selected,
setSelected,
onClick: tabList?.props?.onClick,
id,
...(tabList?.props ?? {}),
})}
{cloneElement(tabPanels[selected], {
key: tabPanels[selected]?.props?.key ?? `${id}-tab-panel-${selected}`,
...(tabPanels[selected]?.props ?? {}),
})}
</div>
)
}

Tabs.TabList = TabList
Tabs.Tab = Tab
Tabs.TabPanel = TabPanel
export default Tabs