본문으로 건너뛰기
Amineslab UI

Component

NumberInput

표시용 포맷과 실제 숫자 값을 분리하는 입력입니다.

Playground

옵션을 조절하며 화면과 사용 코드를 함께 확인하세요.

PC 1280px
Controls

빈 입력 안내 · 사용처의 언어와 문구로 변경

blur 시 천 단위 구분 기호를 표시합니다.

Code
import { type InputProps, NumberInput } from '@amineslab/ui'

import { useState } from 'react'

function NumberExample({ showThousandsSeparator, size, textAlign, ...inputProps }: {
    showThousandsSeparator: boolean;
    size: string;
    textAlign: string;
} & Pick<InputProps, 'opaque' | 'variant' | 'invalid' | 'disabled' | 'startAdornment' | 'endAdornment' | 'placeholder' | 'autoComplete'>) {
    const [value, setValue] = useState<number | null>(12000);
    const resolvedSize = size === 'xs' || size === 'sm' || size === 'lg' || size === 'xl' ? size : 'md';
    const resolvedTextAlign = textAlign === 'end' ? 'end' : 'start';
    return (<div className="grid w-full max-w-sm gap-2">
      <NumberInput {...inputProps} aria-label="금액" showThousandsSeparator={showThousandsSeparator} size={resolvedSize} value={value} onValueChange={setValue} textAlign={resolvedTextAlign}/>
    </div>);
}

export default function ExamplePreview() {
  return ((<NumberExample {...({"placeholder":"금액을 입력해 주세요","opaque":false,"variant":"filled","invalid":false,"disabled":false,"startAdornment":"","endAdornment":"","showThousandsSeparator":true,"size":"md","textAlign":"start"} as const)} variant={"filled"}/>))
}

Props

import { NumberInput, formatNumeric, parseNumeric } from '@amineslab/ui'

NumberInput

Input props를 전달하면서 숫자 표시와 입력 정책을 추가합니다.

NameTypeDefaultDescription
placeholderstring-빈 입력 안내를 사용처의 언어·어투로 덮어씁니다. 빈 문자열로 숨길 수 있습니다.
valuenumber | null-소비자가 보관하는 실제 숫자입니다. 빈 입력은 null입니다.
onValueChange(value: number | null) => void-정규화된 숫자 또는 null을 전달합니다.
showThousandsSeparatorbooleantrueblur 상태에서 천 단위 구분 기호를 표시합니다.
textAlign'start' | 'end''start'표시 문자열 정렬입니다.
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'기본 Input 밀도입니다.
invalidbooleanfalse오류 테두리를 표시하며 focus·open 상태에서도 유지합니다. aria-invalid도 함께 전달합니다.
variant'filled' | 'outline'filled공통 필드 표면 표현입니다. focus·hover는 중립 elevation을 사용합니다.
opaquebooleanfalseelevation 레이어 아래 불투명한 테마 바탕을 추가합니다. hover·focus·invalid 표현은 유지합니다.
startAdornment / endAdornmentReactNode | IconComponent-Input과 동일하게 아이콘 컴포넌트·문자열·ReactNode를 받습니다. PasswordInput의 표시 버튼은 오른쪽 슬롯과 함께 배치됩니다.

Examples

자주 쓰는 조합을 살펴보고, 필요한 예시의 코드를 펼쳐 확인하세요.

공통 필드 표면

variant는 filled·outline 표현을, opaque는 elevation 아래의 불투명 바탕을 정합니다. focus와 hover는 중립 elevation을 사용하고 invalid 테두리는 포커스 중에도 유지합니다. NumberInput·PhoneInput·PasswordInput은 Input의 아이콘·문자열·ReactNode 슬롯을 상속합니다. SelectField에서는 같은 표면 props를 직접 지정하거나 triggerProps로 세부 설정할 수 있습니다.

투명 바탕
원
불투명 바탕
원
Outline + 불투명 바탕
원
<NumberInput value={amount} onValueChange={setAmount} endAdornment="원" />

<NumberInput value={amount} onValueChange={setAmount} endAdornment="원" opaque />

<NumberInput value={amount} onValueChange={setAmount} endAdornment="원" variant="outline" opaque />

표시값과 실제값 분리

입력 중에는 편집 문자열을, blur 후에는 읽기 좋은 표시값을 사용합니다.

import { type InputProps, NumberInput } from '@amineslab/ui'

import { useState } from 'react'

function NumberExample({ showThousandsSeparator, size, textAlign, ...inputProps }: {
    showThousandsSeparator: boolean;
    size: string;
    textAlign: string;
} & Pick<InputProps, 'opaque' | 'variant' | 'invalid' | 'disabled' | 'startAdornment' | 'endAdornment' | 'placeholder' | 'autoComplete'>) {
    const [value, setValue] = useState<number | null>(12000);
    const resolvedSize = size === 'xs' || size === 'sm' || size === 'lg' || size === 'xl' ? size : 'md';
    const resolvedTextAlign = textAlign === 'end' ? 'end' : 'start';
    return (<div className="grid w-full max-w-sm gap-2">
      <NumberInput {...inputProps} aria-label="금액" showThousandsSeparator={showThousandsSeparator} size={resolvedSize} value={value} onValueChange={setValue} textAlign={resolvedTextAlign}/>
    </div>);
}

export default function ExamplePreview() {
  return (<NumberExample showThousandsSeparator size="md" textAlign="start"/>)
}

NumberField로 사용하기

NumberField는 기본 입력에 label·required·description·error를 함께 제공합니다. FormStack 안에 직접 넣으며 FormField로 다시 감싸지 않습니다.

원

라벨·설명·필수 표시를 Field가 함께 처리합니다.

import { useState } from 'react'

import { NumberField } from '@amineslab/ui'

const fieldDescription = '라벨·설명·필수 표시를 Field가 함께 처리합니다.';

function NumberFieldExample() {
    const [value, setValue] = useState<number | null>(null);
    return (<NumberField label="금액" description={fieldDescription} required value={value} onValueChange={setValue} endAdornment="원"/>);
}

export default function ExamplePreview() {
  return (<NumberFieldExample />)
}

사용 기준

권장하는 사용
  • 값은 number 또는 null로 보관하고, showThousandsSeparator는 표시 계층에만 적용합니다.
  • 입력한 소수점 등 편집 문자열은 유지하되 외부 value 변경은 포커스 중에도 반영합니다.
  • IME 조합 중에는 값을 전달하지 않고 완료한 뒤 정규화합니다.
피해야 할 사용
  • 겉모양만으로 사용을 결정하지 마세요.
  • 의미와 키보드 동작, 모바일에서의 흐름을 함께 확인하세요.

접근성

화면에 맞는 이름을 제공하고, 키보드만으로 작업을 마칠 수 있는지 확인하세요.

  • Tab: 입력으로 이동하고 포커스 중에는 구분 기호가 사라집니다.
  • 조합 입력: 조합 중 문자열을 보존하고 완료 시 숫자 형식으로 정규화합니다.