RadioGroup#
여러 항목 중 하나만 선택할 수 있는 라디오 버튼 그룹 컴포넌트입니다.
Live Preview#
Web
Flutter
Loading Flutter...
class RadioDefaultExample extends StatefulComponent {
const RadioDefaultExample({super.key});
@override
State<RadioDefaultExample> createState() => _RadioDefaultExampleState();
}
class _RadioDefaultExampleState extends State<RadioDefaultExample> {
String? _selected = 'option1';
@override
Component build(BuildContext context) {
return CoRadioGroup(
value: _selected,
onChanged: (v) => setState(() => _selected = v),
options: const [
(value: 'option1', label: 'Option 1'),
(value: 'option2', label: 'Option 2'),
(value: 'option3', label: 'Option 3'),
],
);
}
}
class RadioDefaultExample extends StatefulWidget {
const RadioDefaultExample({super.key});
@override
State<RadioDefaultExample> createState() => _RadioDefaultExampleState();
}
class _RadioDefaultExampleState extends State<RadioDefaultExample> {
String? _selected = 'option1';
@override
Widget build(BuildContext context) {
return CoRadioGroup<String>(
value: _selected,
onChanged: (v) => setState(() => _selected = v),
options: const [
(value: 'option1', label: 'Option 1'),
(value: 'option2', label: 'Option 2'),
(value: 'option3', label: 'Option 3'),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 상호 배타적인 선택지 중 하나를 선택해야 하는 경우 (예: 성별, 결제 방법)
- 선택지가 2~6개 이하로 모든 옵션을 동시에 표시해야 하는 경우
- 사용자가 선택지를 비교하며 결정해야 하는 경우
대신 다른 컴포넌트를 사용하세요:
Select: 선택지가 7개 이상이어서 드롭다운으로 공간을 절약해야 하는 경우Checkbox: 여러 항목을 동시에 선택할 수 있는 경우SwitchField: 켜기/끄기의 이진 선택인 경우
기본 사용법 (Basic Usage)#
// options 기반 간편 사용
CoRadioGroup(
value: selectedGender,
onChanged: handleGenderChanged,
options: [
(value: 'male', label: '남성'),
(value: 'female', label: '여성'),
(value: 'other', label: '기타'),
],
)
// 수평 배치
CoRadioGroup(
value: selectedSize,
onChanged: handleSizeChanged,
orientation: CoreRadioGroupOrientation.horizontal,
options: [
(value: 'sm', label: 'S'),
(value: 'md', label: 'M'),
(value: 'lg', label: 'L'),
(value: 'xl', label: 'XL'),
],
)
// child 기반 커스텀 레이아웃
CoRadioGroup(
value: selectedOption,
onChanged: handleOptionChanged,
child: Column(
children: [
CoRadio(value: 'option1', label: 'Option 1'),
CoRadio(value: 'option2', label: 'Option 2'),
],
),
)
// options 기반 간편 사용
CoRadioGroup(
value: selectedGender,
onChanged: handleGenderChanged,
options: [
(value: 'male', label: '남성'),
(value: 'female', label: '여성'),
(value: 'other', label: '기타'),
],
)
// 수평 레이아웃
CoRadioGroup(
value: selectedSize,
onChanged: handleSizeChanged,
orientation: CoreRadioGroupOrientation.horizontal,
options: [
(value: 'sm', label: 'S'),
(value: 'md', label: 'M'),
(value: 'lg', label: 'L'),
],
)
// child 기반 커스텀 레이아웃
CoRadioGroup(
value: selectedOption,
onChanged: handleOptionChanged,
child: div([
CoRadio(value: 'option1', groupValue: selectedOption, label: 'Option 1', onChanged: handleOptionChanged),
CoRadio(value: 'option2', groupValue: selectedOption, label: 'Option 2', onChanged: handleOptionChanged),
]),
)
스타일 시스템 — radioGroupStyle (Epic #1302)#
CoRadioGroup 의 indicator chrome / 슬롯 미세 조정은 단일
radioGroupStyle (CoreRadioGroupStyle) 으로 흐릅니다. 시맨틱 enum
(variant, size, orientation) 은 위젯 파라미터.
CoRadioGroup<String>(
variant: CoreRadioGroupVariant.defaultVariant,
size: CoreComponentSize.md,
orientation: CoreRadioGroupOrientation.vertical,
value: selected,
options: [
(value: 'apple', label: '사과'),
(value: 'banana', label: '바나나'),
],
onChanged: handleChange,
radioGroupStyle: CoreRadioGroupStyle(
indicatorBorderColor: cs.outline,
indicatorActiveColor: cs.primary,
gap: 8,
itemGap: 12,
indicatorDotStyle: CoreIconStyle(size: 8, color: cs.onPrimary),
labelStyle: CoreTextStyle(fontWeight: CoreFontWeight.semiBold),
),
)
CoreRadioGroupStyle 필드#
| 필드 | 타입 | 설명 |
|---|---|---|
indicatorBackgroundColor |
Color? / String? |
unselected 배경 |
indicatorActiveColor |
Color? / String? |
selected 배경 |
indicatorBorderColor |
Color? / String? |
보더 색 |
indicatorBorderWidth | double? | 보더 두께 |
indicatorSize | double? | 인디케이터 크기 (width = height) |
gap | double? | 인디케이터 ↔ 레이블 간격 |
itemGap | double? | 형제 라디오 아이템 간 간격 |
indicatorDotStyle |
CoreIconStyle? |
안쪽 dot (size/color) |
labelStyle | CoreTextStyle? | 아이템 레이블 |
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
value | T? | null | 현재 선택된 값 |
onChanged |
ValueChanged<T?>? |
null |
선택 변경 콜백 |
options |
List<({T value, String label})>? |
null |
간편 옵션 목록 |
child |
Widget? / Component? |
null |
커스텀 레이아웃 |
variant |
CoreRadioGroupVariant |
defaultVariant |
시맨틱 변형 (위젯 파라미터) |
size |
CoreComponentSize |
md |
크기 토큰 (위젯 파라미터) |
orientation |
CoreRadioGroupOrientation |
vertical |
배치 방향 (위젯 파라미터) |
radioGroupStyle |
CoreRadioGroupStyle? |
null |
indicator chrome / nested slot 묶음 |
enabled | bool? | true | 활성화 여부 |
name | String? | null | 폼 필드 이름 |
변형 (Variants)#
수직 배치 (기본)#
CoRadioGroup(
value: selectedPlan,
onChanged: handlePlanChanged,
options: [
(value: 'basic', label: '베이직'),
(value: 'pro', label: '프로'),
(value: 'enterprise', label: '엔터프라이즈'),
],
)
수평 배치#
CoRadioGroup(
value: selectedPayment,
onChanged: handlePaymentChanged,
orientation: CoreRadioGroupOrientation.horizontal,
options: [
(value: 'card', label: '카드'),
(value: 'transfer', label: '계좌이체'),
(value: 'phone', label: '휴대폰'),
],
)
동작 스펙 (Behavior)#
인터랙션#
- 클릭/탭: 라디오 버튼 또는 레이블 클릭 시 해당 옵션 선택
- 호버: 포인터 오버 시 시각적 피드백 표시
- 포커스: 포커스 링(focus ring)으로 현재 포커스된 항목 명확히 표시
상태 전환#
unselected->selected(클릭 또는 Space/Enter 입력 시)- 이미 선택된 항목은 클릭해도
unselected로 변경되지 않음 (단일 선택 보장) disabled상태의 개별 항목은 선택 불가
그룹 동작#
- 동일 그룹 내에서는 하나의 항목만 선택 가능
- 선택 변경 시 이전 선택 항목은 자동으로 해제
사용 가이드라인 (Usage Guidelines)#
Do#
선택지를 모두 명확하게 표시
CoRadioGroup(
value: selectedDelivery,
onChanged: handleDeliveryChanged,
options: [
(value: 'standard', label: '일반 배송 (3-5일)'),
(value: 'express', label: '빠른 배송 (1-2일)'),
(value: 'same_day', label: '당일 배송'),
],
)
모든 옵션을 한 번에 볼 수 있어 사용자가 신중하게 비교하고 선택할 수 있다.
Don't#
선택지가 많을 때 CoRadioGroup 사용
// 10개 이상의 옵션은 화면을 과하게 차지함
CoRadioGroup(
value: selectedCountry,
onChanged: handleCountryChanged,
options: allCountries.map((c) => (value: c.code, label: c.name)).toList(),
// 200여 개 국가 - Select를 사용해야 함
)
선택지가 많으면 스크롤이 필요해 비교가 어렵고 화면을 과도하게 차지한다.
접근성 (Accessibility)#
키보드 인터랙션#
| 키 | 동작 |
|---|---|
Tab | 그룹 내 다음 라디오로 이동 |
Space | 현재 포커스된 항목 선택 |
스크린 리더#
-
Flutter:
Semantics로radiobuttonrole,checked상태, 그룹 레이블 전달 -
Web:
role="radiogroup"/role="radio",aria-checked자동 적용
터치 타겟#
- 최소 터치 타겟 크기: 48x48dp
- 라디오 버튼 + 레이블 전체 영역이 터치 가능 영역
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CoRadioGroup<T> | CoRadioGroup |
| 아이템 | CoRadio<T> | CoRadio |
| 제네릭 | T (any type) | String only |
| child | Widget? child | Component? child |
| 색상 타입 | Color? | CoreColor? |
관련 컴포넌트 (Related Components)#
- Checkbox: 여러 항목을 동시에 선택할 수 있는 경우
- Select: 선택지가 많아 드롭다운이 필요한 경우
- SwitchField: 켜기/끄기 이진 상태를 표현하는 경우
조합 예제#
// CoRadioGroup + Fieldset 조합: 요금제 선택 폼
Fieldset(
legend: '요금제',
description: '월 단위로 청구됩니다',
children: [
CoRadioGroup(
value: selectedPlan,
onChanged: handlePlanChanged,
options: [
(value: 'free', label: '무료 (5GB)'),
(value: 'pro', label: '프로 (100GB) - 9,900원/월'),
(value: 'business', label: '비즈니스 (무제한) - 29,900원/월'),
],
),
],
)