Files
sass-mohfarawati/components/ui/tabs.tsx
T

115 lines
2.5 KiB
TypeScript

"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
type TabsContextValue = {
value: string;
setValue: (value: string) => void;
};
const TabsContext = React.createContext<TabsContextValue | null>(null);
function useTabsContext() {
const context = React.useContext(TabsContext);
if (!context) {
throw new Error("Tabs components must be used within Tabs.");
}
return context;
}
type TabsProps = {
defaultValue: string;
children: React.ReactNode;
className?: string;
};
function Tabs({ defaultValue, children, className }: TabsProps) {
const [value, setValue] = React.useState(defaultValue);
return (
<TabsContext.Provider value={{ value, setValue }}>
<div className={cn("w-full", className)}>{children}</div>
</TabsContext.Provider>
);
}
function TabsList({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn(
"inline-flex h-auto flex-wrap items-center gap-2 rounded-surface border border-border/80 bg-muted/40 p-1.5",
className,
)}
{...props}
/>
);
}
type TabsTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
value: string;
};
function TabsTrigger({
className,
value,
onClick,
...props
}: TabsTriggerProps) {
const { value: activeValue, setValue } = useTabsContext();
const isActive = activeValue === value;
return (
<button
type="button"
className={cn(
"inline-flex items-center justify-center rounded-nested px-3 py-2 text-sm font-medium text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50",
isActive && "bg-background text-foreground shadow-sm",
className,
)}
onClick={(event) => {
setValue(value);
onClick?.(event);
}}
{...props}
/>
);
}
type TabsContentProps = React.HTMLAttributes<HTMLDivElement> & {
value: string;
};
function TabsContent({
className,
value,
children,
...props
}: TabsContentProps) {
const { value: activeValue } = useTabsContext();
if (activeValue !== value) {
return null;
}
return (
<div
className={cn(
"mt-6 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className,
)}
{...props}
>
{children}
</div>
);
}
export { Tabs, TabsContent, TabsList, TabsTrigger };