Slider | CoUI

Slider

범위 내 값을 선택하는 슬라이더 컴포넌트

Slider#

연속적인 값 또는 범위를 선택할 수 있는 슬라이더 컴포넌트입니다.

Live Preview#

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

  @override
  State<SliderDefaultExample> createState() => _SliderDefaultExampleState();
}

class _SliderDefaultExampleState extends State<SliderDefaultExample> {
  double _value = 50;

  @override
  Component build(BuildContext context) {
    return CoSlider(
      value: _value,
      min: 0,
      max: 100,
      onChanged: (v) => setState(() => _value = v),
    );
  }
}
class SliderDefaultExample extends StatefulWidget {
  const SliderDefaultExample({super.key});

  @override
  State<SliderDefaultExample> createState() => _SliderDefaultExampleState();
}

class _SliderDefaultExampleState extends State<SliderDefaultExample> {
  double _value = 50;

  @override
  Widget build(BuildContext context) {
    return CoSlider(
      value: _value,
      min: 0,
      max: 100,
      onChanged: (v) => setState(() => _value = v),
    );
  }
}

사용 시기 (When to Use)#

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

  • 볼륨, 밝기 등 연속적인 값을 직관적으로 조절할 때
  • 가격 범위, 나이 범위 등 두 값 사이의 범위를 선택할 때
  • 값의 상대적 위치를 시각적으로 확인하면서 조절할 때

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

  • Input: 정확한 숫자 입력이 필요할 때
  • Progress: 사용자 조작 없이 진행률만 표시할 때
  • Select: 불연속적인 옵션 중 선택할 때

기본 사용법 (Basic Usage)#

// 기본 슬라이더
CoSlider(
  value: volume,
  onChanged: handleVolumeChange,
  min: 0,
  max: 100,
)

// 단계 지정
CoSlider(
  value: rating,
  onChanged: handleRatingChange,
  min: 0,
  max: 5,
  divisions: 5,
)

// 비활성화
CoSlider(
  value: volume,
  enabled: false,
  min: 0,
  max: 100,
)
// 기본 슬라이더
CoSlider(
  value: volume,
  onChanged: handleVolumeChange,
  min: 0,
  max: 100,
)

// 단계(step) 지정
CoSlider(
  value: rating,
  onChanged: handleRatingChange,
  min: 0,
  max: 5,
  step: 1,
)

// 비활성화
CoSlider(
  value: volume,
  enabled: false,
  min: 0,
  max: 100,
)

