본문으로 건너뛰기
Amineslab UI

Component

Combobox

검색 가능한 단일 선택 컨트롤입니다.

Playground

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

PC 1280px
Controls

트리거 높이와 여백

미선택 상태 문구

검색창 안내 문구

검색 결과가 없을 때 표시

PC 팝오버 정렬

Code
import { useState } from 'react'

import { Combobox, type ControlSize } from '@amineslab/ui'

const people = [
    { value: 'mina', label: '민아', keywords: ['designer', 'design'] },
    { value: 'jun', label: '준', keywords: ['engineer', 'frontend'] },
    { value: 'sora', label: '소라', keywords: ['product'] },
];

function ComboboxExample({ size = 'md', opaque = false, variant = 'filled', invalid = false, disabled = false, placeholder = '담당자 선택', searchPlaceholder = '이름 검색', searchLabel = '담당자 검색', emptyLabel = '검색 결과가 없습니다.', align = 'start', } = {}) {
    const [value, setValue] = useState('');
    return (<div className="grid gap-2">
      <Combobox size={size as ControlSize} opaque={opaque} variant={variant === 'outline' ? 'outline' : 'filled'} invalid={invalid} disabled={disabled} placeholder={placeholder} searchPlaceholder={searchPlaceholder} searchLabel={searchLabel} emptyLabel={emptyLabel} align={align === 'end' ? 'end' : align === 'center' ? 'center' : 'start'} options={people} value={value} onValueChange={setValue} aria-label="담당자"/>
    </div>);
}

export default function ExamplePreview() {
  return (<ComboboxExample {...({"size":"md","searchLabel":"담당자 검색","opaque":false,"variant":"filled","invalid":false,"disabled":false,"placeholder":"담당자 선택","searchPlaceholder":"이름 검색","emptyLabel":"검색 결과가 없습니다.","align":"start"} as const)}/>)
}

Props

@amineslab/ui에서 Combobox를 가져옵니다.

import { Combobox } from '@amineslab/ui'

Combobox

검색·선택·반응형 표면을 함께 소유합니다.

NameTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Button과 같은 트리거 크기입니다.
options*readonly ComboboxOption[]-검색 가능한 선택지입니다.
valuestring-controlled 선택값입니다.
defaultValuestring-uncontrolled 초기값입니다.
onValueChange(value: string) => void-선택값을 전달합니다.
placeholderstring'선택하세요'트리거와 모바일 제목에 표시합니다.
searchPlaceholderstring'검색…'검색 입력 안내입니다.
searchLabelstring'검색'검색 입력의 접근 가능한 이름입니다. placeholder와 별개로 제공합니다.
disabledbooleanfalse트리거와 선택을 막습니다.
invalidbooleanfalse필드 오류 상태를 표시합니다.
aria-requiredAriaAttributes["aria-required"]-필수 입력 상태를 실제 트리거에 전달합니다.
onBlurFocusEventHandler<HTMLButtonElement>-트리거가 포커스를 잃을 때 호출합니다. RHF touched 처리에 사용합니다.
variant'filled' | 'outline'filled공통 필드 표면 표현입니다. focus·hover는 중립 elevation을 사용합니다.
opaquebooleanfalseelevation 레이어 아래 불투명한 테마 바탕을 추가합니다. hover·focus·invalid 표현은 유지합니다.

Examples

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

공통 필드 표면

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

투명 바탕
불투명 바탕
Outline + 불투명 바탕
<Combobox options={options} />

<Combobox options={options} opaque />

<Combobox options={options} variant="outline" opaque />

PC Popover · 모바일 Drawer

같은 API가 넓은 화면에서는 트리거 아래 Popover, 모바일과 중첩 시트에서는 검색 가능한 Drawer로 바뀝니다.

import { useState } from 'react'

import { Combobox, type ControlSize } from '@amineslab/ui'

const people = [
    { value: 'mina', label: '민아', keywords: ['designer', 'design'] },
    { value: 'jun', label: '준', keywords: ['engineer', 'frontend'] },
    { value: 'sora', label: '소라', keywords: ['product'] },
];

function ComboboxExample({ size = 'md', opaque = false, variant = 'filled', invalid = false, disabled = false, placeholder = '담당자 선택', searchPlaceholder = '이름 검색', searchLabel = '담당자 검색', emptyLabel = '검색 결과가 없습니다.', align = 'start', } = {}) {
    const [value, setValue] = useState('');
    return (<div className="grid gap-2">
      <Combobox size={size as ControlSize} opaque={opaque} variant={variant === 'outline' ? 'outline' : 'filled'} invalid={invalid} disabled={disabled} placeholder={placeholder} searchPlaceholder={searchPlaceholder} searchLabel={searchLabel} emptyLabel={emptyLabel} align={align === 'end' ? 'end' : align === 'center' ? 'center' : 'start'} options={people} value={value} onValueChange={setValue} aria-label="담당자"/>
    </div>);
}

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

ComboboxField로 사용하기

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

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

import { useState } from 'react'

import { ComboboxField } from '@amineslab/ui'

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

function ComboboxFieldExample() {
    const [value, setValue] = useState('');
    return (<ComboboxField label="담당자" description={fieldDescription} required value={value} onValueChange={setValue} options={[
            { value: 'mina', label: '미나' },
            { value: 'jisu', label: '지수' },
        ]}/>);
}

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

사용 기준

권장하는 사용
  • 넓은 화면에서는 트리거 아래 Popover 안에 검색과 결과를 표시하고, 모바일과 이미 열린 시트 안에서는 같은 API가 Drawer로 전환됩니다.
  • 결과 선택은 즉시 확정하고 시트를 닫으며, 긴 결과는 본문만 스크롤합니다.
피해야 할 사용
  • 겉모양만으로 사용을 결정하지 마세요.
  • 의미와 키보드 동작, 모바일에서의 흐름을 함께 확인하세요.

접근성

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

  • Arrow Up / Down: 검색 결과를 이동합니다.
  • Enter: 현재 결과를 선택합니다.
  • Escape: Popover 또는 Drawer를 닫습니다.