select.tsx
1 import * as React from "react" 2 import * as SelectPrimitive from "@radix-ui/react-select" 3 import { Check, ChevronDown } from "lucide-react" 4 5 import { cn } from "@/lib/utils" 6 7 const Select = SelectPrimitive.Root 8 9 const SelectGroup = SelectPrimitive.Group 10 11 const SelectValue = SelectPrimitive.Value 12 13 const SelectTrigger = React.forwardRef< 14 React.ElementRef<typeof SelectPrimitive.Trigger>, 15 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> 16 >(({ className, children, ...props }, ref) => ( 17 <SelectPrimitive.Trigger 18 ref={ref} 19 className={cn( 20 "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", 21 className 22 )} 23 {...props} 24 > 25 {children} 26 <SelectPrimitive.Icon asChild> 27 <ChevronDown className="h-4 w-4 opacity-50" /> 28 </SelectPrimitive.Icon> 29 </SelectPrimitive.Trigger> 30 )) 31 SelectTrigger.displayName = SelectPrimitive.Trigger.displayName 32 33 const SelectContent = React.forwardRef< 34 React.ElementRef<typeof SelectPrimitive.Content>, 35 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> 36 >(({ className, children, position = "popper", ...props }, ref) => ( 37 <SelectPrimitive.Portal> 38 <SelectPrimitive.Content 39 ref={ref} 40 className={cn( 41 "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 42 position === "popper" && 43 "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", 44 className 45 )} 46 position={position} 47 {...props} 48 > 49 <SelectPrimitive.Viewport 50 className={cn( 51 "p-1", 52 position === "popper" && 53 "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]" 54 )} 55 > 56 {children} 57 </SelectPrimitive.Viewport> 58 </SelectPrimitive.Content> 59 </SelectPrimitive.Portal> 60 )) 61 SelectContent.displayName = SelectPrimitive.Content.displayName 62 63 const SelectLabel = React.forwardRef< 64 React.ElementRef<typeof SelectPrimitive.Label>, 65 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> 66 >(({ className, ...props }, ref) => ( 67 <SelectPrimitive.Label 68 ref={ref} 69 className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} 70 {...props} 71 /> 72 )) 73 SelectLabel.displayName = SelectPrimitive.Label.displayName 74 75 const SelectItem = React.forwardRef< 76 React.ElementRef<typeof SelectPrimitive.Item>, 77 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> 78 >(({ className, children, ...props }, ref) => ( 79 <SelectPrimitive.Item 80 ref={ref} 81 className={cn( 82 "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 83 className 84 )} 85 {...props} 86 > 87 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> 88 <SelectPrimitive.ItemIndicator> 89 <Check className="h-4 w-4" /> 90 </SelectPrimitive.ItemIndicator> 91 </span> 92 93 <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText> 94 </SelectPrimitive.Item> 95 )) 96 SelectItem.displayName = SelectPrimitive.Item.displayName 97 98 const SelectSeparator = React.forwardRef< 99 React.ElementRef<typeof SelectPrimitive.Separator>, 100 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> 101 >(({ className, ...props }, ref) => ( 102 <SelectPrimitive.Separator 103 ref={ref} 104 className={cn("-mx-1 my-1 h-px bg-muted", className)} 105 {...props} 106 /> 107 )) 108 SelectSeparator.displayName = SelectPrimitive.Separator.displayName 109 110 export { 111 Select, 112 SelectGroup, 113 SelectValue, 114 SelectTrigger, 115 SelectContent, 116 SelectLabel, 117 SelectItem, 118 SelectSeparator, 119 }