Combobox
검색어와 선택 상태를 분리해 타입이 있는 옵션을 하나 또는 여러 개 선택해요.
검색어와 선택 상태를 분리해 타입이 있는 옵션을 하나 또는 여러 개 선택해요.
핵심 속성
| 속성 | 설명 |
|---|---|
| 상태 | 검색어와 선택 값은 서로 다른 축이에요. TRComboboxController가 값과 함께 TextEditingController, FocusNode를 소유하고, TRCombobox.controlled는 값만 호출하는 쪽에 넘기고 검색어는 controller가 계속 들고 있어요. |
| 필드 | 필드는 TRTextField라서 label, placeholder, helperText, errorText, uiSize, width가 그곳과 똑같이 동작해요. clearable을 켜면 검색어나 선택 값이 있을 때 뒤쪽 슬롯에 지우기 버튼이 나타나요. |
| 레이어 크기 | layerSize는 필드 width와 별개예요. 기본값은 선택지 레이어 전체 너비를 기준 요소에 맞추고, 높이는 콘텐츠에 따라 TRMeasurements.measureXl까지 늘려요. |
| 필터링 | optionsBuilder가 후보를 정하고 filterMode가 contains·startsWith·none 중 하나로 좁혀요. filter 콜백을 주면 filterMode보다 우선해요. 원격이나 비동기 optionsBuilder가 이미 결과를 확정한다면 none을 쓰세요. |
| 다중 선택 | TRMultiCombobox는 확정된 값을 필드 위에 삭제 가능한 칩으로 그리고, 하나 고를 때마다 검색어를 비워요. layout: TRComboboxLayout.grid를 주면 팝업이 목록 대신 2열 격자로 배치돼요. |
| 상호작용 | 화살표 키로 하이라이트를 옮기고 Enter로 확정하며 Escape로 팝업을 닫아요. autoHighlight는 화살표 키 없이도 Enter가 첫 일치 항목을 확정할지 정해요. enabled: false 옵션은 계속 보이되 흐리게 그려지고, Enter와 화살표 이동 모두에서 건너뛰어요. |
| 폼 | TRComboboxFormField와 TRMultiComboboxFormField는 FormField 하위 클래스라서 validator, onSaved, autovalidateMode, Form.reset이 평소대로 동작하고 errorText는 필드 상태가 채워줘요. |
선택지가 스크롤보다 입력이 빠를 만큼 길지만 확정되는 값은 반드시 그 목록에서 나와야 할 때 combobox를 쓰세요. 짧은 고정 목록에는 TRSelect를, 사용자가 입력한 자유 텍스트 자체가 답이 될 수 있다면 TRAutocomplete를 쓰세요.
설치
패키지를 추가한 뒤 공개 라이브러리를 가져오세요.
flutter pub add tinyrack_uiimport 'package:tinyrack_ui/tinyrack_ui.dart';플레이그라운드
사용법
import 'package:material_ui/material_ui.dart';
import 'package:tinyrack_ui/tinyrack_ui.dart';
TRCombobox<String>(
label: 'Channel',
placeholder: 'Choose a channel',
items: const [
TRComboboxItem(value: 'stable', label: 'Stable'),
TRComboboxItem(value: 'beta', label: 'Beta'),
],
onValueChange: selectChannel,
)예시
좁혀서 랙 하나 확정하기 고유 링크
입력하면 팝업이 좁혀지고, 확정된 값은 검색어와 별개로 유지돼요. 랙을 고르면 그 레이블이 필드에 다시 쓰여요.
크기 고유 링크
uiSize를 넘겨 옆에 놓인 TRTextField, TRSelect, TRButton과 높이를 맞추세요.
선택된 옵션과 비활성 옵션 고유 링크
enabled를 false로 둔 옵션은 팝업에 남아서 왜 쓸 수 없는지가 계속 보여요. 흐리게 그려지고 Enter와 화살표 이동 모두에서 건너뛰어요.
필터 의미 고유 링크
contains, startsWith, 기본 좁히기 없음을 비교해요. 비동기 `optionsBuilder`가 이미 보여줄 결과를 돌려준다면 none을 쓰세요.
다중 선택 칩과 격자 팝업 고유 링크
TRMultiCombobox는 확정된 값을 삭제 가능한 칩으로 그리고, 하나 고를 때마다 검색어를 비워요. 격자 레이아웃은 짧은 레이블을 2열에 담아요.
필수 선택과 복구 고유 링크
TRComboboxFormField는 오류를 errorText로 알리고 값이 확정되면 바로 지워요. 그래서 다시 제출하지 않아도 상태를 되돌릴 수 있어요.
제어 상태와 사용자 정의 필터 고유 링크
제어 생성자는 값을 호출하는 쪽에 넘기고 controller가 검색어를 들고 있어요. 기본 규칙으로 부족하면 filter 콜백이 filterMode를 대신해요.
팝업 너비와 레이어 고유 링크
Flutter에는 portal이나 positioner 같은 파트가 없어요. 팝업은 combobox 레이어에서 열리고 너비는 필드에서, `width`를 두지 않으면 small 오버레이 너비 토큰에서 가져와요.
키보드 선택 고유 링크
autoHighlight를 끄면 화살표 키로 행을 강조하기 전까지 Enter가 아무것도 확정하지 않아요. 지우기 버튼은 필드로 포커스를 돌려주므로 팝업이 열린 채로 남아요.
단일·다중 선택 필드 고유 링크
FormField 변형은 검색어와 타입이 있는 선택 값을 분리한 채 검증, 저장, 초기화에 참여해요.
API
TRCombobox 속성
| Prop | 타입 / 기본값 | 용도 |
|---|---|---|
items | List<TRComboboxItem<T>> · const [] | 옵션 원본을 제공해요. items나 optionsBuilder 중 하나는 반드시 채워야 해요. |
optionsBuilder | TRComboboxOptionsBuilder<T>? · null | 검색어에 대한 후보를 동기 또는 Future로 돌려줘요. filterMode가 none이 아니면 그 결과도 한 번 더 좁혀져요. |
filterMode | TRComboboxFilterMode · contains | contains나 startsWith로 옵션 레이블을 대소문자 구분 없이 비교하고, none이면 좁히지 않아요. 비교에 toLowerCase를 쓰기 때문에 React useFilter의 collator와 달리 악센트까지 무시하지는 않아요. |
filter | TRComboboxFilter<T>? · null | filterMode 대신 직접 만든 판정 함수를 써요. 전달되는 검색어는 이미 공백이 제거되고 소문자로 바뀐 상태예요. |
autoHighlight | bool · true | 첫 일치 항목을 준비 상태로 둬서 Enter가 바로 확정하게 해요. false로 두면 화살표 키를 먼저 눌러야 해요. 바탕이 되는 RawAutocomplete가 항상 유효한 하이라이트 인덱스를 유지하기 때문에 React 기본값과 달리 여기서는 true가 기본이에요. |
clearable, clearSemanticLabel | bool · false, String · 'Clear' | 검색어나 선택 값이 있을 때 지우기 버튼을 보여줘요. 지우면 검색어를 비우고 onValueChange로 null을 알린 뒤 필드로 포커스를 돌려줘요. |
controller, defaultValue, value | TRComboboxController<T>?, T?, T? | 상태 모델을 정해요. defaultValue는 비제어 생성자의 초기값이고, value는 TRCombobox.controlled에 필수이며, controller는 둘 중 어느 쪽과도 함께 쓸 수 있어요. |
onQueryChange, onValueChange | ValueChanged<String>?, ValueChanged<T?>? | 검색어 편집과 확정된 선택을 따로 알려줘요. 지우기 버튼을 누르면 onValueChange가 null로도 호출돼요. |
layout | TRComboboxLayout · list | 팝업을 1열 목록이나 2열 격자로 그려요. |
enabled, readOnly | bool · true, bool · false | 상호작용을 막거나, 포커스는 되지만 검색어를 편집할 수 없는 필드로 유지해요. 둘 다 지우기 버튼을 감춰요. |
label, placeholder, helperText, errorText | String? · null | 바탕이 되는 TRTextField를 통해 필드와 검증 상태를 설명해요. |
uiSize, width | TRUiSize · TRUiSize.md, double? · null | 컨트롤 크기와 선택적인 고정 필드 너비를 정해요. 팝업 크기는 layerSize로 지정하세요. |
layerSize | TRLayerSize · match anchor / content height ≤ measureXl | 단일 선택, 다중 선택, FormField 변형의 선택지 레이어 전체 크기를 정해요. |
TRMultiCombobox 속성
| Prop | 타입 / 기본값 | 용도 |
|---|---|---|
defaultValue, value | List<T> · const [], List<T>? | 확정된 값들을 담아요. value는 TRMultiCombobox.controlled에 필수이고, 이를 주면 위젯이 완전한 제어 모드가 돼요. |
onValueChange | ValueChanged<List<T>>? · null | 선택, 칩 삭제, 지우기 뒤마다 전체 선택 목록을 알려줘요. 이미 선택된 값을 다시 고르면 해제돼요. |
controller | TRMultiComboboxController<T>? · null | 값들과 공유 검색어 필드를 소유해요. clear는 값만 비우므로 직접 제어할 때는 textEditingController도 함께 비우세요. |
항목과 열거형
| Prop | 타입 / 기본값 | 용도 |
|---|---|---|
TRComboboxItem.value, label | T · required, String · required | 타입이 있는 값과, 팝업에 표시되고 확정 시 필드에 다시 써지는 텍스트를 담아요. |
TRComboboxItem.enabled | bool · true | 옵션을 선택할 수 없게 표시해요. 팝업에는 그대로 남고 muted 텍스트 색으로 그려지며 키보드 이동에서 건너뛰어요. |
TRComboboxItem.leading, trailing | Widget? · null | 옵션 레이블 양옆에 아이콘을 배치해요. |
TRComboboxLayout | list, grid | 팝업 배치를 고르는 열거형이에요. grid는 높이가 고정된 행을 2열로 배치해요. |
TRComboboxFilterMode | contains, startsWith, none | 옵션 원본에 적용할 기본 좁히기 규칙을 고르는 열거형이에요. |
Controller와 폼 필드
| Prop | 타입 / 기본값 | 용도 |
|---|---|---|
TRComboboxController | ChangeNotifier | value, select, clear와 함께 소유한 textEditingController, focusNode를 노출해요. 만든 위젯에서 dispose하세요. |
TRMultiComboboxController | ChangeNotifier | values, replace, toggle, clear를 노출해요. values는 수정할 수 없는 뷰라서 직접 바꾸지 말고 목록을 교체하세요. |
TRComboboxFormField | FormField<T> | 타입이 있는 선택 값으로 검증과 저장 콜백에 참여하고 errorText를 필드로 다시 전달해요. |
TRMultiComboboxFormField | FormField<List<T>> | 값 목록에 대해 같은 일을 해요. validator로 최소 한 개 선택을 요구할 수 있어요. |