70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
"use client";
|
|
|
|
import { Fragment, ReactNode } from 'react';
|
|
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react';
|
|
|
|
interface TabItem {
|
|
label: string;
|
|
icon?: ReactNode;
|
|
content: ReactNode;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
interface TabsProps {
|
|
items: TabItem[];
|
|
defaultIndex?: number;
|
|
onChange?: (index: number) => void;
|
|
className?: string;
|
|
variant?: 'pills' | 'underline';
|
|
}
|
|
|
|
function classNames(...classes: string[]) {
|
|
return classes.filter(Boolean).join(' ');
|
|
}
|
|
|
|
export default function Tabs({
|
|
items,
|
|
defaultIndex = 0,
|
|
onChange,
|
|
className = "",
|
|
variant = 'pills'
|
|
}: TabsProps) {
|
|
return (
|
|
<TabGroup defaultIndex={defaultIndex} onChange={onChange} className={className}>
|
|
<TabList className={classNames(
|
|
'flex space-x-1 p-1 mb-6',
|
|
variant === 'pills' ? 'bg-zinc-100 dark:bg-zinc-800/50 rounded-xl' : 'border-b border-zinc-200 dark:border-zinc-800 bg-transparent'
|
|
)}>
|
|
{items.map((item, index) => (
|
|
<Tab
|
|
key={index}
|
|
disabled={item.disabled}
|
|
className={({ selected }) =>
|
|
classNames(
|
|
'flex items-center justify-center gap-2 py-2.5 text-sm font-bold transition-all outline-none rounded-lg flex-1 cursor-pointer',
|
|
variant === 'pills'
|
|
? selected
|
|
? 'bg-white dark:bg-zinc-700 text-zinc-900 dark:text-white shadow-sm ring-1 ring-black/5'
|
|
: 'text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-white/50 dark:hover:bg-zinc-700/30'
|
|
: selected
|
|
? 'border-b-2 border-brand-500 text-brand-500 rounded-none'
|
|
: 'text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 border-b-2 border-transparent rounded-none'
|
|
)
|
|
}
|
|
>
|
|
{item.icon && <span className="w-4 h-4">{item.icon}</span>}
|
|
{item.label}
|
|
</Tab>
|
|
))}
|
|
</TabList>
|
|
<TabPanels>
|
|
{items.map((item, index) => (
|
|
<TabPanel key={index} className="outline-none">
|
|
{item.content}
|
|
</TabPanel>
|
|
))}
|
|
</TabPanels>
|
|
</TabGroup>
|
|
);
|
|
}
|