espace-paie-odentas/components/ui/tabs.tsx

60 lines
No EOL
1.8 KiB
TypeScript

'use client';
import * as React from 'react';
type TabsContextValue = {
value: string;
setValue: (v: string) => void;
};
const TabsContext = React.createContext<TabsContextValue | null>(null);
type TabsProps = React.HTMLAttributes<HTMLDivElement> & {
defaultValue: string;
};
export function Tabs({ defaultValue, className = '', children, ...props }: TabsProps) {
const [value, setValue] = React.useState(defaultValue);
return (
<TabsContext.Provider value={{ value, setValue }}>
<div className={className} {...props}>{children}</div>
</TabsContext.Provider>
);
}
export function TabsList({ className = '', ...props }: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={`inline-flex w-full overflow-hidden rounded-md border bg-gray-50 p-1 ${className}`}
{...props}
/>
);
}
type TriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
value: string;
};
export function TabsTrigger({ value, className = '', ...props }: TriggerProps) {
const ctx = React.useContext(TabsContext);
if (!ctx) throw new Error('TabsTrigger must be used inside <Tabs>');
const active = ctx.value === value;
return (
<button
type="button"
onClick={() => ctx.setValue(value)}
className={`flex-1 px-4 py-2 text-sm rounded-md transition
${active ? 'bg-white border shadow-sm' : 'text-gray-600 hover:bg-white/60'}
${className}`}
{...props}
/>
);
}
type ContentProps = React.HTMLAttributes<HTMLDivElement> & { value: string };
export function TabsContent({ value, className = '', ...props }: ContentProps) {
const ctx = React.useContext(TabsContext);
if (!ctx) throw new Error('TabsContent must be used inside <Tabs>');
if (ctx.value !== value) return null;
return <div className={className} {...props} />;
}