스타일 시스템 — sliderStyle (Epic #1302)#

CoSlider 의 track + thumb chrome / 슬롯 미세 조정은 단일 sliderStyle (CoreSliderStyle) 으로 흐릅니다. Slider 는 시맨틱 enum (variant) 이 없어 behaviour 필드만 위젯 파라미터.

CoSlider(
  value: temperature,
  min: 0,
  max: 100,
  divisions: 10,
  onChanged: handleChange,
  sliderStyle: CoreSliderStyle(
    trackColor: cs.outline,
    activeColor: cs.primary,
    trackHeight: 4,
    thumbColor: cs.onPrimary,
    thumbBorderColor: cs.outline,
    thumbSize: 20,
    tickLabelStyle: CoreTextStyle(fontSize: 12, color: cs.onSurfaceVariant),
  ),
)

CoreSliderStyle 필드#

필드타입설명
trackColorColor? / String?비활성 트랙 색
activeColor Color? / String? 활성 (filled) 트랙 색
trackHeightdouble?트랙 높이
thumbColorColor? / String?thumb 배경
thumbBorderColor Color? / String? thumb 보더
thumbSizedouble?thumb 크기
tickLabelStyle CoreTextStyle? tick 레이블 (divisions 사용 시)

Props / Parameters#

속성타입기본값설명
valuedouble0.0현재 값
onChanged ValueChanged<double>? null 값 변경 콜백
onChangeStart / onChangeEnd ValueChanged<double>? null 드래그 시작/종료
mindouble0.0최솟값
maxdouble100.0최댓값
stepdouble?null단계 크기
divisionsint?null단계 수
enabledbooltrue활성화 여부
sliderStyle CoreSliderStyle? null track + thumb chrome / nested tickLabelStyle 묶음

변형 (Variants)#

단계 지정#

CoSlider(
  value: temperature,
  onChanged: handleTempChange,
  min: 16,
  max: 30,
  divisions: 14,
)

Step 지정#

CoSlider(
  value: rating,
  onChanged: handleRatingChange,
  min: 0,
  max: 5,
  step: 1,
)

동작 스펙 (Behavior)#

SliderController#

CoSlider(
  value: 50,
  min: 0,
  max: 100,
  onChanged: (v) => setState(() => _value = v),
)
  • value, min, max, onChanged 기본 API
  • step 또는 divisions으로 이산 값 스냅

드래그 인터랙션#

  • 단일 모드: 트랙 아무 곳이나 클릭하면 썸이 이동. 썸 드래그 지원
  • 범위 모드: 클릭 시 가까운 썸이 선택됨. 각 썸 독립 드래그
  • 드래그 중 onChangeStart/onChangeEnd 콜백 호출

Divisions (스냅)#

CoSlider(
  value: rating,
  onChanged: handleRating,
  min: 0, max: 5, divisions: 5,
)
  • divisions가 설정되면 값이 가장 가까운 단계에 스냅
  • SliderValue.roundToDivisions(int) 메서드로 반올림
  • 시각적 틱 마크 표시

Hint Value#

CoSlider(
  value: volume,
  onChanged: handleVolume,
  min: 0,
  max: 100,
)

내부 상수#

상수설명
트랙 높이6px기본 트랙 두께
썸 크기16px드래그 핸들 크기
비활성 알파0.2트랙 비활성 부분 불투명도
테두리 알파0.5썸 테두리 불투명도

키보드 네비게이션#

  • increaseStep / decreaseStep으로 화살표 키 단계 크기 지정
  • FocusableActionDetector 기반 포커스 관리

Web 구현#

  • 네이티브 HTML <input type="range"> 오버레이 (opacity-0)
  • 커스텀 트랙/range div로 시각적 표현
  • step 속성으로 단계 크기 지정
  • showValue: true로 현재 값 라벨 표시

사용 가이드라인 (Usage Guidelines)#

✅ Do#

슬라이더에 현재 값을 라벨로 표시하세요.

CoSlider(
  value: temperature,
  onChanged: handleTemp,
  min: 16, max: 30,
  divisions: 14,
)

사용자가 정확한 값을 확인하면서 조절할 수 있습니다.


❌ Don't#

정밀한 값 입력에 슬라이더만 사용하지 마세요.

// ❌ Bad — 정확한 금액 입력이 어려움
CoSlider(value: price, min: 0, max: 1000000, onChanged: handlePrice)

// ✅ Good — 슬라이더 + 입력 필드 조합
Row(children: [
  Expanded(child: CoSlider(value: price, min: 0, max: 1000000, onChanged: handlePrice)),
  SizedBox(width: 16),
  SizedBox(width: 80, child: CoTextField(initialValue: price.toString())),
])

✅ Do#

범위 슬라이더로 필터를 구현하세요.

CoSlider(
  value: minPrice,
  onChanged: handleMinPriceFilter,
  min: 0,
  max: 500000,
  step: 10000,
)
CoSlider(
  value: maxPrice,
  onChanged: handleMaxPriceFilter,
  min: 0,
  max: 500000,
  step: 10000,
)

가격, 나이 등 범위 필터에 직관적입니다.


❌ Don't#

3개 이상의 값이 필요하면 슬라이더를 사용하지 마세요.

슬라이더는 1~2개 값(단일/범위)에 최적화되어 있습니다. 복잡한 입력은 개별 필드를 사용하세요.

✅ Do#

이산 값에는 divisions를 설정하세요.

// 별점 1~5
CoSlider(
  value: stars, min: 1, max: 5, divisions: 4,
  onChanged: handleStars,
)

연속 값이 아닌 경우 스냅으로 정확한 선택을 보장합니다.

접근성 (Accessibility)#

키보드 인터랙션#

동작
/ 값 감소 (decreaseStep 만큼)
/ 값 증가 (increaseStep 만큼)
Home최솟값으로 이동
End최댓값으로 이동
Tab다음 요소로 포커스 이동

스크린 리더#

  • Flutter: 현재 값, 최솟값, 최댓값이 시맨틱으로 전달
  • Web: 네이티브 <input type="range">aria-valuenow, aria-valuemin, aria-valuemax 자동 적용

터치 영역#

  • 썸(16px)보다 넓은 터치 영역 확보 (트랙 전체 클릭 가능)
  • 모바일에서 충분한 드래그 감도

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

v3.0부터 기본 API (enabled, onChanged, value 등)가 통일되었습니다. 아래는 플랫폼 고유 차이점만 나열합니다.

항목FlutterWeb
클래스명CoSliderCoSlider
값 모델doubledouble
Divisionsdivisions (int)divisions (int)
Stepstep (double)step (double)
트랙 렌더링 커스텀 GestureDetector + 페인팅 <input type="range"> + CSS 오버레이
키보드Arrow keys 커스텀브라우저 네이티브
색상 커스텀activeColor: ColoractiveColor: CoreColor
테마Flutter Theme 기반Tailwind CSS
  • Progress: 진행률 표시. Slider는 입력, Progress는 출력
  • Input: 정확한 숫자 입력. Slider와 함께 사용 가능

조합 예제#

// 가격 범위 필터 패턴
Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('가격 범위'),
    SizedBox(height: 8),
    CoSlider(
      value: minPrice,
      onChanged: (v) => setState(() => minPrice = v),
      min: 0,
      max: 500000,
      step: 10000,
    ),
    CoSlider(
      value: maxPrice,
      onChanged: (v) => setState(() => maxPrice = v),
      min: 0,
      max: 500000,
      step: 10000,
    ),
    SizedBox(height: 4),
    Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Text('₩${minPrice.toInt()}'),
        Text('₩${maxPrice.toInt()}'),
      ],
    ),
  ],
)