Select

Stable

미리 정의한 옵션 중 하나를 선택하는 필드입니다.

DESIGN & DEVELOPMENTUpdated Sep 2026

Overview

Select는 여러 개의 선택지 중 하나 또는 여러 개의 옵션을 선택할 수 있는 풍부한 드롭다운 컨트롤입니다. Seed Design 표준을 준수하여 아이템별 보조 설명, 접두사 아이콘, 실시간 검색, 다중 선택 태그/요약 모드, 그룹 구분자를 모두 지원합니다.

LIVE PREVIEW마우스 클릭 또는 키보드(방향키, Enter, Esc)로 조작 가능
선택된 상태값"seoul"
TSX / CSS
<Select
  size="md"
  searchable={true}
  clearable={true}
  placeholder="여행지를 선택하세요"
  value={selectedValue}
  onValueChange={(val) => setSelectedValue(val)}
  options={[
    { value: 'seoul', label: '서울', description: '수도이자 문화 중심지', prefixIcon: <Landmark /> },
    { value: 'busan', label: '부산', description: '대표 해양 도시', prefixIcon: <MapPin /> },
    ...
  ]}
/>

WAI-ARIA role="combobox" 및 role="listbox" 표준을 준수합니다. 키보드 화살표 키(↑, ↓)로 탐색하고, Enter/Space 키로 선택하며, Esc 키로 드롭다운을 즉시 닫을 수 있습니다. 또한 SSR 환경 및 표준 폼 전송과의 100% 호환성을 보장합니다.

Anatomy

번호구성 요소역할
1Label필드 레이블. htmlId와 aria-labelledby로 연결되는 폼 컨트롤 제목
2Trigger Container현재 선택된 값이나 placeholder를 보여주고 클릭/엔터 시 드롭다운을 토글하는 외곽 영역
3Prefix Icon트리거 또는 개별 아이템 좌측에 위치하는 문맥 아이콘
4Value / Tags / Summary단일 선택된 텍스트, 다중 선택된 개별 제거 가능 태그 칩, 또는 요약 문구
5Clear Button & Chevron값 초기화 X 버튼 및 열림 상태에 따라 180도 회전하는 화살표 인디케이터
6Dropdown Popover실시간 검색창, 카테고리 헤더, 아이템 목록 및 체크 인디케이터를 포함하는 팝오버
7Helper / Error Messagearia-describedby와 연동되는 가이드라인 또는 유효성 검사 안내

Variants

단순 텍스트 옵션부터 메타데이터가 포함된 풍부한 옵션, 검색 필터링 및 다중 선택(태그·요약)까지 용도에 맞는 변형을 제공합니다.

Variant미리보기 (Preview)특징 및 권장 적용 맥락
기본 단일 선택
접두사 아이콘이나 부가 설명 없이 순수 텍스트로 구성된 가장 표준적인 단일 선택
메타데이터 확장
접두사 아이콘(prefixIcon)과 보조 설명(description)을 함께 노출해 선택 맥락 강화
실시간 검색
선택지가 많은 경우(10개 이상) 드롭다운 상단 검색창으로 실시간 필터링 제공
다중 선택 (Tags)
복수 항목을 개별 태그 칩으로 나열하고 각 칩의 X 버튼으로 즉시 제거 가능
다중 선택 (Summary)
"서울 외 2개"처럼 간결한 요약형 텍스트로 표시하여 좁은 화면이나 모바일에 최적화

Sizes

주변 입력 필드 및 버튼과의 조화를 위해 3가지 표준 크기를 제공합니다. 기본값은 md(40px)입니다.

Size높이 (Height)미리보기 (Preview)권장 적용 맥락
sm32px
밀도 높은 데이터 테이블 내부 필터, 좁은 사이드바 패널 제어
md40px (기본값)
대부분의 표준 폼 양식, 설정 다이얼로그 및 기본 입력 뷰
lg48px
히어로 검색 폼, 터치 조작 편의성이 최우선인 모바일 인터페이스

