46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
|
|
export interface SectionTab<T extends string> {
|
||
|
|
id: T
|
||
|
|
label: string
|
||
|
|
count?: number
|
||
|
|
}
|
||
|
|
|
||
|
|
interface SectionTabsProps<T extends string> {
|
||
|
|
tabs: SectionTab<T>[]
|
||
|
|
activeTab: T
|
||
|
|
onChange: (tab: T) => void
|
||
|
|
className?: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export default function SectionTabs<T extends string>({
|
||
|
|
tabs,
|
||
|
|
activeTab,
|
||
|
|
onChange,
|
||
|
|
className = '',
|
||
|
|
}: SectionTabsProps<T>) {
|
||
|
|
return (
|
||
|
|
<div className={`sticky top-0 z-20 border-b border-gray-200 bg-white/95 py-3 backdrop-blur dark:border-gray-800 dark:bg-gray-950/95 ${className}`}>
|
||
|
|
<div className="flex gap-2 overflow-x-auto">
|
||
|
|
{tabs.map((tab) => (
|
||
|
|
<button
|
||
|
|
key={tab.id}
|
||
|
|
type="button"
|
||
|
|
onClick={() => onChange(tab.id)}
|
||
|
|
className={
|
||
|
|
activeTab === tab.id
|
||
|
|
? 'whitespace-nowrap rounded-lg bg-primary-600 px-3 py-2 text-sm font-semibold text-white'
|
||
|
|
: 'whitespace-nowrap rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium text-gray-700 transition hover:border-primary-400 hover:text-primary-700 dark:border-gray-700 dark:text-gray-300 dark:hover:text-primary-300'
|
||
|
|
}
|
||
|
|
>
|
||
|
|
{tab.label}
|
||
|
|
{typeof tab.count === 'number' ? (
|
||
|
|
<span className={activeTab === tab.id ? 'ml-2 text-primary-100' : 'ml-2 text-gray-500 dark:text-gray-400'}>
|
||
|
|
{tab.count.toLocaleString()}
|
||
|
|
</span>
|
||
|
|
) : null}
|
||
|
|
</button>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)
|
||
|
|
}
|