
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
selectuiDropdown select primitive — single-select with optional groups, per-item descriptions, Radix UI popover mode, and zero-JS styled NativeSelect for lightweight/mobile use.
Also available for Vue ->Select is the headless primitive for flat options. Advance Select is the searchable combobox. Cascade and Tree selectors are designed specifically for hierarchical and nested datasets.
| Component | Role | Use when |
|---|---|---|
| Selectcurrent Short, flat option lists (< 20 items) where typing to filter is unnecessary. | Primitive Dropdown | |
| AdvanceSelect Large datasets requiring fuzzy search, multi-select tag pills, or remote option filtering. | Searchable Combobox | |
| CascadeSelect Sequential multi-level drilldowns (e.g. Country > State > City, Category > Subcategory). | Hierarchical Picker | |
| TreeSelect Deeply nested taxonomy structures, folder trees, or parent-child permission nodes. | Tree Picker |
$pnpm dlx shadcn@latest add https://uipkge.dev/r/react/select.json$npx shadcn@latest add https://uipkge.dev/r/react/select.json$yarn dlx shadcn@latest add https://uipkge.dev/r/react/select.json$bunx shadcn@latest add https://uipkge.dev/r/react/select.jsonnpx shadcn@latest add @uipkge-react/selectInstalls to:components/ui/select/| Name | Type / Values | Default | Required |
|---|---|---|---|
size | 'sm' | 'default' | 'lg' | default | optional |
state | 'default' | 'error' | 'success' | default | optional |
loading | boolean | false | optional |
Type aliases from this item's source — use them to shape the data you pass in.
NativeSelectOptioninterface NativeSelectOption {
label: string
value: string | number
disabled?: boolean
}'use client'
import * as React from 'react'
import * as SelectPrimitive from '@radix-ui/react-select'
import { Check, ChevronDown, ChevronUp, Loader } from 'lucide-react'
import { cn } from '@/lib/utils'
const Select = SelectPrimitive.Root
const SelectGroup = SelectPrimitive.Group
const SelectValue = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Value>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>
>((props, ref) => <SelectPrimitive.Value ref={ref} data-slot="select-value" {...props} />)
SelectValue.displayName = SelectPrimitive.Value.displayName
const triggerSizeClasses = {
sm: 'h-8 text-sm px-2.5 py-1.5',
default: 'h-9 text-sm px-3 py-2',
lg: 'h-11 text-base px-4 py-2.5',
}
const triggerStateClasses = {
default: 'border-input dark:hover:bg-input/50',
error:
'border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
success: 'border-success focus-visible:border-success',
}
export interface SelectTriggerProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> {
size?: 'sm' | 'default' | 'lg'
state?: 'default' | 'error' | 'success'
loading?: boolean
}
const SelectTrigger = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Trigger>, SelectTriggerProps>(
({ className, children, size = 'default', state = 'default', loading = false, disabled, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
data-uipkge=""
data-slot="select-trigger"
data-size={size}
data-state-value={state}
disabled={disabled || loading}
aria-busy={loading}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex w-full items-center justify-between gap-2 rounded-md border bg-transparent text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
triggerSizeClasses[size],
triggerStateClasses[state],
className,
)}
{...props}
>
{children}
{loading ? (
<Loader className="size-4 animate-spin opacity-50" aria-hidden="true" />
) : (
<SelectPrimitive.Icon asChild>
<ChevronDown className="size-4 opacity-50" aria-hidden="true" />
</SelectPrimitive.Icon>
)}
</SelectPrimitive.Trigger>
),
)
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
data-uipkge=""
data-slot="select-scroll-up-button"
className={cn('flex cursor-default items-center justify-center py-1', className)}
{...props}
>
{children ?? <ChevronUp className="size-4" aria-hidden="true" />}
</SelectPrimitive.ScrollUpButton>
))
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
data-uipkge=""
data-slot="select-scroll-down-button"
className={cn('flex cursor-default items-center justify-center py-1', className)}
{...props}
>
{children ?? <ChevronDown className="size-4" aria-hidden="true" />}
</SelectPrimitive.ScrollDownButton>
))
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = 'popper', ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
data-uipkge=""
data-slot="select-content"
position={position}
className={cn(
'bg-popover text-popover-foreground motion-safe:data-[state=open]:animate-in motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=open]:ease-emphasized motion-safe:data-[state=open]:blur-in-2 motion-safe:data-[state=closed]:blur-out-2 motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=closed]:zoom-out-95 motion-safe:data-[state=open]:zoom-in-95 motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=left]:slide-in-from-right-2 motion-safe:data-[side=right]:slide-in-from-left-2 motion-safe:data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-md border shadow-md motion-safe:data-[state=closed]:duration-[var(--dur-exit)] motion-safe:data-[state=open]:duration-200',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
className,
)}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
'p-1',
position === 'popper' &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1',
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
data-uipkge=""
data-slot="select-label"
className={cn('text-muted-foreground px-2 py-1.5 text-xs', className)}
{...props}
/>
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
data-uipkge=""
data-slot="select-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className,
)}
{...props}
>
<span className="absolute right-2 flex size-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="size-4" aria-hidden="true" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
const SelectItemText = SelectPrimitive.ItemText
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
data-uipkge=""
data-slot="select-separator"
className={cn('bg-border pointer-events-none -mx-1 my-1 h-px', className)}
{...props}
/>
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
export {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectItemText,
SelectLabel,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
}
'use client'
import * as React from 'react'
import { ChevronDown } from 'lucide-react'
import { cn } from '@/lib/utils'
export interface NativeSelectOption {
label: string
value: string | number
disabled?: boolean
}
export interface NativeSelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
options?: (NativeSelectOption | string)[]
sizeVariant?: 'sm' | 'md' | 'lg'
selectClassName?: string
}
const sizeClasses: Record<string, string> = {
sm: 'h-8 text-xs pl-2.5 pr-8',
md: 'h-9 text-sm pl-3 pr-9',
lg: 'h-11 text-base pl-4 pr-10',
}
const iconSizes: Record<string, string> = {
sm: 'size-3.5 right-2.5',
md: 'size-4 right-3',
lg: 'size-5 right-3.5',
}
export const NativeSelect = React.forwardRef<HTMLSelectElement, NativeSelectProps>(
({ className, selectClassName, options, sizeVariant = 'md', disabled, children, ...props }, ref) => {
return (
<div
data-uipkge=""
data-slot="native-select-wrapper"
className={cn('relative inline-flex w-full items-center', className)}
>
<select
ref={ref}
data-slot="native-select"
disabled={disabled}
className={cn(
'border-input bg-background w-full appearance-none rounded-md border shadow-xs transition-[color,box-shadow]',
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] focus-visible:outline-none',
'disabled:bg-muted/30 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
sizeClasses[sizeVariant],
selectClassName,
)}
{...props}
>
{options && options.length > 0
? options.map((opt) => {
const isString = typeof opt === 'string'
const value = isString ? opt : opt.value
const label = isString ? opt : opt.label
const isDisabled = !isString && opt.disabled
return (
<option key={String(value)} value={value} disabled={isDisabled}>
{label}
</option>
)
})
: children}
</select>
<ChevronDown
data-slot="native-select-icon"
aria-hidden="true"
className={cn(
'text-muted-foreground pointer-events-none absolute transition-opacity',
disabled && 'opacity-50',
iconSizes[sizeVariant],
)}
/>
</div>
)
},
)
NativeSelect.displayName = 'NativeSelect'
export {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectItemText,
SelectLabel,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
} from './select'
export { NativeSelect, type NativeSelectProps, type NativeSelectOption } from './NativeSelect'
Raw manifest:https://uipkge.dev/r/react/select.json