103 lines
4.2 KiB
TypeScript
103 lines
4.2 KiB
TypeScript
'use client';
|
|
|
|
import { Tab } from '@headlessui/react';
|
|
import { ReactNode } from 'react';
|
|
|
|
function classNames(...classes: string[]) {
|
|
return classes.filter(Boolean).join(' ');
|
|
}
|
|
|
|
export interface TabItem {
|
|
name: string;
|
|
icon?: React.ComponentType<{ className?: string }>;
|
|
content: ReactNode;
|
|
}
|
|
|
|
interface TabsProps {
|
|
tabs: TabItem[];
|
|
defaultIndex?: number;
|
|
onChange?: (index: number) => void;
|
|
variant?: 'card' | 'modal'; // Novo: variante para diferentes contextos
|
|
}
|
|
|
|
export default function Tabs({ tabs, defaultIndex = 0, onChange, variant = 'card' }: TabsProps) {
|
|
if (variant === 'modal') {
|
|
// Versão para modais - sem card wrapper
|
|
return (
|
|
<Tab.Group defaultIndex={defaultIndex} onChange={onChange}>
|
|
<Tab.List className="flex border-b border-zinc-200 dark:border-zinc-700 px-6">
|
|
{tabs.map((tab) => (
|
|
<Tab
|
|
key={tab.name}
|
|
className={({ selected }) =>
|
|
classNames(
|
|
'px-4 py-3 text-sm font-medium border-b-2 transition-colors focus:outline-none whitespace-nowrap',
|
|
selected
|
|
? 'border-[var(--brand-color)] text-[var(--brand-color)]'
|
|
: 'border-transparent text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300'
|
|
)
|
|
}
|
|
>
|
|
<div className="flex items-center justify-center gap-2">
|
|
{tab.icon && <tab.icon className="w-4 h-4 flex-shrink-0" />}
|
|
{tab.name}
|
|
</div>
|
|
</Tab>
|
|
))}
|
|
</Tab.List>
|
|
|
|
<Tab.Panels className="p-6">
|
|
{tabs.map((tab, idx) => (
|
|
<Tab.Panel
|
|
key={idx}
|
|
className="focus:outline-none"
|
|
>
|
|
{tab.content}
|
|
</Tab.Panel>
|
|
))}
|
|
</Tab.Panels>
|
|
</Tab.Group>
|
|
);
|
|
}
|
|
|
|
// Versão padrão para páginas - com card wrapper
|
|
return (
|
|
<Tab.Group defaultIndex={defaultIndex} onChange={onChange}>
|
|
<div className="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden">
|
|
<Tab.List className="flex space-x-1 rounded-t-xl bg-zinc-100 dark:bg-zinc-800/50 p-1 overflow-x-auto scrollbar-hide">
|
|
{tabs.map((tab) => (
|
|
<Tab
|
|
key={tab.name}
|
|
className={({ selected }) =>
|
|
classNames(
|
|
'w-full rounded-lg py-2 sm:py-2.5 px-3 sm:px-4 text-xs sm:text-sm font-medium leading-5 transition-all duration-200 whitespace-nowrap',
|
|
'focus:outline-none',
|
|
selected
|
|
? 'bg-white dark:bg-zinc-800 text-zinc-900 dark:text-white shadow'
|
|
: 'text-zinc-500 hover:bg-white/[0.12] hover:text-zinc-700 dark:hover:text-zinc-300'
|
|
)
|
|
}
|
|
>
|
|
<div className="flex items-center justify-center gap-1.5 sm:gap-2">
|
|
{tab.icon && <tab.icon className="w-3.5 h-3.5 sm:w-4 sm:h-4 flex-shrink-0" />}
|
|
{tab.name}
|
|
</div>
|
|
</Tab>
|
|
))}
|
|
</Tab.List>
|
|
|
|
<Tab.Panels className="p-4 sm:p-6">
|
|
{tabs.map((tab, idx) => (
|
|
<Tab.Panel
|
|
key={idx}
|
|
className="focus:outline-none"
|
|
>
|
|
{tab.content}
|
|
</Tab.Panel>
|
|
))}
|
|
</Tab.Panels>
|
|
</div>
|
|
</Tab.Group>
|
|
);
|
|
}
|