Lynx

Select

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

Engine ≥ 3.9<overlay>
사용 가능 버전@seed-design/[email protected], @seed-design/[email protected]
Lynx 예제를 불러오는 중입니다.

Installation

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

Usage

SelectContent는 native overlay, 위치 계산, 표시 수명과 긴 목록의 scroll viewport를 함께 소유합니다.

import {
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectRoot,
  SelectTrigger,
} from "@/components/ui/select";

export function App() {
  return (
    <view style={{ width: "240px" }}>
      <SelectRoot defaultValue={["apple"]}>
        <SelectTrigger accessibility-label="과일" placeholder="과일을 선택하세요" />
        <SelectContent>
          <SelectGroup>
            <SelectItem value="apple" label="사과" />
            <SelectItem value="banana" label="바나나" />
            <SelectItem value="cherry" label="체리" />
          </SelectGroup>
        </SelectContent>
      </SelectRoot>
    </view>
  );
}
  • SelectRootvalue/defaultValueopen/defaultOpen을 관리합니다. multiple일 때는 항목을 탭해도 목록을 유지하고 선택을 toggle합니다.
  • SelectTrigger는 선택 값 또는 placeholder를 표시하고 탭으로 목록을 열고 닫습니다. SelectRoot의 문자열 label 또는 accessibility-label은 trigger의 기본 접근성 이름으로 사용됩니다.
  • SelectContent는 선택된 항목이 보이도록 목록을 스크롤하고, trigger 너비·화면 여유 공간·safe area에 맞춰 목록을 배치합니다.
  • SelectGroup은 관련 항목을 묶습니다. 여러 그룹 사이에는 구분선이 표시되고 label은 그룹 제목을 만듭니다.
  • SelectItem은 label, 선택적 description, prefix icon과 기본 checkmark indicator를 조합합니다. selectedIndicator로 checkmark를 교체할 수 있습니다.

낮은 수준의 조합이 필요하면 Select namespace의 Root, Trigger, Value, Placeholder, PrefixIcon, SuffixIcon, Content, ScrollArea, Group, GroupLabel, Item, ItemPrefixIcon, ItemBody, ItemLabel, ItemDescription, ItemIndicator를 사용하세요. 같은 API는 SelectRoot, SelectTrigger처럼 Select 접두어가 붙은 flat export로도 제공합니다.

Props

SelectRoot

Prop

Type

label?React.ReactNode
labelWeight?"medium" | "bold" | undefined
indicator?React.ReactNode
showRequiredIndicator?boolean | undefined
description?React.ReactNode
errorMessage?React.ReactNode
fieldRef?React.Ref<NodesRef> | undefined
accessibility-label?string | undefined
value?string[] | undefined
defaultValue?string[] | undefined
onValueChange?((value: string[]) => void) | undefined
multiple?boolean | undefined
open?boolean | undefined
defaultOpen?boolean | undefined
onOpenChange?((open: boolean, details: SelectOpenChangeDetails) => void) | undefined
disabled?boolean | undefined
readOnly?boolean | undefined
invalid?boolean | undefined
required?boolean | undefined
placement?Placement | undefined
gutter?number | undefined
overflowPadding?number | undefined
formatValue?((items: SelectSelectedItem[]) => React.ReactNode) | undefined
size?"medium" | "large" | "responsive" | undefined
style?CSSProperties | undefined
children?React.ReactNode
className?string | undefined

SelectTrigger

Prop

Type

placeholder?React.ReactNode
prefixIcon?React.ReactElement<LynxIconElementProps, string | React.JSXElementConstructor<any>> | undefined
suffixIcon?React.ReactElement<LynxIconElementProps, string | React.JSXElementConstructor<any>> | undefined
style?CSSProperties | undefined
className?string | undefined
bindtap?EventHandler<BaseTouchEvent<Target>> | undefined
main-thread:bindtap?EventHandler<BaseTouchEvent<Element>> | undefined

SelectContent

Prop

Type

style?CSSProperties | undefined
children?React.ReactNode
className?string | undefined

SelectGroup

Prop

Type

label?React.ReactNode
style?CSSProperties | undefined
children?React.ReactNode
className?string | undefined

SelectItem

Prop

Type

labelReact.ReactNode
description?React.ReactNode
selectedIndicator?React.ReactNode
prefixIcon?React.ReactElement<LynxIconElementProps, string | React.JSXElementConstructor<any>> | undefined
disabled?boolean | undefined
readOnly?boolean | undefined
style?CSSProperties | undefined
className?string | undefined
bindtap?EventHandler<BaseTouchEvent<Target>> | undefined
main-thread:bindtap?EventHandler<BaseTouchEvent<Element>> | undefined
valuestring
textValue?string | undefined

Examples

Size

size로 trigger와 목록의 크기를 정합니다. 기본값은 large이고, responsive는 native runtime의 화면 폭이 1280 이상이면 medium, 그 외에는 large로 해석합니다.

Lynx 예제를 불러오는 중입니다.

Groups

SelectGroup으로 옵션을 묶고 label로 그룹 제목을 표시합니다. 두 번째 그룹부터는 그룹 사이에 구분선이 추가됩니다.

Lynx 예제를 불러오는 중입니다.

Multiple Selection

