All files / src/components/ui tabs.tsx

100% Statements 15/15
100% Branches 8/8
100% Functions 5/5
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105                                                      14x           207x               207x                           751x 751x 2x     748x   748x         46x                             741x 741x 2x     738x 536x     202x                          
import * as React from "react";
import { cn } from "../../lib/utils";
 
interface TabsProps {
	value: string;
	onValueChange: (value: string) => void;
	children: React.ReactNode;
	className?: string;
}
 
interface TabsListProps {
	children: React.ReactNode;
	className?: string;
}
 
interface TabsTriggerProps {
	value: string;
	children: React.ReactNode;
	className?: string;
}
 
interface TabsContentProps {
	value: string;
	children: React.ReactNode;
	className?: string;
}
 
const TabsContext = React.createContext<{
	value: string;
	onValueChange: (value: string) => void;
} | null>(null);
 
export function Tabs({ value, onValueChange, children, className }: TabsProps) {
	return (
		<TabsContext.Provider value={{ value, onValueChange }}>
			<div className={cn("w-full", className)}>{children}</div>
		</TabsContext.Provider>
	);
}
 
export function TabsList({ children, className }: TabsListProps) {
	return (
		<div
			role="tablist"
			className={cn(
				"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground overflow-x-auto",
				className,
			)}
		>
			{children}
		</div>
	);
}
 
export function TabsTrigger({ value, children, className }: TabsTriggerProps) {
	const context = React.useContext(TabsContext);
	if (!context) {
		throw new Error("TabsTrigger must be used within Tabs");
	}
 
	const isActive = context.value === value;
 
	return (
		<button
			type="button"
			role="tab"
			aria-selected={isActive}
			onClick={() => context.onValueChange(value)}
			className={cn(
				"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
				isActive
					? "bg-background text-foreground shadow-sm"
					: "text-muted-foreground hover:text-foreground",
				className,
			)}
		>
			{children}
		</button>
	);
}
 
export function TabsContent({ value, children, className }: TabsContentProps) {
	const context = React.useContext(TabsContext);
	if (!context) {
		throw new Error("TabsContent must be used within Tabs");
	}
 
	if (context.value !== value) {
		return null;
	}
 
	return (
		<div
			role="tabpanel"
			key={value}
			className={cn(
				"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 animate-tab-in",
				className,
			)}
		>
			{children}
		</div>
	);
}