Stepper#
사용자가 단계를 클릭하여 이동할 수 있는 인터랙티브 프로세스 컴포넌트입니다.
Live Preview#
default
Web
Account
2
Profile
3
Complete
Flutter
Loading Flutter...
class StepperDefaultExample extends StatefulComponent {
const StepperDefaultExample({super.key});
@override
State<StepperDefaultExample> createState() => _StepperDefaultExampleState();
}
class _StepperDefaultExampleState extends State<StepperDefaultExample> {
int _currentStep = 1;
void handleStepChanged(int index) {
setState(() {
_currentStep = index;
});
}
@override
Component build(BuildContext context) {
return Stepper(
currentStep: _currentStep,
onStepChanged: handleStepChanged,
steps: const [
CoreStepItem(label: 'Account', description: 'Create account'),
CoreStepItem(label: 'Profile', description: 'Set up profile'),
CoreStepItem(label: 'Complete', description: 'All done'),
],
);
}
}
class StepperDefaultExample extends StatefulWidget {
const StepperDefaultExample({super.key});
@override
State<StepperDefaultExample> createState() => _StepperDefaultExampleState();
}
class _StepperDefaultExampleState extends State<StepperDefaultExample> {
int _currentStep = 1;
void handleStepChanged(int index) {
setState(() {
_currentStep = index;
});
}
@override
Widget build(BuildContext context) {
return Stepper(
currentStep: _currentStep,
onStepChanged: handleStepChanged,
steps: const [
CoreStepItem(label: 'Account', description: 'Create account'),
CoreStepItem(label: 'Profile', description: 'Set up profile'),
CoreStepItem(label: 'Complete', description: 'All done'),
],
);
}
}
vertical
Web
Account
Create account
2
Profile
Set up profile
3
Complete
All done
Flutter
Loading Flutter...
class StepperVerticalExample extends StatefulComponent {
const StepperVerticalExample({super.key});
@override
State<StepperVerticalExample> createState() => _StepperVerticalExampleState();
}
class _StepperVerticalExampleState extends State<StepperVerticalExample> {
int _currentStep = 1;
void handleStepChanged(int index) {
setState(() {
_currentStep = index;
});
}
@override
Component build(BuildContext context) {
return Stepper(
currentStep: _currentStep,
orientation: CoreStepperOrientation.vertical,
onStepChanged: handleStepChanged,
steps: const [
CoreStepItem(label: 'Account', description: 'Create account'),
CoreStepItem(label: 'Profile', description: 'Set up profile'),
CoreStepItem(label: 'Complete', description: 'All done'),
],
);
}
}
class StepperVerticalExample extends StatefulWidget {
const StepperVerticalExample({super.key});
@override
State<StepperVerticalExample> createState() => _StepperVerticalExampleState();
}
class _StepperVerticalExampleState extends State<StepperVerticalExample> {
int _currentStep = 1;
void handleStepChanged(int index) {
setState(() {
_currentStep = index;
});
}
@override
Widget build(BuildContext context) {
return Stepper(
currentStep: _currentStep,
orientation: CoreStepperOrientation.vertical,
onStepChanged: handleStepChanged,
steps: const [
CoreStepItem(label: 'Account', description: 'Create account'),
CoreStepItem(label: 'Profile', description: 'Set up profile'),
CoreStepItem(label: 'Complete', description: 'All done'),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 회원가입, 결제, 설정 마법사 등 다단계 폼
- 사용자가 이전 단계로 돌아가거나 특정 단계로 점프할 수 있어야 할 때
대신 다른 컴포넌트를 사용하세요:
Steps: 읽기 전용 진행 상태 표시 (탭 불가)Tabs: 독립적인 콘텐츠 간 전환 (순서/진행 개념 없음)
기본 사용법 (Basic Usage)#
Stepper(
currentStep: 1,
steps: [
CoreStepItem(label: 'Account', description: 'Create account'),
CoreStepItem(label: 'Profile', description: 'Set up profile'),
CoreStepItem(label: 'Complete', description: 'All done'),
],
onStepChanged: (index) => setState(() => _step = index),
)
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
steps | List<CoreStepItem> | 필수 | 단계 목록 |
currentStep |
int |
0 |
현재 활성 단계 인덱스 |
orientation |
CoreStepperOrientation |
.horizontal |
배치 방향 (horizontal/vertical) |
onStepChanged |
void Function(int)? |
null |
단계 클릭 시 호출 |
stepperStyle |
CoreStepperStyle<Color>? / CoreStepperStyle<CoreColor>? |
null |
인스턴스 스타일 (Style 시스템 참조) |
스타일 시스템 (Style System)#
Stepper 의 모든 chrome / dimensional / nested-slot 오버라이드는 CoreStepperStyle<Clr> 단일 슬롯으로 흐릅니다 (Epic #1302 원칙 6/7/8). 시맨틱 enum (orientation) 과 behaviour (steps
/ currentStep / onStepChanged) 는 위젯/컴포넌트 파라미터로 직접 전달합니다.
시맨틱 vs 스타일#
-
시맨틱 enum / behaviour: 위젯/컴포넌트 파라미터로 직접 (
steps,currentStep,orientation,onStepChanged) -
chrome / dimensional / 슬롯 스타일:
CoreStepperStyle한 곳으로 (indicatorActiveColor/indicatorInactiveColor/indicatorBorderColor/indicatorBorderWidth/indicatorSize/connectorActiveColor/connectorInactiveColor/connectorThickness/indicatorContentGapStyle/stepPadding/connectorMargin/horizontalLabelGapStyle/connectorMinExtent/iconSizeRatio/labelStyle/descriptionStyle/indicatorIconStyle)
Resolve chain#
design system default for stepper
→ CoreStepperTheme.style // 프로젝트 공통
→ parent component slot override
→ widget.stepperStyle // 인스턴스별
각 nested 슬롯 스타일 (labelStyle / descriptionStyle / indicatorIconStyle) 은 자기 컴포넌트의 자체 resolve chain 으로 다시 한 번 머지됩니다.
슬롯 매핑 (CoreStepperStyle 17 필드)#
| 필드 | 타입 (Flutter) | 적용 영역 |
|---|---|---|
indicatorActiveColor | Color? | 활성/완료 단계 인디케이터 fill |
indicatorInactiveColor | Color? | 대기 단계 인디케이터 fill |
indicatorBorderColor | Color? | 인디케이터 보더 색 |
indicatorBorderWidth | double? | 인디케이터 보더 두께 (px) |
indicatorSize | double? | 인디케이터 지름 (px) |
connectorActiveColor | Color? | 완료 연결선 색 |
connectorInactiveColor | Color? | 대기 연결선 색 |
connectorThickness | double? | 연결선 두께 (px) |
indicatorContentGapStyle |
CoreGapStyle? |
인디케이터 열과 단계 콘텐츠 간격 슬롯 (Gap 으로 전달) |
stepPadding | double? | 세로 배치에서 각 단계 콘텐츠 하단 패딩 (px) |
connectorMargin | double? | 연결선 둘레 마진 (px) |
horizontalLabelGapStyle |
CoreGapStyle? |
가로 배치에서 인디케이터 ↔ 라벨 간격 슬롯 (Gap 으로 전달) |
connectorMinExtent | double? | 세로 배치 연결선 최소 길이 (px) |
iconSizeRatio | double? | 인디케이터 지름 대비 체크 아이콘 크기 비율 |
labelStyle |
CoreTextStyle<Color>? |
단계 라벨 텍스트 스타일 |
descriptionStyle |
CoreTextStyle<Color>? |
단계 설명 텍스트 스타일 |
indicatorIconStyle |
CoreIconStyle<Color>? |
인디케이터 체크 아이콘 스타일 |
변형 (Variants)#
가로 배치#
Stepper(
currentStep: 1,
orientation: CoreStepperOrientation.horizontal,
steps: [
CoreStepItem(label: '기본 정보'),
CoreStepItem(label: '주소 입력'),
CoreStepItem(label: '결제 수단'),
CoreStepItem(label: '확인'),
],
onStepChanged: (i) => setState(() => _step = i),
)
세로 배치#
Stepper(
currentStep: 1,
orientation: CoreStepperOrientation.vertical,
steps: [
CoreStepItem(label: '기본 정보', description: '이름과 이메일'),
CoreStepItem(label: '주소 입력', description: '배송지 설정'),
CoreStepItem(label: '결제 수단', description: '카드 등록'),
],
onStepChanged: (i) => setState(() => _step = i),
)
동작 스펙 (Behavior)#
상태 표시#
currentStep미만: 완료 (primary 원 + 체크 아이콘)currentStep인덱스: 현재 (primary 원 + 번호, 볼드 라벨)currentStep초과: 대기 (surfaceContainer 원 + 번호)
인터랙션#
- 각 단계 인디케이터 클릭 →
onStepChanged(index)호출 - 키보드 네비게이션은 표준
Tab순서 따름
접근성 (Accessibility)#
키보드#
| 키 | 동작 |
|---|---|
Tab | 다음 단계로 포커스 이동 |
Enter / Space | 포커스된 단계로 이동 |
스크린 리더#
- 각 단계는 순서 + 라벨 + 설명 읽음
- 완료/현재/대기 상태 시각 표시 기반
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | Stepper | Stepper |
| 렌더링 | Column/Row + GestureDetector |
<div> + 인라인 스타일 |
| 아이콘 | Icon(LucideIcons.check) |
Icon(LucideIcons.check) |
| 테마 | CoreStepperTheme | CoreStepperTheme |