tabs.tsx
1 import * as TabsPrimitive from "@radix-ui/react-tabs"; 2 import * as React from "react"; 3 4 import { VariantProps, cva } from "class-variance-authority"; 5 import { cn } from "../../lib/utils"; 6 7 const Tabs = TabsPrimitive.Root; 8 9 const tabsListVariants = cva( 10 "inline-flex items-center justify-center px-1 bg-gray-500/10", 11 { 12 variants: { 13 color: { 14 primary: "text-primary", 15 secondary: "text-secondary", 16 error: "text-error", 17 success: "text-success", 18 warning: "text-warning", 19 info: "text-info", 20 muted: "bg-gray-500", 21 }, 22 round: { 23 none: "rounded-none", 24 both: "rounded-full", 25 left: "rounded-l-full", 26 right: "rounded-r-full", 27 t: "rounded-t", 28 b: "rounded-b", 29 tl: "rounded-tl", 30 tr: "rounded-tr", 31 bl: "rounded-bl", 32 br: "rounded-br", 33 }, 34 radius: { 35 full: "rounded-full", 36 xs: "rounded-[2px]", 37 sm: "rounded-[4px]", 38 md: "rounded-[6px]", 39 lg: "rounded-[8px]", 40 xl: "rounded-[12px]", 41 }, 42 size: { 43 xs: "h-4", 44 sm: "h-6", 45 md: "h-7", 46 lg: "px-1.5 h-9", 47 xl: "px-2 h-10", 48 }, 49 }, 50 defaultVariants: { 51 size: "md", 52 radius: "md", 53 round: "both", 54 color: "primary", 55 }, 56 }, 57 ); 58 59 export interface TabsListProps 60 extends Omit< 61 React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>, 62 "color" 63 >, 64 VariantProps<typeof tabsListVariants> {} 65 66 const TabsList = React.forwardRef< 67 React.ElementRef<typeof TabsPrimitive.List>, 68 TabsListProps 69 >(({ className, size, round, radius, color, ...props }, ref) => ( 70 <TabsPrimitive.List 71 ref={ref} 72 className={cn( 73 tabsListVariants({ 74 color, 75 round, 76 radius, 77 size, 78 }), 79 size !== "xs" && `rounded-${round}-${size}`, 80 className, 81 )} 82 {...props} 83 /> 84 )); 85 TabsList.displayName = TabsPrimitive.List.displayName; 86 87 const tabsTriggerVariants = cva( 88 "inline-flex items-center bg-transparent hover:text-foreground hover:border-foreground justify-center whitespace-nowrap 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 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm", 89 { 90 variants: { 91 color: { 92 primary: "border-primary text-primary", 93 secondary: "border-secondary text-secondary", 94 error: "border-error text-error", 95 success: "border-success text-success", 96 warning: "border-warning text-warning", 97 info: "border-info text-info", 98 muted: "border-gray-500", 99 }, 100 size: { 101 xs: "px-2 h-3.5 text-xs", 102 sm: "px-3 h-4.5 text-sm", 103 md: "px-4 h-5.5 text-base", 104 lg: "px-8 h-7.5 text-lg", 105 xl: "px-10 h-8.5 text-xl", 106 }, 107 radius: { 108 full: "rounded-full", 109 xs: "rounded-[2px]", 110 sm: "rounded-[4px]", 111 md: "rounded-[6px]", 112 lg: "rounded-[8px]", 113 xl: "rounded-[12px]", 114 }, 115 }, 116 defaultVariants: { 117 color: "muted", 118 radius: "sm", 119 size: "md", 120 }, 121 }, 122 ); 123 124 export interface TabsTriggerProps 125 extends Omit< 126 React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, 127 "color" 128 >, 129 VariantProps<typeof tabsTriggerVariants> {} 130 131 const TabsTrigger = React.forwardRef< 132 React.ElementRef<typeof TabsPrimitive.Trigger>, 133 TabsTriggerProps 134 >(({ className, color, radius, size, ...props }, ref) => { 135 return ( 136 <TabsPrimitive.Trigger 137 ref={ref} 138 className={cn( 139 tabsTriggerVariants({ 140 color, 141 radius, 142 size, 143 }), 144 className, 145 )} 146 {...props} 147 /> 148 ); 149 }); 150 151 TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; 152 153 const TabsContent = React.forwardRef< 154 React.ElementRef<typeof TabsPrimitive.Content>, 155 React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content> 156 >(({ className, ...props }, ref) => ( 157 <TabsPrimitive.Content 158 ref={ref} 159 className={cn( 160 "mt-2 ring-offset-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 dark:ring-offset-slate-950 dark:focus-visible:ring-slate-300", 161 className, 162 )} 163 {...props} 164 /> 165 )); 166 TabsContent.displayName = TabsPrimitive.Content.displayName; 167 168 export { Tabs, TabsContent, TabsList, TabsTrigger };