54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
import React, { useState } from 'react';
|
|
|
|
interface Tab {
|
|
id: string;
|
|
label: string;
|
|
content: React.ReactNode;
|
|
}
|
|
|
|
interface TabsProps {
|
|
tabs: Tab[];
|
|
defaultTab?: string;
|
|
onChange?: (id: string) => void;
|
|
className?: string;
|
|
}
|
|
|
|
const Tabs: React.FC<TabsProps> = ({ tabs, defaultTab, onChange, className = "" }) => {
|
|
const [activeTab, setActiveTab] = useState(defaultTab || tabs[0]?.id);
|
|
|
|
const handleTabChange = (id: string) => {
|
|
setActiveTab(id);
|
|
if (onChange) {
|
|
onChange(id);
|
|
}
|
|
};
|
|
|
|
if (!tabs || tabs.length === 0) return null;
|
|
|
|
return (
|
|
<div className={`flex flex-col w-full ${className}`}>
|
|
<div className="flex border-b border-slate-200 dark:border-slate-700">
|
|
{tabs.map((tab) => (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => handleTabChange(tab.id)}
|
|
className={`
|
|
px-4 py-2 text-sm font-medium transition-colors duration-200
|
|
${activeTab === tab.id
|
|
? 'border-b-2 border-blue-500 text-blue-600 dark:text-blue-400'
|
|
: 'text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200'
|
|
}
|
|
`}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
<div className="py-4">
|
|
{tabs.find((tab) => tab.id === activeTab)?.content}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Tabs; |