Skip to Content

Select

옵션 목록에서 선택하는 드롭다운 컴포넌트


개요

Select 컴포넌트는 Radix UI의 Select Primitive를 기반으로 구축된 드롭다운 선택 컴포넌트입니다. 키보드 네비게이션과 완벽한 접근성을 제공합니다.

주요 특징

  • Radix UI 기반: 검증된 headless 컴포넌트
  • 키보드 네비게이션: 완벽한 키보드 지원
  • 접근성 우선: WCAG 2.1 AA 준수
  • 검색 가능: 타이핑으로 옵션 검색
  • TypeScript: 완벽한 타입 지원

설치

npx @vortex/cli add select

기본 사용법

import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, } from "@vortex/ui-foundation"; export default function App() { return ( <Select> <SelectTrigger className="w-[180px]"> <SelectValue placeholder="옵션 선택" /> </SelectTrigger> <SelectContent> <SelectItem value="option1">옵션 1</SelectItem> <SelectItem value="option2">옵션 2</SelectItem> <SelectItem value="option3">옵션 3</SelectItem> </SelectContent> </Select> ); }

컴포넌트 구조

Select는 여러 하위 컴포넌트로 구성됩니다.

<Select> <SelectTrigger> <SelectValue /> </SelectTrigger> <SelectContent> <SelectItem /> </SelectContent> </Select>

언제 사용하는가

✅ 권장 사용 사례

  • 단일 선택: 여러 옵션 중 하나 선택
  • 카테고리 선택: 제품 카테고리, 태그 등
  • 설정 변경: 언어, 테마, 정렬 기준 등
  • 필터링: 목록 필터링 옵션
  • 폼 입력: 국가, 직업, 연령대 등

실전 예제

폼에서 사용

<form className="space-y-4"> <div> <label htmlFor="country" className="block text-sm font-medium mb-2"> 국가 </label> <Select> <SelectTrigger id="country"> <SelectValue placeholder="국가 선택" /> </SelectTrigger> <SelectContent> <SelectItem value="kr">대한민국</SelectItem> <SelectItem value="us">미국</SelectItem> <SelectItem value="jp">일본</SelectItem> </SelectContent> </Select> </div> </form>

언제 사용하지 말아야 하는가

상황대신 사용할 컴포넌트
2-3개 옵션<RadioGroup>
다중 선택<Checkbox>
On/Off 토글<Switch>
텍스트 입력<Input>
날짜 선택<DatePicker>

Advanced Usage

Controlled 컴포넌트

import { useState } from "react"; function ControlledSelect() { const [value, setValue] = useState(""); return ( <Select value={value} onValueChange={setValue}> <SelectTrigger> <SelectValue placeholder="선택하세요" /> </SelectTrigger> <SelectContent> <SelectItem value="option1">옵션 1</SelectItem> <SelectItem value="option2">옵션 2</SelectItem> </SelectContent> </Select> ); }

Disabled 옵션

<Select> <SelectTrigger> <SelectValue placeholder="선택하세요" /> </SelectTrigger> <SelectContent> <SelectItem value="option1">옵션 1</SelectItem> <SelectItem value="option2" disabled> 옵션 2 (비활성) </SelectItem> <SelectItem value="option3">옵션 3</SelectItem> </SelectContent> </Select>

그룹화

import { SelectGroup, SelectLabel } from "@vortex/ui-foundation"; <Select> <SelectTrigger> <SelectValue placeholder="과일 선택" /> </SelectTrigger> <SelectContent> <SelectGroup> <SelectLabel>과일</SelectLabel> <SelectItem value="apple">사과</SelectItem> <SelectItem value="banana">바나나</SelectItem> </SelectGroup> <SelectGroup> <SelectLabel>채소</SelectLabel> <SelectItem value="carrot">당근</SelectItem> <SelectItem value="tomato">토마토</SelectItem> </SelectGroup> </SelectContent> </Select>;

접근성 (Accessibility)

Select 컴포넌트는 WCAG 2.1 AA 기준을 준수합니다.

ARIA Attributes

자동으로 제공:

  • role="combobox": Radix UI가 자동 설정
  • aria-expanded: 드롭다운 상태 자동 설정
  • aria-controls: 콘텐츠와 자동 연결

키보드 네비게이션

  • Space/Enter: 드롭다운 열기/닫기
  • Arrow Up/Down: 옵션 탐색
  • Home/End: 처음/마지막 옵션으로 이동
  • Esc: 드롭다운 닫기
  • 타이핑: 옵션 검색

Best Practices

1. 명확한 레이블

// ✅ Good <label htmlFor="language">언어</label> <Select> <SelectTrigger id="language"> <SelectValue placeholder="언어 선택" /> </SelectTrigger> </Select> // ❌ Bad: 레이블 없음 <Select>...</Select>

2. 적절한 Placeholder

// ✅ Good: 선택 안내 <SelectValue placeholder="국가를 선택하세요" /> // ❌ Bad: 모호한 문구 <SelectValue placeholder="선택" />

3. 옵션 개수 고려

// ✅ Good: 4개 이상일 때 Select 사용 <Select> <SelectContent> {countries.map((country) => ( <SelectItem key={country.code} value={country.code}> {country.name} </SelectItem> ))} </SelectContent> </Select> // ❌ Bad: 2-3개는 RadioGroup 사용

TypeScript

import { Select, SelectProps } from "@vortex/ui-foundation"; interface CustomSelectProps { label: string; options: Array<{ value: string; label: string }>; value?: string; onValueChange?: (value: string) => void; } function CustomSelect({ label, options, value, onValueChange, }: CustomSelectProps) { return ( <div> <label className="block text-sm font-medium mb-2">{label}</label> <Select value={value} onValueChange={onValueChange}> <SelectTrigger> <SelectValue placeholder="선택하세요" /> </SelectTrigger> <SelectContent> {options.map((option) => ( <SelectItem key={option.value} value={option.value}> {option.label} </SelectItem> ))} </SelectContent> </Select> </div> ); }

성능 최적화

많은 옵션 처리

import { useMemo } from "react"; function LargeSelect({ items }: { items: string[] }) { const memoizedItems = useMemo( () => items.map((item) => ( <SelectItem key={item} value={item}> {item} </SelectItem> )), [items] ); return ( <Select> <SelectTrigger> <SelectValue /> </SelectTrigger> <SelectContent>{memoizedItems}</SelectContent> </Select> ); }

관련 컴포넌트

  • RadioGroup: 2-3개 옵션 선택
  • Checkbox: 다중 선택
  • Combobox: 검색 가능한 선택
  • Input: 텍스트 입력

참고 자료


지원 및 피드백

문제가 발생하거나 개선 제안이 있으신가요?

Last updated on