select.tsx
1 import * as React from "react"; 2 import * as SelectPrimitive from "@radix-ui/react-select"; 3 import { Check, ChevronDown, ChevronUp } from "lucide-react"; 4 import { cn } from "../../lib/util"; 5 6 const Select = SelectPrimitive.Root; 7 8 const SelectGroup = SelectPrimitive.Group; 9 10 const SelectValue = SelectPrimitive.Value; 11 12 const SelectTrigger = React.forwardRef< 13 React.ElementRef<typeof SelectPrimitive.Trigger>, 14 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> 15 >(({ className, children, ...props }, ref) => ( 16 <SelectPrimitive.Trigger 17 ref={ref} 18 className={cn( 19 "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 [&>span]:line-clamp-1", 20 className 21 )} 22 {...props} 23 > 24 {children} 25 <SelectPrimitive.Icon asChild> 26 <ChevronDown className="h-4 w-4 opacity-50" /> 27 </SelectPrimitive.Icon> 28 </SelectPrimitive.Trigger> 29 )); 30 SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; 31 32 const SelectScrollUpButton = React.forwardRef< 33 React.ElementRef<typeof SelectPrimitive.ScrollUpButton>, 34 React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton> 35 >(({ className, ...props }, ref) => ( 36 <SelectPrimitive.ScrollUpButton 37 ref={ref} 38 className={cn( 39 "flex cursor-default items-center justify-center py-1", 40 className 41 )} 42 {...props} 43 > 44 <ChevronUp className="h-4 w-4" /> 45 </SelectPrimitive.ScrollUpButton> 46 )); 47 SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; 48 49 const SelectScrollDownButton = React.forwardRef< 50 React.ElementRef<typeof SelectPrimitive.ScrollDownButton>, 51 React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton> 52 >(({ className, ...props }, ref) => ( 53 <SelectPrimitive.ScrollDownButton 54 ref={ref} 55 className={cn( 56 "flex cursor-default items-center justify-center py-1", 57 className 58 )} 59 {...props} 60 > 61 <ChevronDown className="h-4 w-4" /> 62 </SelectPrimitive.ScrollDownButton> 63 )); 64 SelectScrollDownButton.displayName = 65 SelectPrimitive.ScrollDownButton.displayName; 66 67 const SelectContent = React.forwardRef< 68 React.ElementRef<typeof SelectPrimitive.Content>, 69 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> 70 >(({ className, children, position = "popper", ...props }, ref) => ( 71 <SelectPrimitive.Portal> 72 <SelectPrimitive.Content 73 ref={ref} 74 className={cn( 75 "relative z-50 max-h-96 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", 76 position === "popper" && 77 "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", 78 className 79 )} 80 position={position} 81 {...props} 82 > 83 <SelectScrollUpButton /> 84 <SelectPrimitive.Viewport 85 className={cn( 86 "p-1", 87 position === "popper" && 88 "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]" 89 )} 90 > 91 {children} 92 </SelectPrimitive.Viewport> 93 <SelectScrollDownButton /> 94 </SelectPrimitive.Content> 95 </SelectPrimitive.Portal> 96 )); 97 SelectContent.displayName = SelectPrimitive.Content.displayName; 98 99 const SelectLabel = React.forwardRef< 100 React.ElementRef<typeof SelectPrimitive.Label>, 101 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> 102 >(({ className, ...props }, ref) => ( 103 <SelectPrimitive.Label 104 ref={ref} 105 className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} 106 {...props} 107 /> 108 )); 109 SelectLabel.displayName = SelectPrimitive.Label.displayName; 110 111 const SelectItem = React.forwardRef< 112 React.ElementRef<typeof SelectPrimitive.Item>, 113 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> 114 >(({ className, children, ...props }, ref) => ( 115 <SelectPrimitive.Item 116 ref={ref} 117 className={cn( 118 "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", 119 className 120 )} 121 {...props} 122 > 123 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> 124 <SelectPrimitive.ItemIndicator> 125 <Check className="h-4 w-4" /> 126 </SelectPrimitive.ItemIndicator> 127 </span> 128 129 <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText> 130 </SelectPrimitive.Item> 131 )); 132 SelectItem.displayName = SelectPrimitive.Item.displayName; 133 134 const SelectSeparator = React.forwardRef< 135 React.ElementRef<typeof SelectPrimitive.Separator>, 136 React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> 137 >(({ className, ...props }, ref) => ( 138 <SelectPrimitive.Separator 139 ref={ref} 140 className={cn("-mx-1 my-1 h-px bg-muted", className)} 141 {...props} 142 /> 143 )); 144 SelectSeparator.displayName = SelectPrimitive.Separator.displayName; 145 146 export { 147 Select, 148 SelectGroup, 149 SelectValue, 150 SelectTrigger, 151 SelectContent, 152 SelectLabel, 153 SelectItem, 154 SelectSeparator, 155 SelectScrollUpButton, 156 SelectScrollDownButton, 157 };