tabs.tsx 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. "use client";
  2. import * as React from "react";
  3. import { cva, type VariantProps } from "class-variance-authority";
  4. import { Tabs as TabsPrimitive } from "radix-ui";
  5. import { cn } from "@/lib/utils";
  6. function Tabs({
  7. className,
  8. orientation = "horizontal",
  9. ...props
  10. }: React.ComponentProps<typeof TabsPrimitive.Root>) {
  11. return (
  12. <TabsPrimitive.Root
  13. data-slot="tabs"
  14. data-orientation={orientation}
  15. orientation={orientation}
  16. className={cn(
  17. "group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
  18. className,
  19. )}
  20. {...props}
  21. />
  22. );
  23. }
  24. const tabsListVariants = cva(
  25. "rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
  26. {
  27. variants: {
  28. variant: {
  29. default: "bg-muted",
  30. line: "gap-1 bg-transparent",
  31. },
  32. },
  33. defaultVariants: {
  34. variant: "default",
  35. },
  36. },
  37. );
  38. function TabsList({
  39. className,
  40. variant = "default",
  41. ...props
  42. }: React.ComponentProps<typeof TabsPrimitive.List> &
  43. VariantProps<typeof tabsListVariants>) {
  44. return (
  45. <TabsPrimitive.List
  46. data-slot="tabs-list"
  47. data-variant={variant}
  48. className={cn(tabsListVariants({ variant }), className)}
  49. {...props}
  50. />
  51. );
  52. }
  53. function TabsTrigger({
  54. className,
  55. ...props
  56. }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
  57. return (
  58. <TabsPrimitive.Trigger
  59. data-slot="tabs-trigger"
  60. className={cn(
  61. "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
  62. "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
  63. "data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
  64. "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
  65. className,
  66. )}
  67. {...props}
  68. />
  69. );
  70. }
  71. function TabsContent({
  72. className,
  73. ...props
  74. }: React.ComponentProps<typeof TabsPrimitive.Content>) {
  75. return (
  76. <TabsPrimitive.Content
  77. data-slot="tabs-content"
  78. className={cn("flex-1 outline-none", className)}
  79. {...props}
  80. />
  81. );
  82. }
  83. export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };