Selectstandard
목록에서 값 하나를 고르는 선택 상자(select)입니다. shadcn base-nova 의 stock 아이템이며 Base UI `Select` 위에 서 있습니다. 브라우저 기본 목록을 쓰려면 `native-select`, 검색이 필요하면 `combobox` 를 씁니다.
설치
pnpm
pnpm dlx shadcn@4.23.0 add @uikit/selectDefault
select-example.tsx
"use client"
import { Example, ExampleWrapper,} from "@/components/example"import { Button } from "@/components/ui/button"import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog"import { Field, FieldDescription, FieldError, FieldLabel,} from "@/components/ui/field"import { Input } from "@/components/ui/input"import { Item, ItemContent, ItemDescription, ItemTitle,} from "@/components/ui/item"import { NativeSelect, NativeSelectOption,} from "@/components/ui/native-select"import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue,} from "@/components/ui/select"import { ChartBarIcon, ChartLineIcon, ChartPieIcon } from "lucide-react"
export default function SelectExample() { return ( <ExampleWrapper> <SelectBasic /> <SelectSides /> <SelectWithIcons /> <SelectWithGroups /> <SelectLargeList /> <SelectMultiple /> <SelectSizes /> <SelectPlan /> <SelectWithButton /> <SelectItemAligned /> <SelectWithField /> <SelectInvalid /> <SelectInline /> <SelectDisabled /> <SelectInDialog /> </ExampleWrapper> )}
function SelectBasic() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes" }, { label: "Pineapple", value: "pineapple" }, ] return ( <Example title="Basic"> <Select items={items}> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
function SelectSides() { const items = [ { label: "Select", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, ] return ( <Example title="Sides" containerClassName="col-span-2"> <div className="flex flex-wrap justify-center gap-2"> {( [ "inline-start", "left", "top", "bottom", "right", "inline-end", ] as const ).map((side) => ( <Select key={side} items={items}> <SelectTrigger aria-label="Select option" className="w-28 capitalize"> <SelectValue placeholder={side.replace("-", " ")} /> </SelectTrigger> <SelectContent side={side} alignItemWithTrigger={false}> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> ))} </div> </Example> )}
function SelectWithIcons() { const items = [ { label: ( <> <ChartLineIcon /> Chart Type </> ), value: null, }, { label: ( <> <ChartLineIcon /> Line </> ), value: "line", }, { label: ( <> <ChartBarIcon /> Bar </> ), value: "bar", }, { label: ( <> <ChartPieIcon /> Pie </> ), value: "pie", }, ] return ( <Example title="With Icons"> <div className="flex flex-col gap-4"> <Select items={items}> <SelectTrigger aria-label="Select option" size="sm"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <Select items={items}> <SelectTrigger aria-label="Select option" size="default"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </div> </Example> )}
function SelectWithGroups() { const fruits = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, ] const vegetables = [ { label: "Carrot", value: "carrot" }, { label: "Broccoli", value: "broccoli" }, { label: "Spinach", value: "spinach" }, ] const allItems = [ { label: "Select a fruit", value: null }, ...fruits, ...vegetables, ] return ( <Example title="With Groups & Labels"> <Select items={allItems}> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> <SelectLabel>Fruits</SelectLabel> {fruits.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> <SelectSeparator /> <SelectGroup> <SelectLabel>Vegetables</SelectLabel> {vegetables.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
function SelectLargeList() { const items = [ { label: "Select an item", value: null }, ...Array.from({ length: 100 }).map((_, i) => ({ label: `Item ${i}`, value: `item-${i}`, })), ] return ( <Example title="Large List"> <Select items={items}> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
function SelectSizes() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, ] return ( <Example title="Sizes"> <div className="flex flex-col gap-4"> <Select items={items}> <SelectTrigger aria-label="Select option" size="sm"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <Select items={items}> <SelectTrigger aria-label="Select option" size="default"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </div> </Example> )}
function SelectWithButton() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, ] return ( <Example title="With Button"> <div className="flex flex-col gap-4"> <div className="flex items-center gap-2"> <Select items={items}> <SelectTrigger aria-label="Select option" size="sm"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <Button variant="outline" size="sm"> Submit </Button> </div> <div className="flex items-center gap-2"> <Select items={items}> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <Button variant="outline">Submit</Button> </div> </div> </Example> )}
function SelectItemAligned() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes", disabled: true }, { label: "Pineapple", value: "pineapple" }, ] return ( <Example title="Item Aligned"> <Select items={items}> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent alignItemWithTrigger={true}> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value} disabled={item.disabled} > {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
function SelectWithField() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes" }, { label: "Pineapple", value: "pineapple" }, ] return ( <Example title="With Field"> <Field> <FieldLabel htmlFor="select-fruit">Favorite Fruit</FieldLabel> <Select items={items}> <SelectTrigger id="select-fruit"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <FieldDescription> Choose your favorite fruit from the list. </FieldDescription> </Field> </Example> )}
function SelectInvalid() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes" }, { label: "Pineapple", value: "pineapple" }, ] return ( <Example title="Invalid"> <div className="flex flex-col gap-4"> <Select items={items}> <SelectTrigger aria-label="Select option" aria-invalid="true"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <Field data-invalid> <FieldLabel htmlFor="select-fruit-invalid">Favorite Fruit</FieldLabel> <Select items={items}> <SelectTrigger id="select-fruit-invalid" aria-invalid> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <FieldError errors={[{ message: "Please select a valid fruit." }]} /> </Field> </div> </Example> )}
function SelectInline() { const items = [ { label: "Filter", value: null }, { label: "All", value: "all" }, { label: "Active", value: "active" }, { label: "Inactive", value: "inactive" }, ] return ( <Example title="Inline with Input & NativeSelect"> <div className="flex items-center gap-2"> <Input placeholder="Search..." className="flex-1" /> <Select items={items}> <SelectTrigger aria-label="Select option" className="w-[140px]"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> <NativeSelect aria-label="Select option" className="w-[140px]"> <NativeSelectOption value="">Sort by</NativeSelectOption> <NativeSelectOption value="name">Name</NativeSelectOption> <NativeSelectOption value="date">Date</NativeSelectOption> <NativeSelectOption value="status">Status</NativeSelectOption> </NativeSelect> </div> </Example> )}
function SelectDisabled() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes", disabled: true }, { label: "Pineapple", value: "pineapple" }, ] return ( <Example title="Disabled"> <Select items={items} disabled> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value} disabled={item.disabled} > {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
const plans = [ { name: "Starter", description: "Perfect for individuals getting started.", }, { name: "Professional", description: "Ideal for growing teams and businesses.", }, { name: "Enterprise", description: "Advanced features for large organizations.", },]
function SelectPlan() { return ( <Example title="Subscription Plan"> <Select defaultValue={plans[0]} itemToStringValue={(plan: (typeof plans)[number]) => plan.name} > <SelectTrigger aria-label="Select option" className="h-auto! w-72"> <SelectValue> {(value: (typeof plans)[number]) => <SelectPlanItem plan={value} />} </SelectValue> </SelectTrigger> <SelectContent> <SelectGroup> {plans.map((plan) => ( <SelectItem key={plan.name} value={plan}> <SelectPlanItem plan={plan} /> </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
function SelectPlanItem({ plan }: { plan: (typeof plans)[number] }) { return ( <Item size="xs" className="w-full p-0"> <ItemContent className="gap-0 normal-case"> <ItemTitle className="font-sans">{plan.name}</ItemTitle> <ItemDescription className="text-xs font-normal tracking-normal"> {plan.description} </ItemDescription> </ItemContent> </Item> )}
function SelectMultiple() { const items = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes" }, { label: "Pineapple", value: "pineapple" }, { label: "Strawberry", value: "strawberry" }, { label: "Watermelon", value: "watermelon" }, ] return ( <Example title="Multiple Selection"> <Select items={items} multiple defaultValue={[]}> <SelectTrigger aria-label="Select option" className="w-72"> <SelectValue> {(value: string[]) => { if (value.length === 0) { return "Select fruits" } if (value.length === 1) { return items.find((item) => item.value === value[0])?.label } return `${value.length} fruits selected` }} </SelectValue> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </Example> )}
function SelectInDialog() { const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Blueberry", value: "blueberry" }, { label: "Grapes", value: "grapes" }, { label: "Pineapple", value: "pineapple" }, ] return ( <Example title="In Dialog"> <Dialog> <DialogTrigger render={<Button variant="outline" />}> Open Dialog </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Select Example</DialogTitle> <DialogDescription> Use the select below to choose a fruit. </DialogDescription> </DialogHeader> <Select items={items}> <SelectTrigger aria-label="Select option"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {items.map((item) => ( <SelectItem key={item.value} value={item.value}> {item.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </DialogContent> </Dialog> </Example> )}