React

Select

트리거를 눌러 열리는 목록에서 값을 선택하는 컴포넌트입니다.

Installation

npx @seed-design/cli@latest add ui:select

Usage

import {
  SelectRoot,
  SelectTrigger,
  SelectContent,
  SelectGroup,
  SelectItem,
} from "seed-design/ui/select";
<SelectRoot defaultValue={["apple"]}>
  <SelectTrigger aria-label="과일" placeholder="과일을 선택하세요" />
  <SelectContent>
    <SelectGroup label="국산">
      <SelectItem value="apple" label="사과" />
      <SelectItem value="pear" label="배" />
    </SelectGroup>
    <SelectGroup label="수입산">
      <SelectItem value="banana" label="바나나" />
    </SelectGroup>
  </SelectContent>
</SelectRoot>
  • SelectRoot: 선택 값(value)과 열림 상태를 관리합니다.
  • SelectTrigger: 선택된 값 또는 placeholder를 표시하며, 클릭 시 목록을 엽니다.
  • SelectContent: 옵션 목록을 감싸는 플로팅 컨테이너입니다.
  • SelectGroup: 관련된 옵션들을 그룹으로 묶습니다. 모든 SelectItemSelectGroup 안에 있어야 합니다. label로 그룹의 제목을 표시할 수 있습니다.
  • SelectItem: 개별 옵션입니다. value가 필요하며, 선택되면 체크마크가 표시됩니다.

Props

SelectRoot

Prop

Type

label?React.ReactNode
indicator?React.ReactNode
showRequiredIndicator?boolean | undefined
description?React.ReactNode
errorMessage?React.ReactNode
hiddenSelectProps?SeedSelect.HiddenSelectProps | undefined
fieldRef?React.Ref<HTMLDivElement> | undefined
children?React.ReactNode
open?boolean | undefined
defaultOpen?boolean | undefined
onOpenChange?((open: boolean, details?: SelectOpenChangeDetails) => void) | undefined
defaultValue?string[] | undefined
onValueChange?((value: string[]) => void) | undefined
disabled?boolean | undefined
invalid?boolean | undefined
readOnly?boolean | undefined

SelectTrigger

Prop

Type

placeholder?React.ReactNode
prefixIcon?React.ReactNode

SelectContent

Prop

Type

positionerContainer?React.RefObject<HTMLElement | null> | undefined

SelectGroup

Prop

Type

label?React.ReactNode

SelectItem

Prop

Type

description?React.ReactNode
disabled?boolean | undefined
valuestring

Examples

Size

size로 트리거와 목록의 크기를 정합니다. (default: large)

responsive 사용 시 화면 너비에 따라 size가 자동으로 전환됩니다.

Groups

SelectGroup으로 옵션을 묶고, label로 그룹의 제목을 표시합니다. SelectGroup의 개수와 관계없이 모든 SelectItemSelectGroup 안에 있어야 합니다.

그룹이 두 개 이상이면 그룹 사이에 구분선이 자동으로 그려집니다.

Multiple Selection

SelectRootmultiple을 지정하면 여러 옵션을 선택할 수 있습니다. 옵션을 선택해도 목록이 닫히지 않으며, 이미 선택된 옵션을 다시 누르면 선택이 해제됩니다.

트리거에는 선택된 옵션들의 textValue", "로 이어져 표시됩니다. 이 문구는 Custom Value Format으로 바꿀 수 있습니다.

With Description

SelectItemdescription prop으로 옵션에 부가 설명을 추가합니다.

With Prefix Icon

SelectItemprefixIcon prop으로 옵션에 아이콘을 표시합니다.

1개의 옵션이 선택된 경우 해당 옵션의 아이콘이 트리거의 prefix 아이콘으로 표시됩니다. 선택된 옵션이 없거나, 선택된 옵션에 아이콘이 없거나, 여러 옵션이 선택된 경우 트리거에는 SelectTrigger에 지정한 prefixIcon이 표시됩니다.

Custom Item Label

