Carousel#
슬라이드 형태로 콘텐츠를 순환하며 보여주는 컴포넌트입니다. 자동 재생, 탐색 버튼, 인디케이터를 지원합니다.
Live Preview#
Web
Slide 3
Slide 1
Slide 2
Slide 3
Slide 1
Flutter
Loading Flutter...
class CarouselDefaultExample extends StatefulComponent {
const CarouselDefaultExample({super.key});
@override
State<CarouselDefaultExample> createState() =>
_CarouselDefaultExampleState();
}
class _CarouselDefaultExampleState extends State<CarouselDefaultExample> {
int _index = 0;
@override
Component build(BuildContext context) {
return CoCarousel(
currentIndex: _index,
onIndexChanged: (idx) => setState(() => _index = idx),
items: [
div(
[Component.text('Slide 1')],
styles: Styles(raw: {
'background': '#3B82F6',
'color': 'white',
'font-size': '18px',
'display': 'flex',
'align-items': 'center',
'justify-content': 'center',
'padding': 'var(--coui-space-64)',
}),
),
div(
[Component.text('Slide 2')],
styles: Styles(raw: {
'background': '#22C55E',
'color': 'white',
'font-size': '18px',
'display': 'flex',
'align-items': 'center',
'justify-content': 'center',
'padding': 'var(--coui-space-64)',
}),
),
div(
[Component.text('Slide 3')],
styles: Styles(raw: {
'background': '#F97316',
'color': 'white',
'font-size': '18px',
'display': 'flex',
'align-items': 'center',
'justify-content': 'center',
'padding': 'var(--coui-space-64)',
}),
),
],
);
}
}
class CarouselDefaultExample extends StatefulWidget {
const CarouselDefaultExample({super.key});
@override
State<CarouselDefaultExample> createState() =>
_CarouselDefaultExampleState();
}
class _CarouselDefaultExampleState extends State<CarouselDefaultExample> {
@override
Widget build(BuildContext context) {
return CoCarousel(
transition: CarouselTransition.sliding(),
items: [
Container(
alignment: Alignment.center,
color: const Color(0xFF3B82F6),
padding: const EdgeInsets.all(CoreSpace.space64),
child: const Text('Slide 1',
style: TextStyle(color: Colors.white, fontSize: 18)),
),
Container(
alignment: Alignment.center,
color: const Color(0xFF22C55E),
padding: const EdgeInsets.all(CoreSpace.space64),
child: const Text('Slide 2',
style: TextStyle(color: Colors.white, fontSize: 18)),
),
Container(
alignment: Alignment.center,
color: const Color(0xFFF97316),
padding: const EdgeInsets.all(CoreSpace.space64),
child: const Text('Slide 3',
style: TextStyle(color: Colors.white, fontSize: 18)),
),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 여러 이미지나 콘텐츠를 슬라이드쇼로 표시할 때
- 프로모션 배너를 순환 표시할 때
대신 다른 컴포넌트를 사용하세요:
HoverGallery: 호버 기반 이미지 전환
기본 사용법 (Basic Usage)#
CoCarousel(
transition: CarouselTransition.sliding(),
items: [
Container(color: Colors.blue, child: Text('Slide 1')),
Container(color: Colors.green, child: Text('Slide 2')),
Container(color: Colors.orange, child: Text('Slide 3')),
],
autoPlay: true,
showIndicators: true,
showNavigation: true,
)
CoCarousel(
currentIndex: _index,
onIndexChanged: (i) => setState(() => _index = i),
items: [
div([Component.text('Slide 1')]),
div([Component.text('Slide 2')]),
div([Component.text('Slide 3')]),
],
autoPlay: true,
showIndicators: true,
showNavigation: true,
)
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
items |
List<Widget/Component>? |
null |
슬라이드 목록 |
itemBuilder |
Function? |
null |
빌더 모드 (Flutter) |
itemCount |
int? |
null |
빌더 모드 아이템 수 |
transition |
CarouselTransition / Object |
required / Object() |
전환 효과 |
duration |
Duration? |
null |
자동 재생 간격 |
autoPlay | bool | false | 자동 재생 |
showIndicators |
bool |
true |
인디케이터 표시 |
showNavigation |
bool |
true |
좌우 버튼 표시 |
currentIndex |
int |
0 |
현재 슬라이드 인덱스 |
onIndexChanged |
Function(int)? |
null |
인덱스 변경 콜백 |
wrap | bool | true | 무한 순환 |
pauseOnHover |
bool |
true |
호버 시 자동 재생 일시 정지 |
carouselStyle |
CoreCarouselStyle<Color>? / CoreCarouselStyle<CoreColor>? |
null |
인스턴스 스타일 (Style 시스템 참조) |
스타일 시스템 (Style System)#
Carousel 의 모든 chrome / dimensional / nested-slot 오버라이드는 CoreCarouselStyle<Clr> 단일 슬롯으로 흐릅니다 (Epic #1302 원칙 6/7/8). 시맨틱 enum (transition) 과 behaviour (autoPlay
/ wrap / pauseOnHover / showIndicators / showNavigation) 는 위젯 파라미터로 직접 전달합니다.
시맨틱 vs 스타일#
-
시맨틱 enum / behaviour: 위젯 파라미터로 직접 (
transition,autoPlay,wrap,pauseOnHover,showIndicators,showNavigation,currentIndex,onIndexChanged) -
chrome / dimensional / 슬롯 스타일:
CoreCarouselStyle한 곳으로 (indicatorActiveColor/indicatorInactiveColor/indicatorSize/indicatorGap/controlOverlayColor/prevNextButtonStyle)
Resolve chain#
design system default for carousel
→ CoreCarouselTheme.style // 프로젝트 공통
→ parent component slot override
→ widget.carouselStyle // 인스턴스별
각 nested 슬롯 스타일 (prevNextButtonStyle) 은 자기 컴포넌트의 자체 resolve chain 으로 다시 한 번 머지됩니다.
슬롯 매핑 (CoreCarouselStyle 6 필드)#
| 필드 | 타입 (Flutter) | 적용 영역 |
|---|---|---|
indicatorActiveColor | Color? | 활성 인디케이터 dot 색 |
indicatorInactiveColor | Color? | 비활성 인디케이터 dot 색 |
indicatorSize | double? | 인디케이터 dot 지름 (px) |
indicatorGap | double? | 인디케이터 dot 간격 (px) |
controlOverlayColor | Color? | prev/next 버튼 배경 오버레이 |
prevNextButtonStyle |
CoreButtonStyle<Color>? |
prev/next 버튼 chrome (CoButton 슬롯으로 위임) |
Migration#
기존에는 인디케이터 색상/크기 / prev-next 버튼 스타일을 인라인 직접 변경 외에는 노출하지 않았습니다. 새 코드는 carouselStyle 슬롯을 사용하세요:
| 기존 (위젯/테마 직접 수정) | 새 위치 |
|---|---|
| 직접 인라인으로 인디케이터 색 변경 | carouselStyle.indicatorActiveColor / indicatorInactiveColor |
| 직접 dot 크기/간격 조정 | carouselStyle.indicatorSize / indicatorGap |
| prev/next 버튼 배경 변경 | carouselStyle.controlOverlayColor |
| prev/next 버튼 chrome 변경 | carouselStyle.prevNextButtonStyle (CoreButtonStyle) |
사용 예 (Flutter)#
CoCarousel(
items: [slide1, slide2, slide3],
transition: CarouselTransition.sliding(),
carouselStyle: CoreCarouselStyle<Color>(
indicatorActiveColor: Colors.blue,
indicatorInactiveColor: Colors.grey,
indicatorSize: 8,
indicatorGap: 6,
),
)
사용 예 (Web)#
CoCarousel(
items: items,
carouselStyle: CoreCarouselStyle<CoreColor>(
indicatorSize: 8,
indicatorGap: 6,
),
)
동작 스펙 (Behavior)#
- 좌우 버튼으로 슬라이드 전환
- 인디케이터 dot 클릭으로 직접 이동
autoPlay: true시 자동 순환pauseOnHover: true시 호버 시 일시 정지wrap: true시 마지막에서 첫 번째로 순환
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CoCarousel | CoCarousel |
| 전환 | CarouselTransition (sliding/fading) |
CSS translateX + transition (sliding) |
| 드래그 | GestureDetector 지원 |
mousedown/mousemove/mouseup 지원 |
| 자동 재생 | Ticker 기반 | Timer.periodic 기반 |
| 호버 감지 | MouseRegion |
mouseenter/mouseleave |
| 무한 순환 | CarouselController 연속 값 | 가상 무한 트랙 (clone + instant jump) |
관련 컴포넌트 (Related Components)#
- HoverGallery: 호버 기반 이미지 전환
- DotIndicator: 페이지 위치 표시