RangeSlider
두 네이티브 input[type="range"]를 겹친 두-썸 범위 슬라이더 — 각 썸이 실제 슬라이더라 키보드/ARIA는 네이티브가 보장하고, 두 썸은 교차 불가(low ≤ high). 비제어(defaultValue) 우선 + 제어(value/onChange).
마지막 업데이트 2026-06-12
한눈에#
가격대·연식·기간처럼 시작~끝 두 값(범위) 을 어림으로 고르는 두-썸 슬라이더입니다 — 두 썸은 교차하지 않습니다(low ≤ high).
- 두-썸 범위
- low ≤ high 교차 불가
- 네이티브 range×2
- showValue 라벨
각 썸이 실제 네이티브 슬라이더라 키보드·ARIA를 그대로 보장합니다
사용 시점#
시작~끝 두 값(범위)을 어림잡아 고르면 RangeSlider — 단일 값이나 정밀 정수는 다른 컴포넌트입니다.
가격대·연식·기간처럼 교차하지 않는 두 값(low ≤ high) 범위 필터
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
import { RangeSlider } from '@wds/ui-web';
<RangeSlider
aria-label="가격 범위"
defaultValue={[20, 80]}
min={0}
max={100}
step={5}
/>변형#
formatLabel은 함수라 라이브 데모로 넘길 수 없어 코드로 안내합니다 — showValue
라벨과 두 입력의 aria-valuetext에 포맷된 값이 노출됩니다.
<RangeSlider
aria-label="가격"
min={0}
max={200}
step={10}
defaultValue={[40, 160]}
showValue
formatLabel={(v) => `${v.toLocaleString()}원`}
/>
크기#
단일 크기입니다 — 4px(space.1) 트랙 + 18px(icon.size-md) 썸 2개. 필드 높이는
control.height-md(44px)로 썸보다 큰 터치 타깃을 확보합니다. 두 썸 사이는
color.primary 채움 트랙으로 표시합니다(기하만 %, 색은 토큰).
상태#
- Focus — 각 썸
:focus-visible에 primary 링 (Tab으로 두 썸을 차례로 확인하세요) - Disabled — 트랙·채움·썸이
color.border-subtle/color.text-placeholder톤으로 가라앉고 커서 차단 - 교차 방지(no-cross) — 낮은 값 썸이 높은 값을 넘어서면 두 값을 정렬해
low ≤ high를 유지합니다
Props#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
defaultValue | [number, number] | — | 초기 범위 — 없으면 [min, max] (비제어). 이후 상태는 내부 소유 |
value | [number, number] | — | 제어 범위 값 — 제공하면 제어 모드(내부 상태 무시, 모든 전환이 onChange로 통지) |
onChange | (value: [number, number]) => void | — | 범위 변경 통지 — 항상 정렬된 [low, high]. 제어/비제어 모두에서 호출 |
min · max · step | number | 0 · 100 · 1 | 네이티브 range 속성 — 두 입력에 동일 적용 |
aria-label | string | — | 두 썸 공통 라벨 기반 — "{label} 최소"/"{label} 최대"로 파생 |
aria-label-min · aria-label-max | string | — | 낮은/높은 값 썸 라벨 직접 지정 — 제공 시 aria-label 파생을 덮어씀 |
formatLabel | (value: number) => ReactNode | — | showValue 라벨 포매터(예: (v) => `${v}원`) + SR용 aria-valuetext 노출 |
showValue | boolean | false | 현재 범위 라벨 표시 — 시각 보조용(aria-hidden) |
disabled | boolean | — | 두 입력을 함께 비활성화 |
className | string | — | 루트(div)에 적용 — 폭 제어 등 레이아웃 조정용 |
접근성#
두 개의 네이티브 input[type="range"](낮은 값·높은 값)라 각각이 실제 슬라이더로
키보드·ARIA가 브라우저에서 보장됩니다. 단일 Slider와 같은 전략을
두 썸으로 확장한 별도 컴포넌트입니다.
| 키 | 동작 (각 썸, 네이티브) |
|---|---|
→ / ↑ | step만큼 증가 |
← / ↓ | step만큼 감소 |
Home / End | min / max로 점프 |
Tab | 낮은 값 썸 → 높은 값 썸 순으로 이동 |
- 각 썸은 자체
aria-label을 가집니다 —aria-label에서 "최소"/"최대"를 파생하거나aria-label-min/aria-label-max로 직접 지정합니다 formatLabel제공 시 두 입력에aria-valuetext노출 — SR이 원시 숫자 대신 포맷된 값("20원")을 읽도록 합니다(문자열·숫자 포맷만 직렬화, 복합 노드는 네이티브 값 낭독으로 폴백)showValue범위 라벨은 중복 낭독을 막기 위해aria-hidden- 채움 트랙은 순수 장식이라
aria-hidden— 값 정보는 두 슬라이더가 전달합니다
토큰#
component 토큰 없이 semantic을 직접 소비합니다(신설 기준 §4 미충족).
| 속성 | 토큰 |
|---|---|
| 트랙 | color.border · 높이 space.1 |
| 채움(두 썸 사이) | color.primary |
| 썸 | color.primary 채움 + shadow.sm · 크기 icon.size-md |
| 라운드 | radius.full |
| 히트 영역 | control.height-md (44px) |
| 값 라벨 | font.size-body-2 · color.text-muted |
| 비활성 | color.border-subtle 트랙 + color.text-placeholder 채움·썸 |