ComponentsP3 본문

QuantityStepper

수량 증감 입력기 — −/값/+ 구성에 min·max·step 클램핑. 진행 단계 Stepper와 역할이 달라 별도 이름을 씁니다(ADR-012 Track C).

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

한눈에#

장바구니 수량·인원수처럼 정수를 ±step 단위로 정밀하게 증감하는 −/값/+ 입력기입니다.

  • −/값/+ 구성
  • min·max·step 클램프
  • 2 크기(md·sm)
  • 44px 히트 영역

값 칸은 직접 타이핑·화살표 키 증감 모두 가능하고, 한계 도달 시 해당 버튼이 비활성됩니다

진행 단계 표시기 Stepper와 이름이 비슷하지만 역할이 다릅니다 — 이쪽은 수량 입력, Stepper는 진행 단계 표시입니다.

사용 시점#

정수를 ±step 단위로 정밀 증감하면 QuantityStepper — 어림 조절이나 진행 단계 표시는 다른 컴포넌트입니다.

권장 — 이렇게 쓰세요

지양 — 이러지 마세요

쓴다장바구니 수량·인원수처럼 min/max 클램프 + −/+ 버튼이 필요한 정수 증감

대신 Slider볼륨·밝기처럼 어림값으로 충분한 연속 조절

대신 Stepper진행 단계(스텝 1·2·3) 표시 — 이름만 비슷하고 역할이 다름

플레이그라운드#

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

QuantityStepper를 직접 조작해 보세요

속성·테마·토큰을 바꾸고 React·Flutter 코드를 확인하는 풀스크린 빌더로 엽니다.

빌더 열기

플레이그라운드는 넓은 작업 영역이 필요해 웹·태블릿에서 편집할 수 있어요.

해부#

/값/+ 위에 토큰 실측을 핀으로 얹습니다 — 컨테이너는 입력 어휘(input.*)를 재사용하고, 값이 바뀌면 핀도 함께 움직입니다(드리프트 0).

md · −/값/+ — 실물 렌더 위에 토큰 실측을 핀으로 표기
height
44pxinput.height (control.height-md)
button
32pxcontrol.height-sm
button hit
44px (::after)
icon
20pxicon.size-md
gap
4pxspace-1
radius
10pxinput.radius (control)
border
1pxinput.border

컨테이너 높이는 input.height(=control.height-md 44px)로 같은 줄의 Input·Select와 자동 정렬됩니다. /+ 버튼은 시각 32px(control.height-sm)이지만 히트 영역은 ::after로 44px까지 확장됩니다.

변형#

단일 형태입니다 — /값/+ 구성. 값 칸은 직접 타이핑할 수 있고, 위/아래 화살표 키로도 증감합니다. step으로 증감 단위를, min/max로 범위를 정합니다.

크기#

size로 2단 — md(기본)·sm. 컨테이너 높이만 줄고 버튼 시각·아이콘은 공유하며, 두 크기 모두 −/+ 버튼의 히트 영역을 44px로 유지해 터치 타깃을 보장합니다.

md · sm — 공유 베이스라인에서 컨테이너 높이차 비교
sizeheightbuttoniconhit areamd44px (input.height)32px20px44pxsm32px (control.height-sm)32px20px44px

상태#

비제어 컴포넌트입니다 — defaultValue로 시작하고 clamp된 값이 실제로 바뀔 때만 onChange가 발화합니다. 상·하한에서는 해당 버튼이 비활성화되고, 한계 도달 시 중복 발화하지 않습니다. 직접 입력한 값은 [min, max]로 clamp되며, 비숫자 입력은 무시하고 blur 시 마지막 유효값으로 복원합니다.

min/max 경계 — 상·하한에서 버튼 비활성

Props#

Prop타입기본값설명
aria-labelstring값 입력의 접근 이름(예: "수량") — 필수. 루트 group은 컨트롤을 묶기만 한다(중복 announce 회피)
defaultValuenumber비제어 초기값 — 생략 시 min(있으면) 또는 0
onChange(value: number) => voidclamp된 값이 실제로 바뀔 때만 발화
minnumber0하한 — 기본 0
maxnumber상한 — 기본 없음(무제한)
stepnumber1증감 단위 — 기본 1
disabledbooleanfalse입력·버튼 모두 비활성
size'sm' | 'md'md컨트롤 크기 — md(기본) | sm
refRef<HTMLInputElement>수량 <input>으로 직결되는 ref — 증감 버튼이 아닌 텍스트 입력 요소 (React 19 ref-as-prop)

접근성#

  • 루트는 role="group"으로 −/값/+ 를 하나의 컨트롤로 묶습니다(이름 중복 announce를 피하기 위해 이름은 값 입력에만 둡니다).
  • 값 입력은 inputMode="numeric" + aria-label(필수)을 가지며, ArrowUp/ArrowDown으로 증감합니다.
  • /+ 버튼은 각각 aria-label(“감소”/“증가”)을 가지고, 한계 도달 시 disabled 됩니다.
  • 입력은 경계에서 신뢰하지 않습니다 — 숫자만 받고 [min, max]로 clamp, 비숫자는 거부합니다.

토큰#

component 토큰 없이 semantic(+input 어휘)을 직접 소비합니다(신설 기준 §4 미충족).

속성토큰
컨테이너input.height · input.bg · input.border(focus input.border-focus) · input.radius
버튼control.height-sm 시각 + 44px 히트 · color.text-muted(hover surface-hover → active surface-pressed) · radius.control
값/비활성input.fg · color.disabled-fg
포커스컨테이너 color.primary 18% 링 · 버튼 color.focus-ring 2px 아웃라인
모션duration.fast + ease.standard