본문으로 건너뛰기
Amineslab UI

Component

Select

짧은 목록에서 항목 하나를 고릅니다. 넓은 화면에서는 popover, 좁은 화면에서는 Drawer로 엽니다.

Playground

옵션을 조절하며 화면과 사용 코드를 함께 확인하세요.

PC 1280px
Controls

elevation 아래 불투명 바탕

control 높이

필드 표면

선택 전 trigger에 보여 줄 placeholder

오류 상태

비활성

Code
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@amineslab/ui'

export default function ExamplePreview() {
  return ((<Select required={false} disabled={false}>
      <SelectTrigger aria-invalid={undefined} aria-label="역할" size={"md"} variant={"filled"} opaque={false}>
        <SelectValue placeholder={"역할 선택"}/>
      </SelectTrigger>
      <SelectContent position={"popper"}>
        <SelectItem value="viewer">뷰어</SelectItem>
        <SelectItem value="editor">편집자</SelectItem>
        <SelectItem value="owner">소유자</SelectItem>
      </SelectContent>
    </Select>))
}

Props

import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
  SelectGroup,
  SelectLabel,
  // ...
} from '@amineslab/ui'

Select

선택값과 화면 크기별 열림 방식을 관리하는 root입니다.

NameTypeDefaultDescription
valuestring-외부에서 제어하는 선택값입니다.
defaultValuestring-내부 상태로 관리할 때의 초기 선택값입니다.
onValueChange(value: string) => void-선택값이 바뀔 때 호출합니다.
disabledbooleanfalse선택을 막습니다.
openboolean-외부에서 제어하는 열림 상태입니다.
onOpenChange(open: boolean) => void-open 상태 변경 콜백입니다.

SelectTrigger

현재 선택값을 보여 주고 목록을 여는 trigger입니다. 좁은 화면에서는 Drawer를 엽니다.

NameTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'입력 요소의 높이와 내부 여백입니다.
variant'filled' | 'outline''filled'trigger의 배경과 테두리 스타일입니다.
requiredbooleanfalsetrigger에 aria-required를 전달합니다.
aria-invalidboolean | "grammar" | "spelling"-오류 시각 상태와 ARIA 상태를 전달합니다.
invalidbooleanfalse오류 테두리를 표시하며 focus·open 상태에서도 유지합니다. aria-invalid도 함께 전달합니다.
opaquebooleanfalseelevation 레이어 아래 불투명한 테마 바탕을 추가합니다. hover·focus·invalid 표현은 유지합니다.

SelectValue

NameTypeDefaultDescription
placeholderReactNode-선택값이 없을 때 표시할 내용입니다.

SelectContent

NameTypeDefaultDescription
position'item-aligned' | 'popper''popper'데스크톱 목록의 정렬 방식입니다.

SelectItem

NameTypeDefaultDescription
value*string-제출할 선택값입니다.
disabledbooleanfalse선택할 수 없게 합니다.

Examples

자주 쓰는 조합을 살펴보고, 필요한 예시의 코드를 펼쳐 확인하세요.

공통 필드 표면

variant는 filled·outline 표현을, opaque는 elevation 아래의 불투명 바탕을 정합니다. focus와 hover는 중립 elevation을 사용하고 invalid 테두리는 포커스 중에도 유지합니다. NumberInput·PhoneInput·PasswordInput은 Input의 아이콘·문자열·ReactNode 슬롯을 상속합니다. SelectField에서는 같은 표면 props를 직접 지정하거나 triggerProps로 세부 설정할 수 있습니다.

투명 바탕
불투명 바탕
Outline + 불투명 바탕
<Select>
  <SelectTrigger><SelectValue placeholder="역할 선택" /></SelectTrigger>
  <SelectContent><SelectItem value="viewer">뷰어</SelectItem></SelectContent>
</Select>

<Select>
  <SelectTrigger opaque><SelectValue placeholder="역할 선택" /></SelectTrigger>
  <SelectContent><SelectItem value="viewer">뷰어</SelectItem></SelectContent>
</Select>

<Select>
  <SelectTrigger variant="outline" opaque><SelectValue placeholder="역할 선택" /></SelectTrigger>
  <SelectContent><SelectItem value="viewer">뷰어</SelectItem></SelectContent>
</Select>

Sizes

import { type ComponentPropsWithoutRef } from 'react'

import { cn } from '@amineslab/ui/utils'

import { type ControlSize, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@amineslab/ui'

const controlSizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const satisfies readonly ControlSize[];

const sizes = controlSizes;

function ExampleStack({ className, compact = false, fullWidth = false, ...props }: ComponentPropsWithoutRef<'div'> & {
    compact?: boolean;
    fullWidth?: boolean;
}) {
    return (<div {...props} className={cn('grid', compact ? 'w-auto gap-2' : fullWidth ? 'w-full gap-4' : 'w-full max-w-[360px] gap-3', className)}/>);
}

export default function ExamplePreview() {
  return ((<ExampleStack>
          {sizes.map((size) => (<Select key={size}>
              <SelectTrigger aria-label={`정렬 ${size}`} size={size}>
                <SelectValue placeholder={`정렬 ${size}`}/>
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="recent">최근 순</SelectItem>
                <SelectItem value="name">이름 순</SelectItem>
              </SelectContent>
            </Select>))}
        </ExampleStack>))
}

SelectField로 사용하기

SelectField는 기본 입력에 label·required·description·error를 함께 제공합니다. FormStack 안에 직접 넣으며 FormField로 다시 감싸지 않습니다.

라벨·설명·필수 표시를 Field가 함께 처리합니다.

import { useState } from 'react'

import { SelectField } from '@amineslab/ui'

const fieldDescription = '라벨·설명·필수 표시를 Field가 함께 처리합니다.';

function SelectFieldExample() {
    const [value, setValue] = useState('');
    return (<SelectField label="역할" description={fieldDescription} required value={value} onValueChange={setValue} options={[
            { value: 'viewer', label: '뷰어' },
            { value: 'editor', label: '편집자' },
        ]}/>);
}

export default function ExamplePreview() {
  return (<SelectFieldExample />)
}

사용 기준

권장하는 사용
  • 선택지가 익숙하고 모두 한 번에 로드될 때 사용합니다.
  • 긴 목록이나 검색이 필요하면 별도 combobox 패턴을 사용합니다.
피해야 할 사용
  • 검색이 필요한 긴 목록에는 사용하지 마세요.

접근성

화면에 맞는 이름을 제공하고, 키보드만으로 작업을 마칠 수 있는지 확인하세요.

  • Tab: select로 포커스 이동
  • Enter 또는 Space: 목록 열기
  • Arrow keys: 데스크톱 목록에서 option 이동
  • Escape: 목록 닫기