Carousel | CoUI

Carousel

슬라이드 형태로 콘텐츠를 순환하며 보여주는 컴포넌트

Carousel#

슬라이드 형태로 콘텐츠를 순환하며 보여주는 컴포넌트입니다. 자동 재생, 탐색 버튼, 인디케이터를 지원합니다.

Live Preview#

Web
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 자동 재생 간격
autoPlayboolfalse자동 재생
showIndicators bool true 인디케이터 표시
showNavigation bool true 좌우 버튼 표시
currentIndex int 0 현재 슬라이드 인덱스
onIndexChanged Function(int)? null 인덱스 변경 콜백
wrapbooltrue무한 순환
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)적용 영역
indicatorActiveColorColor?활성 인디케이터 dot 색
indicatorInactiveColorColor?비활성 인디케이터 dot 색
indicatorSizedouble?인디케이터 dot 지름 (px)
indicatorGapdouble?인디케이터 dot 간격 (px)
controlOverlayColorColor?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)#

항목FlutterWeb
클래스명CoCarouselCoCarousel
전환 CarouselTransition (sliding/fading) CSS translateX + transition (sliding)
드래그 GestureDetector 지원 mousedown/mousemove/mouseup 지원
자동 재생Ticker 기반Timer.periodic 기반
호버 감지 MouseRegion mouseenter/mouseleave
무한 순환CarouselController 연속 값가상 무한 트랙 (clone + instant jump)