ComponentsP3 본문

RangeSlider

두 네이티브 input[type="range"]를 겹친 두-썸 범위 슬라이더 — 각 썸이 실제 슬라이더라 키보드/ARIA는 네이티브가 보장하고, 두 썸은 교차 불가(low ≤ high). 비제어(defaultValue) 우선 + 제어(value/onChange).

마지막 업데이트 2026-06-12

한눈에#

가격대·연식·기간처럼 시작~끝 두 값(범위) 을 어림으로 고르는 두-썸 슬라이더입니다 — 두 썸은 교차하지 않습니다(low ≤ high).

  • 두-썸 범위
  • low ≤ high 교차 불가
  • 네이티브 range×2
  • showValue 라벨

각 썸이 실제 네이티브 슬라이더라 키보드·ARIA를 그대로 보장합니다

사용 시점#

시작~끝 두 값(범위)을 어림잡아 고르면 RangeSlider — 단일 값이나 정밀 정수는 다른 컴포넌트입니다.

쓴다

가격대·연식·기간처럼 교차하지 않는 두 값(low ≤ high) 범위 필터

대신 Slider

단일 값 하나만 조절할 때

대신 Input

정수를 정밀하게 입력해야 하는 범위일 때(두 개의 Input)

플레이그라운드#

컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.

import { RangeSlider } from '@wds/ui-web';

<RangeSlider
  aria-label="가격 범위"
  defaultValue={[20, 80]}
  min={0}
  max={100}
  step={5}
/>

변형#

showValue — 현재 범위 라벨이 실시간 갱신

formatLabel은 함수라 라이브 데모로 넘길 수 없어 코드로 안내합니다 — showValue 라벨과 두 입력의 aria-valuetext에 포맷된 값이 노출됩니다.

<RangeSlider
  aria-label="가격"
  min={0}
  max={200}
  step={10}
  defaultValue={[40, 160]}
  showValue
  formatLabel={(v) => `${v.toLocaleString()}원`}
/>
min · max · step — 네이티브 속성 그대로

크기#

단일 크기입니다 — 4px(space.1) 트랙 + 18px(icon.size-md) 썸 2개. 필드 높이는 control.height-md(44px)로 썸보다 큰 터치 타깃을 확보합니다. 두 썸 사이는 color.primary 채움 트랙으로 표시합니다(기하만 %, 색은 토큰).

상태#

Disabled
  • 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 · stepnumber0 · 100 · 1네이티브 range 속성 — 두 입력에 동일 적용
aria-labelstring두 썸 공통 라벨 기반 — "{label} 최소"/"{label} 최대"로 파생
aria-label-min · aria-label-maxstring낮은/높은 값 썸 라벨 직접 지정 — 제공 시 aria-label 파생을 덮어씀
formatLabel(value: number) => ReactNodeshowValue 라벨 포매터(예: (v) => `${v}원`) + SR용 aria-valuetext 노출
showValuebooleanfalse현재 범위 라벨 표시 — 시각 보조용(aria-hidden)
disabledboolean두 입력을 함께 비활성화
classNamestring루트(div)에 적용 — 폭 제어 등 레이아웃 조정용

접근성#

두 개의 네이티브 input[type="range"](낮은 값·높은 값)라 각각이 실제 슬라이더로 키보드·ARIA가 브라우저에서 보장됩니다. 단일 Slider와 같은 전략을 두 썸으로 확장한 별도 컴포넌트입니다.

동작 (각 썸, 네이티브)
/ step만큼 증가
/ step만큼 감소
Home / Endmin / 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 채움·썸