본문으로 건너뛰기

NumberField

숫자만 입력받는 필드입니다. 값을 단계적으로 올리고 내리는 stepper, 범위 제한, 서식 표시가 함께 제공됩니다.

tsx
import { NumberField } from 'neba';

<NumberField label="좌석" defaultValue={3} min={1} max={20} />;

Props

Prop타입기본값설명
variant공통'solid' | 'outline' | 'text''outline'표면의 무게. TextField와 같은 셸입니다
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl''md'높이와 타입 스케일. 스테퍼는 em이므로 숫자를 따라갑니다
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'의미론적 색 역할. 표면은 흰색이므로 가장자리·포커스 링·캐럿·스테퍼의 호버에 나타납니다
density공통'default' | 'compact''default'여백만 바꿉니다. 높이와 글자 크기는 그대로
elevation공통0 | 1 | 2 | 30그림자 깊이. 0은 그림자 없음
valuenumber | null값. null이 비어 있음입니다. 파싱해야 하는 문자열이 아닙니다
defaultValuenumber초기 값
onValueChange(value: number | null) => void값이 바뀔 때마다. 타이핑, 스테핑, 휠
onValueCommitted(value: number | null) => void값이 자리를 잡을 때. 타이핑 후 blur, 누르기를 뗄 때
minnumber범위의 시작. 스테핑은 여기서 멈춥니다
maxnumber범위의 끝
stepnumber | 'any'1한 걸음의 크기. any는 step 검증을 끕니다
largeStepnumber10Shift를 누른 채의 한 걸음
smallStepnumber0.1Alt를 누른 채의 한 걸음
snapOnStepbooleanfalse스테핑이 step의 배수에 붙는지
allowWheelScrubbooleanfalse포커스된 채 호버 중일 때 휠이 값을 바꾸는지. 포인터 아래에서 스크롤되는 페이지와 바뀌는 필드는 같은 제스처이고, 의도된 것은 하나뿐입니다
formatIntl.NumberFormatOptions숫자를 어떻게 쓸지, 통화, 백분율, 소수 자릿수. 필드는 $1,240을 보여 주고 값으로는 1240을 보고합니다
localeIntl.LocalesArgument어느 로케일로 쓰고 읽을지. 기본은 런타임의 것. BCP 47 문자열이면 두 스테퍼의 이름도 이 언어로 씁니다
steppers'end' | 'split' | 'none''end'스테퍼가 앉는 자리. split은 숫자 양옆, none은 버튼 없음
labelReactNode컨트롤과 연결되는 라벨. Base UI Field가 묶어 줍니다
descriptionReactNode보조 설명
errorReactNode오류 메시지. 값이 있으면 invalid 상태도 함께 켜지고 색 계열이 danger로 넘어갑니다
invalidboolean!!error메시지 없이 invalid만 켭니다. 외부 폼 라이브러리가 유효성을 가질 때
startIconReactNode숫자 앞에 놓이는 내용, 통화 기호, 단위
endIconReactNode숫자 뒤, 스테퍼 앞에 놓이는 내용
fullWidthbooleanfalse컨테이너 너비만큼 확장
incrementLabelstring증가 버튼의 접근성 이름
decrementLabelstring감소 버튼의 접근성 이름
namestring폼 제출 시의 필드 이름
readOnlybooleanfalse값은 보이지만 바꿀 수 없음. 색과 가장자리는 유지한 채 채도만 빠집니다
disabledbooleanfalse사용 불가. 색 계열을 버리고 중립 회색이 됩니다
shortcutsNebaShortcuts<HTMLInputElement>Shortcut이 그리는 그대로 쓴 키 조합과 그때 할 일. { 'Mod+Enter': send } 형태입니다. Mod는 Mac에서 Command, 나머지에서 Control입니다. root가 아니라 input에 붙습니다. onKeyDown은 라벨과 메시지가 함께 있는 열에 떨어지므로 currentTarget이 필드가 아닙니다
placeholderstring값이 없을 때 필드에 보이는 글자
requiredboolean폼을 제출하기 전에 값이 있어야 하는지
classNamesNebaSlots<'label' | 'shell' | 'control' | 'description' | 'error' | 'stepper'>루트 뒤에 있는 각 파트의 class. 루트 자체는 className이 맡으므로 root 키는 없습니다

