Files
leocrm/frontend/src/components/shared/Tabs.tsx
T

63 lines
2.0 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
import clsx from 'clsx';
export interface TabItem {
key: string;
label: string;
content: React.ReactNode;
badge?: number;
}
export interface TabsProps {
tabs: TabItem[];
defaultKey?: string;
className?: string;
}
export function Tabs({ tabs, defaultKey, className }: TabsProps) {
const [activeKey, setActiveKey] = useState(defaultKey || tabs[0]?.key || '');
const activeTab = tabs.find((t) => t.key === activeKey);
return (
<div className={clsx('w-full', className)}>
<div className="border-b border-secondary-200" role="tablist">
<div className="flex gap-1 px-6 overflow-x-auto">
{tabs.map((tab) => (
<button
key={tab.key}
role="tab"
aria-selected={activeKey === tab.key}
aria-controls={`panel-${tab.key}`}
id={`tab-${tab.key}`}
tabIndex={activeKey === tab.key ? 0 : -1}
onClick={() => setActiveKey(tab.key)}
className={clsx(
'px-4 py-3 text-sm font-medium border-b-2 min-h-touch whitespace-nowrap',
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 rounded-t-md',
activeKey === tab.key
? 'border-primary-600 text-primary-700'
: 'border-transparent text-secondary-600 hover:text-secondary-900 hover:border-secondary-300'
)}
>
{tab.label}
{tab.badge !== undefined && tab.badge > 0 && (
<span className="ml-2 inline-flex items-center justify-center px-2 py-0.5 rounded-full text-xs bg-primary-100 text-primary-700">
{tab.badge}
</span>
)}
</button>
))}
</div>
</div>
<div
id={`panel-${activeKey}`}
role="tabpanel"
aria-labelledby={`tab-${activeKey}`}
className="px-6 py-4"
>
{activeTab?.content}
</div>
</div>
);
}