SelectItemlabel에는 ReactNode를 넘길 수 있습니다. 이 노드는 목록의 옵션에만 렌더링됩니다.

SelectItemlabel로 string이 아닌 ReactNode를 지정하는 경우 트리거에는 SelectItemtextValue가 표시됩니다. textValuelabel이 string이면 label, 아니면 value입니다.

따라서, label이 string이 아닌 경우 textValue를 함께 지정하는 것을 권장합니다. textValue는 트리거에 표시되는 문구, 키보드로 타이핑해 옵션을 찾을 때 매칭되는 문자열(typeahead), 폼 제출용 native <option>의 텍스트로 쓰입니다. label로 string이 아닌 ReactNode를 전달하면서 textValue를 지정하지 않는 경우 이 값들은 모두 기본적으로 value로 설정되며, 개발 모드에서 경고가 출력됩니다.

typeahead 문자열만 변경하고자 하는 경우 typeaheadLabel을 사용하세요.

Disabled

SelectItemdisabled로 특정 옵션을, SelectRootdisabled로 Select 전체를 비활성화합니다.

Long List

옵션이 많으면 목록 안에서 스크롤됩니다. 목록의 최대 높이는 지정된 최대 높이와 트리거 주변에 남은 화면 공간 중 더 작은 값으로 정해지고, 노치와 홈 인디케이터 영역을 피해 배치됩니다.

목록은 현재 선택된 옵션이 보이는 위치로 스크롤된 상태에서 열립니다.

Placement

SelectRootplacement prop으로 목록의 위치를 설정합니다. 기본값은 "bottom"입니다.

Listening to Value Changes

valueonValueChange로 선택 값을 제어할 수 있습니다.

Controlled Open State

openonOpenChange로 목록의 열림 상태를 제어할 수 있습니다. 초기 상태만 지정하려면 defaultOpen을 사용하세요.

목록이 열리면 포커스가 목록으로 이동하고, 닫히면 트리거로 되돌아옵니다.

onOpenChange Details

onOpenChange 두 번째 인자로 details가 제공됩니다.

reason

열릴 때 (open: true)

  • "trigger": SelectTrigger 클릭 또는 SelectTrigger에 포커스된 상태에서 , , Enter, Space 키 사용

닫힐 때 (open: false)

  • "trigger": 목록이 열린 상태에서 SelectTrigger 클릭
  • "itemSelect": 옵션 선택
    • multiple인 경우 옵션을 선택해도 목록이 닫히지 않으므로 발생하지 않습니다.
  • "keyboardClose": 하이라이트된 옵션이 없는 상태에서 Enter 또는 Space 키 사용
  • "escapeKeyDown": ESC 키 사용
  • "interactOutside": 외부 영역 클릭
  • "focusOut": Tab 등으로 포커스가 목록 밖으로 이동
  • "cascadeDismiss": 상위 레이어 닫힘으로 인한 연쇄 닫힘

Custom Value Format

SelectRootformatValue prop으로 트리거에 표시되는 선택 값을 커스텀합니다. 기본적으로는, 선택된 옵션들의 textValue", "로 join하여 표시합니다. textValue의 기본값은 label이 string이면 label, 아닌 경우 value입니다.

formatValue가 받는 각 항목에는 label도 담겨 있으므로, ReactNode label을 트리거에 렌더링하고 싶다면 여기서 꺼내 쓰면 됩니다.

// 선택된 옵션 중 첫 번째 옵션의 label만 트리거에 표시
<SelectRoot formatValue={(items) => items[0]?.label} />

Intl.ListFormat을 사용하면 locale에 맞는 접속사로 목록을 조합할 수 있습니다.

Field Integration

label, description, errorMessage 등의 Field 관련 prop을 사용할 수 있습니다.

Form Integration

SelectRoot가 내부에서 렌더링하는 숨겨진 native <select>를 통해 폼 제출에 참여할 수 있습니다.

React Hook Form

value, onValueChange, invalid, errorMessage를 연결하면 React Hook FormuseController로 검증 상태를 제어할 수 있습니다.

Last updated on

On this page