OptionList
선택지 목록 — OptionItem 을 세로로 쌓는 묶음
목차
OptionList 는 OptionItem 을 세로로 쌓은 선택지 목록입니다. 목록이 맡는 것은 배치뿐입니다 — 줄을 위에서
아래로 놓고, 각 줄이 목록의 폭을 채웁니다. 어느 줄이 골라졌는지, 하나만 고를 수 있는지 여럿을 고를 수 있는지는
호출자의 몫이고, 각 줄이 자기 selection 과 selected 를 말합니다.
기본 사용법 (Basic Usage)#
OptionList(
children: [
OptionItem(
label: const Text('최신순'),
selected: sort == Sort.latest,
onPressed: () => setState(() => sort = Sort.latest),
),
OptionItem(
label: const Text('인기순'),
selected: sort == Sort.popular,
onPressed: () => setState(() => sort = Sort.popular),
),
],
)
OptionList(
children: [
OptionItem(
label: const Text('최신순'),
selected: sort == Sort.latest,
onPressed: () => setState(() => sort = Sort.latest),
),
OptionItem(
label: const Text('인기순'),
selected: sort == Sort.popular,
onPressed: () => setState(() => sort = Sort.popular),
),
],
)
폭은 부모가 정합니다 — 목록은 받은 폭을 채우고 높이는 줄의 합이 정합니다.
Live Preview#
코드 보기
class OptionListDefaultExample extends StatelessComponent {
const OptionListDefaultExample({super.key});
@override
Component build(BuildContext context) {
return OptionList(
children: [
OptionItem(
label: const Text('최신순'),
selected: true,
onPressed: () {},
),
OptionItem(
label: const Text('인기순'),
onPressed: () {},
),
OptionItem(
label: const Text('낮은 가격순'),
onPressed: () {},
),
],
);
}
}
class OptionListDefaultExample extends StatelessWidget {
const OptionListDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return OptionList(
children: [
OptionItem(
label: const Text('최신순'),
selected: true,
onPressed: () {},
),
OptionItem(
label: const Text('인기순'),
onPressed: () {},
),
OptionItem(
label: const Text('낮은 가격순'),
onPressed: () {},
),
],
);
}
}
구조 (Anatomy)#
[ OptionItem ]
[ OptionItem ]
[ OptionItem ]
| 부분 | 역할 | 슬롯 |
|---|---|---|
| 줄 | 선택지 한 줄 — OptionItem | children |
Figma: CoUI 라이브러리 파일의
OptionList 페이지
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 바텀시트나 패널 안에서
OptionItem여러 줄을 한 목록으로 놓을 때
대신 다른 컴포넌트를 사용하세요:
Props / Parameters#
W 는 Flutter의 Widget / Web의 Jaspr Component입니다.
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children |
List<W> |
필수 | 위에서 아래로 쌓을 줄 — 보통 OptionItem |
optionListStyle |
CoreOptionListStyle? |
null |
모든 chrome 이 지나는 단일 슬롯 (아래 표 참고) |
CoreOptionListStyle 필드#
| 필드 | 타입 | 설명 |
|---|---|---|
spacing |
double? |
Space between two rows (logical px, pre-scaling). null → [defaultSpacing]. |
스타일 시스템 (Style System)#
optionListStyle#
- 시맨틱 / behaviour: 위젯 파라미터로 직접 (
children) - chrome / dimensional:
CoreOptionListStyle한 곳으로
| 부분 | 필드 | 기본값 |
|---|---|---|
| 간격 | spacing | 0 — 줄 사이 |
줄 사이 간격은 간격 사다리 위의 값이라 밀도(CoreDensity)가 한 칸 옮깁니다.
Resolve chain
CoreOptionListStyle.defaultX // 기본값
→ CoreOptionListTheme.style // 프로젝트 공통
→ widget.optionListStyle // 인스턴스별
사용 예
CoreComponentTheme(
optionList: CoreOptionListTheme(
style: CoreOptionListStyle(spacing: CoreSpace.space4),
),
)
빠른 오버라이드 (Chain)
OptionList(children: items).withStyle(
const CoreOptionListStyle(spacing: CoreSpace.space4),
)
동작 스펙 (Behavior)#
배치#
- 줄을 위에서 아래로 쌓고, 줄 사이는
spacing입니다. 각 줄은 목록의 폭을 채웁니다 - 높이는 줄의 합이 정합니다
인터랙션#
- 목록 자체는 입력을 받지 않습니다 — 탭은 각 줄(
OptionItem)이 받습니다 - 선택을 한 줄로 제한하는 규칙은 없습니다. 단일 선택이면 호출자가 한 줄만
selected로 둡니다
상태 전환#
- 상태가 없습니다. 같은 줄 · 같은 폭이면 같은 배치입니다
애니메이션#
- 없습니다
사용 가이드라인 (Usage Guidelines)#
Do#
한 목록의 줄은 같은 selection 으로 맞춘다
OptionList(
children: [
for (final tag in tags)
OptionItem(
selection: .multiple,
label: Text(tag.name),
selected: chosen.contains(tag),
onPressed: () => toggle(tag),
),
],
)
이유: 한 목록에서 체크 표시와 체크박스가 섞이면 고르는 방식이 줄마다 달라 보입니다.
Don't#
줄 사이에 구분선을 직접 끼우지 않는다
// ❌ 줄마다 위아래 여백이 이미 14 라 구분선을 끼우면 목록이 늘어진다
OptionList(children: [first, const Divider(), second])
이유: 목록의 줄 사이 간격은 optionListStyle.spacing 으로 정합니다.
접근성 (Accessibility)#
역할#
-
Flutter:
CoUISemantics(role: .group, container: true)로 목록 전체를 하나의 그룹으로 묶습니다 - Web: 루트
<div>에role="group"을 내보냅니다
그룹에는 접근 가능한 이름이 없습니다. 줄의 라벨이 곧 내용입니다.
키보드#
| 키 | Flutter | Web |
|---|---|---|
Tab | 활성 줄을 화면 순서로 이동 | 활성 줄을 화면 순서로 이동 |
Enter / Space | 포커스를 가진 줄이 처리 | 포커스를 가진 줄이 처리 |
목록 자체는 포커스를 받지 않습니다.
스크린 리더#
그룹 안에서 줄 순서대로 읽힙니다. 상태 통보(live region)는 없습니다.
포커스 관리#
- 진입 · 이탈 · 트랩: 없음 — 목록은 오버레이가 아닙니다
알려진 제약#
-
그룹에 이름이 없습니다. 이름이 필요하면 호출자가 붙입니다 — Web 은
attributes: {'aria-label': '…'}, Flutter 는 목록을Semantics(label:)로 감쌉니다
전역 축(동작 줄이기 · 고대비 · 색 강제 모드 · 시맨틱 역할 · 최소 터치 타겟)은 접근성 페이지가 한 곳에서 다룹니다.
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | OptionList | OptionList |
| 루트 | CoUISemantics → Column(stretch, 최소 높이) |
<div role="group">(flex 열) |
| Web 전용 HTML 표면 | — |
attributes
·
classes
·
css
·
eventHandlers
·
id
통과
|
위 차이 밖에는 없습니다 — 이름 · 순서 · 기본값을 두 위젯 생성자에서 대조했습니다.
관련 컴포넌트 (Related Components)#
- OptionItem: 목록의 줄
- Menu: 동작을 실행하는 줄의 목록
- Select: 목록을 드롭다운 안에 접는 선택