Swiper | CoUI

Swiper

스와이프 제스처로 가장자리에서 오버레이 패널을 여는 컴포넌트

Swiper#

자식 위젯을 감싸 스와이프 제스처에 반응하고, 화면 가장자리에서 오버레이 패널을 슬라이드 인하는 컴포넌트입니다. 모바일 환경의 자연스러운 스와이프 인터랙션으로 네비게이션 메뉴나 시트를 여는 데 활용됩니다.

Live Preview#

Web
Flutter
Loading Flutter...
class SwiperDefaultExample extends StatefulComponent {
  const SwiperDefaultExample({super.key});

  @override
  State<SwiperDefaultExample> createState() => _SwiperDefaultExampleState();
}

class _SwiperDefaultExampleState extends State<SwiperDefaultExample> {
  bool _open = false;

  @override
  Component build(BuildContext context) {
    return Swiper(
      position: CoreSwiperPosition.left,
      open: _open,
      onOpenChanged: (isOpen) => setState(() => _open = isOpen),
      overlayContent: div(
        const [
          Text('Dashboard'),
          Text('Settings'),
          Text('Profile'),
        ],
        classes: 'flex flex-col gap-${CoreSpace.scale.space8}',
      ),
      child: Button(
        variant: CoreButtonVariant.outline,
        onPressed: () => setState(() => _open = true),
        child: const Text('Open swiper'),
      ),
    );
  }
}
class SwiperDefaultExample extends StatefulWidget {
  const SwiperDefaultExample({super.key});

  @override
  State<SwiperDefaultExample> createState() => _SwiperDefaultExampleState();
}

class _SwiperDefaultExampleState extends State<SwiperDefaultExample> {
  bool _open = false;

  @override
  Widget build(BuildContext context) {
    return Swiper(
      position: CoreSwiperPosition.left,
      open: _open,
      onOpenChanged: (isOpen) => setState(() => _open = isOpen),
      overlayContent: const Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Dashboard'),
          Text('Settings'),
          Text('Profile'),
        ],
      ),
      child: Button(
        variant: CoreButtonVariant.outline,
        onPressed: () => setState(() => _open = true),
        child: const Text('Open swiper'),
      ),
    );
  }
}

사용 시기 (When to Use)#

이 컴포넌트를 사용하세요:

  • 화면 가장자리 스와이프로 네비게이션 메뉴를 열 때
  • 모바일 환경에서 제스처 기반으로 시트/패널을 열 때
  • 버튼 탭과 스와이프 두 가지 방식 모두로 오버레이를 열고 싶을 때

대신 다른 컴포넌트를 사용하세요:

  • Drawer: 버튼/명령으로만 여는 가장자리 패널에 (제스처 불필요)
  • Carousel: 스와이프로 슬라이드를 순환 탐색할 때

기본 사용법 (Basic Usage)#

// 좌측에서 열리는 드로어 스타일 오버레이
Swiper(
  position: CoreSwiperPosition.left,
  open: isMenuOpen,
  onOpenChanged: (isOpen) => setState(() => isMenuOpen = isOpen),
  overlayContent: const Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Text('Dashboard'),
      Text('Settings'),
    ],
  ),
  child: const AppHeader(),
)

// 아래에서 올라오는 시트 스타일
Swiper(
  position: CoreSwiperPosition.bottom,
  variant: CoreSwiperVariant.sheet,
  open: isSheetOpen,
  onOpenChanged: (isOpen) => setState(() => isSheetOpen = isOpen),
  overlayContent: const ActionSheet(),
  child: const PageContent(),
)
// 좌측에서 열리는 드로어 스타일 오버레이
Swiper(
  position: CoreSwiperPosition.left,
  open: isMenuOpen,
  onOpenChanged: (isOpen) => setState(() => isMenuOpen = isOpen),
  overlayContent: div([
    const Text('Dashboard'),
    const Text('Settings'),
  ], classes: 'flex flex-col gap-${CoreSpace.scale.space8}'),
  child: const AppHeader(),
)

// 아래에서 올라오는 시트 스타일
Swiper(
  position: CoreSwiperPosition.bottom,
  variant: CoreSwiperVariant.sheet,
  open: isSheetOpen,
  onOpenChanged: (isOpen) => setState(() => isSheetOpen = isOpen),
  overlayContent: const ActionSheet(),
  child: const PageContent(),
)

Props / Parameters#

속성타입기본값설명
child Widget / Component 필수 스와이프 제스처에 반응하는 자식
overlayContent Widget / Component 필수 오버레이 패널에 표시할 콘텐츠
position CoreSwiperPosition left 오버레이가 슬라이드 인하는 가장자리
variant CoreSwiperVariant drawer 오버레이 표현 스타일 (drawer / sheet)
open bool false 오버레이 열림 상태 (제어 값)
onOpenChanged void Function(bool)? null 열림 상태 변경 콜백
enabled bool true 스와이프 제스처 활성화 여부
showDragHandle bool true 드래그 핸들 표시 여부
barrierDismissible bool true 배경 탭으로 닫기 허용 여부
swiperStyle CoreSwiperStyle? null 오버레이 크롬 / 치수 / 애니메이션 스타일 override

변형 (Variants)#

드로어 (Drawer)#

그림자가 있는 입체 패널입니다. 네비게이션 메뉴에 적합합니다.

Swiper(
  position: CoreSwiperPosition.left,
  variant: CoreSwiperVariant.drawer,
  open: isOpen,
  onOpenChanged: (v) => setState(() => isOpen = v),
  overlayContent: const NavigationMenu(),
  child: const AppHeader(),
)

시트 (Sheet)#

그림자 없이 최소 장식의 패널입니다. 바텀 시트에 적합합니다.

Swiper(
  position: CoreSwiperPosition.bottom,
  variant: CoreSwiperVariant.sheet,
  open: isOpen,
  onOpenChanged: (v) => setState(() => isOpen = v),
  overlayContent: const ActionSheet(),
  child: const PageContent(),
)

동작 스펙 (Behavior)#

인터랙션#

  • 스와이프 열기: position 방향을 드러내는 방향으로 스와이프하면 오버레이가 열림 (좌측 오버레이 → 오른쪽 스와이프)
  • 배경 탭 닫기: barrierDismissibletrue이면 배경 탭으로 닫힘
  • 제어 값: openonOpenChanged로 버튼 등 외부 트리거로도 제어 가능

애니메이션#

  • 슬라이드 전환: 300ms ease-in-out
  • 배경 페이드: 200ms ease-in-out

접근성 (Accessibility)#

  • 오버레이 패널에 role="dialog" + aria-modal="true" 부여
  • 배경 닫기 버튼에 aria-label 제공
  • 스와이프 외에 버튼 등 명시적 트리거를 함께 제공하여 키보드/스크린 리더 사용자도 오버레이를 열 수 있게

크로스 플랫폼 차이점 (Platform Differences)#

항목FlutterWeb
클래스명SwiperSwiper
제스처 감지GestureDetector 드래그touch / pointer 이벤트
오버레이 마운트PopupRouteposition: fixed 패널
애니메이션SlideTransitionCSS transition: transform
  • Drawer: 버튼/명령으로 여는 가장자리 패널
  • Carousel: 스와이프로 슬라이드를 순환 탐색