본문으로 건너뛰기
언어

Selectstandard

목록에서 값 하나를 고르는 선택 상자(select)입니다. shadcn base-nova 의 stock 아이템이며 Base UI `Select` 위에 서 있습니다. 브라우저 기본 목록을 쓰려면 `native-select`, 검색이 필요하면 `combobox` 를 씁니다.

설치

pnpm
pnpm dlx shadcn@4.23.0 add @uikit/select

Default

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>  )}