multiple을 지정하면 선택한 옵션을 다시 탭해 해제할 수 있습니다. 다중 선택 중에는 목록이 닫히지 않으며 trigger에는 기본적으로 선택된 textValue", "로 연결되어 표시됩니다.

Lynx 예제를 불러오는 중입니다.

With Description

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

Lynx 예제를 불러오는 중입니다.

With Prefix Icon

SelectItemprefixIcon으로 옵션 앞에 아이콘을 표시합니다. 단일 옵션이 선택되면 해당 아이콘이 trigger prefix에 표시됩니다. 선택이 없거나 여러 옵션이 선택된 경우에는 SelectTriggerprefixIcon fallback을 사용합니다.

Lynx 예제를 불러오는 중입니다.

Custom Item Label

label에는 복합 JSX를 전달할 수 있습니다. 복합 label을 사용할 때는 trigger에 표시할 문자열과 옵션 접근성 이름을 위해 textValue를 함께 지정하세요.

Lynx 예제를 불러오는 중입니다.

Disabled

SelectItemdisabled는 특정 옵션을, SelectRootdisabled는 Select 전체를 비활성화합니다. readOnly도 목록을 열거나 선택을 바꾸지 않습니다.

Lynx 예제를 불러오는 중입니다.

Long List

목록은 상하 8px 패딩을 포함한 내용 높이만큼 표시하며, 별도의 최소 높이는 없습니다. 최대 높이는 480px이고 trigger 주위의 남은 공간과 safe area에 맞춰 제한합니다. 내용이 이 높이를 넘을 때만 스크롤됩니다.

열릴 때 선택된 옵션이 화면 밖에 있으면 보이는 데 필요한 만큼만 스크롤합니다. 이미 보이는 옵션을 선택하거나 목록이 닫히는 중에는 스크롤 위치를 바꾸지 않습니다.

Lynx 예제를 불러오는 중입니다.

Placement

placement로 목록 위치를 정합니다. 기본값은 bottom이며, 공간이 부족하면 native positioner가 반대쪽으로 뒤집거나 경계 안으로 이동합니다.

Lynx 예제를 불러오는 중입니다.

Listening to Value Changes

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

Lynx 예제를 불러오는 중입니다.

Controlled Open State

openonOpenChange로 목록 상태를 제어합니다. 초기 상태만 지정하려면 defaultOpen을 사용하세요.

Lynx 예제를 불러오는 중입니다.

onOpenChange Details

onOpenChange의 두 번째 인자는 상태를 바꾼 이유를 제공합니다. 열림 이유는 trigger이고, 닫힘 이유는 trigger, itemSelect, interactOutside, dismiss입니다.

Lynx 예제를 불러오는 중입니다.

Custom Value Format

formatValue로 trigger에 표시할 선택 값을 바꿉니다. callback은 value, label, textValue, prefixIcon을 담은 선택 item 배열을 받습니다.

Lynx 예제를 불러오는 중입니다.

Field Integration

SelectRoot는 기존 Lynx Field를 조합하므로 label, description, errorMessage, invalid, requiredshowRequiredIndicator를 지원합니다. 오류 메시지가 있으면 description 대신 오류 메시지를 표시합니다.

Lynx 예제를 불러오는 중입니다.

Form Integration

Lynx에는 HTML <form>과 native <select> 제출 모델이 없습니다. 선택 값은 onValueChange로 앱 state에 저장하고, 제출 action의 payload에 그 값을 넣으세요.

React Hook Form

현재 Lynx React 런타임과 이 예제 경로에는 React Hook Form 통합·dependency가 없습니다. value/onValueChangeinvalid/errorMessage를 앱 상태 및 native request action에 직접 연결하세요.

웹 버전과의 차이

Lynx Select는 native overlay 위에 렌더링됩니다. HTML DOM의 focus와 form 모델 대신 native tap, overlay dismissal, accessibility-* 속성과 앱 상태를 사용합니다.

항목ReactLynx
Trigger 조합asChild와 DOM button 조합native SelectTrigger를 사용
위치와 긴 목록DOM positioner와 scroll areaSelectContent가 native overlay, 위치 계산, scroll viewport를 함께 소유
열림 이유keyboard/focus를 포함한 DOM 상호작용trigger, itemSelect, interactOutside, dismiss
키보드focus, typeahead, Escape로 닫기현재 Lynx Select에서 지원하지 않음
접근성DOM ARIA id 연결SelectRoot 또는 SelectTriggeraccessibility-label과 item의 native 접근성 속성 사용
반응형 size웹 viewport 기반native runtime 폭을 사용

Lynx 미지원 기능

기능웹 대응앱 대안
hidden native select, name, form 제출<select>FormDataonValueChange로 앱 state를 갱신하고 제출 action payload에 그 값을 넣기
browser validationrequired의 native form validation앱 제출 action에서 state를 검증하고 invalid/errorMessage를 제어하기
React Hook Form 예제useController와 HTML form 통합현재 예제 경로에는 React Hook Form 통합·dependency가 없으므로 value/onValueChange 및 앱 상태·요청 action으로 연결하기
DOM focus, typeahead, keyboard navigationfocus/keyboard APInative tap과 host의 접근성 탐색 흐름 사용
DOM ARIA idaria-describedby, aria-controls각 trigger와 복합 item에 필요한 accessibility-* 속성을 직접 지정

Last updated on

목차