<div>의 native 속성은 root로 전달됩니다. colordefaultValue만 위 표와 이름이 겹쳐 제외됩니다.

value의 타입은 number | null이며 null이 비어 있음을 뜻합니다. 파싱해야 하는 문자열이 아닙니다.

shell은 TextField와 동일하므로 같은 size의 필드와 한 줄에 놓을 수 있습니다.

예시

steppers

end는 필드 오른쪽에 증감 버튼을 모아 놓습니다. split은 숫자 양옆에 마이너스와 플러스를 두어 눌러서 맞추는 수량에 적합합니다. none은 버튼을 없애고 키보드 입력만 남깁니다.

step · largeStep · smallStep

방향키는 step만큼, Shift와 함께 누르면 largeStep만큼, Alt와 함께 누르면 smallStep만큼 값을 움직입니다. snapOnStep은 그 결과를 step의 배수에 맞춥니다.

allowWheelScrub은 기본값이 꺼짐입니다. 켜면 필드 위에서 휠로 값을 조절할 수 있지만, 페이지 스크롤과 같은 제스처를 공유하게 됩니다.

format과 locale

formatIntl.NumberFormatOptions입니다. 필드가 $1,240이나 7.5%를 보여 주더라도 value1240, 0.075로 유지됩니다.

variant

size

stepper는 em 단위로 그려지므로 숫자 크기를 따라갑니다. 같은 sizeButton · TextField · Select와 높이가 맞습니다.

disabled · readOnly · error

readOnly는 stepper를 비활성 상태로 남기지 않고 아예 제거합니다. 숫자는 여전히 선택해서 복사할 수 있습니다.

shortcuts

shortcuts는 키 조합에서 할 일로 가는 map이고, 조합은 Shortcut이 그리는 표기 그대로 씁니다. Mod는 Mac에서 Command, 그 밖에서는 Control이며 modifier는 정확히 일치해야 하므로 EnterMod+Enter가 함께 발동하는 일은 없습니다.

tsx
<NumberField label="수량" shortcuts={{ Enter: commit }} />

root가 아니라 <input>에 붙는다는 점이 여기서는 중요합니다. classNameonKeyDown도 라벨과 아래 두 줄을 담는 열에 떨어지므로 currentTarget이 필드가 아닙니다.

대신 preventDefault를 해 주지는 않습니다. ArrowUp에 건 shortcut은 실행되고 동시에 값도 한 칸 올라갑니다. 그러지 않아야 한다면 핸들러에서 직접 막으세요.

classNames

className은 루트(라벨과 shell, 그 아래 두 줄을 담는 열)에 붙고, <input> 자체는 classNames.control로 갑니다.

tsx
<NumberField label="Seats" classNames={{ control: 'text-right', stepper: 'rounded-none' }} />

slot은 label, shell, control, description, error, stepper입니다. stepper는 증가·감소 버튼을 따로 두지 않고 하나로 받습니다. 서로 다르게 생긴 stepper 한 쌍을 만들려는 사람은 없기 때문입니다. 넘긴 class가 컴포넌트 자신의 class와 어떻게 겨루는지는 prop 규약을 보세요.

접근성

  • 보이는 컨트롤은 inputmode="numeric"aria-roledescription을 가진 텍스트 입력이고, 그 옆에 min · max · step을 들고 있는 hidden <input type="number">가 폼 제출과 브라우저 검증을 담당합니다. 이렇게 나뉘어 있어 보이는 필드가 $1,240 같은 서식을 표시할 수 있습니다.
  • label이 accessible name이 되고, stepper 버튼의 이름은 incrementLabeldecrementLabel이 정합니다.
  • stepper는 tab 순서에서 빠져 있습니다. 필드의 방향키가 같은 일을 합니다.
  • min이나 max에 도달한 stepper는 disabled가 됩니다.
  • 두 스테퍼의 접근성 이름은 locale이 정합니다. BCP 47 문자열을 넘기면 숫자와 버튼이 같은 언어로 읽힙니다.

Released under the MIT License