States

상호작용 및 폼 유효성 검증 상태를 시각적 테두리와 색상으로 명확히 구분합니다.

상태 (State)미리보기 (Preview)동작 및 가이드
Default
사용자의 선택을 기다리는 기본 활성 인터랙션 상태
Error
유효성 검증 실패 시 강조 테두리(Red)와 aria-invalid 적용
ReadOnly
선택값 열람은 허용되나 드롭다운 열림 및 값 수정은 차단 (폼 전송 포함)
Disabled
조작 및 폼 전송에서 완전히 제외되는 비활성화 상태

Guidelines

권장해요

옵션이 5개 이상이거나 화면 공간을 절약해야 할 때 Select를 사용합니다.

목록이 10개 이상으로 길어지면 searchable을 활성화하여 빠른 탐색을 지원합니다.

옵션 간 성격이 다를 때는 group 프로퍼티로 논리적으로 분류합니다.

다중 선택 시 모바일 환경이나 좁은 공간에서는 summary 모드를 활용합니다.

피해주세요

선택지가 2~3개 이하로 적고 즉시 비교가 필요할 때는 Select 대신 Radio 또는 Switch를 고려하세요.

placeholder만으로 Label을 대신하지 않습니다. 항상 명확한 레이블을 제공합니다.

선택 가능한 옵션이 없을 때 빈 드롭다운만 방치하지 않고 적절한 안내 문구를 표시합니다.

API

PropTypeDefaultDescription
optionsSelectItem[]필수value, label, description, prefixIcon, disabled, group을 포함하는 옵션 배열
valuestring | string[]undefined현재 선택된 값 (단일: 문자열, 다중: 문자열 배열)
defaultValuestring | string[]undefined초기 기본 선택 값
placeholderstringundefined선택된 값이 없을 때 표시할 안내 문구
multiplebooleanfalse다중 선택 모드 활성화 여부
displayMode'tags' | 'summary''tags'다중 선택 시 트리거 내 표시 방식 (개별 칩 vs 요약 텍스트)
searchablebooleanfalse드롭다운 상단에 실시간 필터 검색창 노출 여부
clearablebooleanfalse선택된 값을 한 번에 지울 수 있는 X 버튼 표시 여부
size'sm' | 'md' | 'lg''md'컨트롤의 높이 및 패딩 크기
prefixIconReactNodeundefined트리거 좌측에 표시할 공통 접두사 아이콘
onValueChange(val: string | string[]) => voidundefined선택 값 변경 시 트리거되는 직관적인 값 변경 콜백
onChange(e: any) => voidundefined기존 리액트 이벤트 핸들러와의 완벽한 하위 호환성을 제공하는 콜백

Code Example

TSX / CSS
import { useState } from 'react';
import { Field, Select, type SelectItem } from '@/components/ui';
import { Landmark, MapPin, TreePine } from 'lucide-react';

const destinations: SelectItem[] = [
  { value: 'seoul', label: '서울', description: '수도 및 문화 중심', prefixIcon: <Landmark /> },
  { value: 'busan', label: '부산', description: '해양 관광 도시', prefixIcon: <MapPin /> },
  { value: 'jeju', label: '제주도', description: '힐링 자연 휴양지', prefixIcon: <TreePine /> },
];

export function BookingForm() {
  const [selectedCities, setSelectedCities] = useState<string[]>(['seoul']);

  return (
    <Field
      label="희망 여행지"
      description="방문하고 싶은 도시를 선택하세요."
      required
    >
      <Select
        multiple={true}
        displayMode="tags"
        searchable={true}
        clearable={true}
        options={destinations}
        value={selectedCities}
        onValueChange={(val) => setSelectedCities(val as string[])}
        placeholder="도시를 선택하세요"
      />
    </Field>
  );
}
작은 원칙이 좋은 경험을 만듭니다.맨 위로