Clawscale

Numeric input

A NumericInput takes a number. Buttons and arrow keys step the value up and down.

Usage#

import { NumericInput } from "@clawscale/react";
<NumericInput aria-label="Retention in days" min={1} onValueChange={(valueAsNumber) => setDays(valueAsNumber)} />

Name it with aria-label, and show a visible label with a FormGroup without labelFor. Do not pass id: the step buttons keep aria-controls on an id that Blueprint generates.

Interactions#

Hold a modifier key while you press an arrow key or click a button.

ModifierStepDefault
NonestepSize1
ShiftmajorStepSize10
AltminorStepSize0.1

Examples#

Basic#

NumericInput is uncontrolled by default. onValueChange reports the value as a number and as a string.

import { FormGroup, NumericInput } from "@clawscale/react";

export default function NumericInputBasic() {
  return (
    <FormGroup label="Retention" labelInfo="(days)">
      <NumericInput aria-label="Retention in days" defaultValue={30} />
    </FormGroup>
  );
}

Min, max and step sizes#

min and max stop the buttons and arrow keys at the bounds. Set a step size to null to turn off its modifier.

1 to 64. Shift steps by 8.
import { FormGroup, NumericInput } from "@clawscale/react";

export default function NumericInputStepSizes() {
  return (
    <FormGroup helperText="1 to 64. Shift steps by 8." label="Workers">
      <NumericInput
        aria-label="Workers"
        defaultValue={8}
        majorStepSize={8}
        max={64}
        min={1}
        minorStepSize={null}
        stepSize={1}
      />
    </FormGroup>
  );
}

Button position#

buttonPosition puts the buttons on the right (default) or left, or hides them with none. Arrow keys still work without buttons.

import { FormGroup, NumericInput } from "@clawscale/react";

export default function NumericInputButtonPosition() {
  return (
    <>
      <FormGroup label="Batch size">
        <NumericInput aria-label="Batch size" buttonPosition="left" defaultValue={500} />
      </FormGroup>
      <FormGroup label="Priority">
        <NumericInput aria-label="Priority" buttonPosition="none" defaultValue={3} />
      </FormGroup>
    </>
  );
}

Controlled#

Store the value as a string and update it from the second argument of onValueChange. A number would drop partial input such as 0. or -.

import { Button, ControlGroup, FormGroup, NumericInput } from "@clawscale/react";
import { useState } from "react";

export default function NumericInputControlled() {
  const [threshold, setThreshold] = useState("0.95");
  return (
    <FormGroup label="Alert threshold">
      <ControlGroup>
        <NumericInput
          aria-label="Alert threshold"
          majorStepSize={0.1}
          max={1}
          min={0}
          minorStepSize={0.001}
          stepSize={0.01}
          value={threshold}
          onValueChange={(_valueAsNumber, valueAsString) => setThreshold(valueAsString)}
        />
        <Button text="Reset" onClick={() => setThreshold("0.95")} />
      </ControlGroup>
    </FormGroup>
  );
}

Precision and clamping#

Steps round to the decimals of minorStepSize, or of stepSize when minorStepSize is null. clampValueOnBlur pulls a typed value back into range on blur. Format the value for display yourself, here with Intl.NumberFormat.

$1,250.50 per month
import { FormGroup, NumericInput } from "@clawscale/react";
import { useState } from "react";

const INITIAL_LIMIT = 1250.5;
const usd = new Intl.NumberFormat("en-US", { currency: "USD", style: "currency" });

export default function NumericInputPrecision() {
  const [limit, setLimit] = useState(INITIAL_LIMIT);
  return (
    <FormGroup helperText={`${usd.format(limit)} per month`} label="Spend limit">
      <NumericInput
        aria-label="Spend limit in US dollars"
        clampValueOnBlur
        defaultValue={INITIAL_LIMIT}
        leftIcon="dollar"
        majorStepSize={1000}
        max={10000}
        min={0}
        minorStepSize={0.01}
        stepSize={50}
        onValueChange={(value) => setLimit(Number.isNaN(value) ? 0 : value)}
      />
    </FormGroup>
  );
}

Interactive playground#

Props
Open dropdown
Range
0
30
1
30
730
365
View source on GitHub

Props interface#

NumericInput also accepts the HTML attributes of an <input>.

interface NumericInputProps extends InputSharedProps@clawscale/react
PropsDescription
allowNumericCharactersOnly
boolean = true
Whether to allow only floating-point number characters in the field, mimicking the native input[type="number"].
asyncControl
boolean
Set this to true if you will be controlling the value of this input with asynchronous updates. These may occur if you do not immediately call setState in a parent component with the value from the onChange handler.
buttonPosition
typeof Position.LEFT | typeof Position.RIGHT | "none" = Position.RIGHT
The position of the buttons with respect to the input field.
clampValueOnBlur
boolean = false
Whether the value should be clamped to [min, max] on blur. The value will be clamped to each bound only if the bound is defined. Note that native input[type="number"] controls do NOT clamp on blur.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
defaultValue
number | string = ""
In uncontrolled mode, this sets the default value of the input. Note that this value is only used upon component instantiation and changes to this prop during the component lifecycle will be ignored.
disabled
boolean = false
Whether the input is disabled.
Inherited from InputSharedProps
fill
boolean
Whether the component should take up the full width of its container.
Inherited from InputSharedProps
inputClassName
string
Class name to apply to the <input> element (not the InputGroup container).
Inherited from InputSharedProps
inputRef
React.Ref<HTMLInputElement>
Ref attached to the HTML <input> element backing this component.
Inherited from InputSharedProps
inputSize
HTMLInputProps["size"]
Alias for the native HTML input size attribute. see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/size
intent
Intent
Visual intent color to apply to element.
Inherited from IntentProps
largedeprecated
boolean = false
If set to true, the input will display with larger styling. This is equivalent to setting Classes.LARGE via className on the parent control group and on the child input group.
use size="large" instead
leftElement
React.JSX.Element
Element to render on the left side of input. This prop is mutually exclusive with leftIcon.
Inherited from InputSharedProps
leftIcon
IconName | MaybeElement
Name of a Blueprint UI icon to render on the left side of the input group, before the user's cursor.
Inherited from InputSharedProps
locale
string = ""
The locale name, which is passed to the component to format the number and allowing to type the number in the specific locale. See MDN documentation for more info about browser locale identification.
majorStepSize
number | null = 10
The increment between successive values when <kbd>shift</kbd> is held. Pass explicit null value to disable this interaction.
max
number
The maximum value of the input.
min
number
The minimum value of the input.
minorStepSize
number | null = 0.1
The increment between successive values when <kbd>alt</kbd> is held. Pass explicit null value to disable this interaction.
onButtonClick
(valueAsNumber: number, valueAsString: string): void
The callback invoked when the value changes due to a button click.
onValueChange
(valueAsNumber: number, valueAsString: string, inputElement: HTMLInputElement | null): void
The callback invoked when the value changes due to typing, arrow keys, or button clicks.
placeholder
string
Placeholder text in the absence of any value.
Inherited from InputSharedProps
readOnly
boolean = false
Whether the input is read-only.
Inherited from InputSharedProps
rightElement
React.JSX.Element
Element to render on right side of input. For best results, use a minimal button, tag, or small spinner.
Inherited from InputSharedProps
selectAllOnFocus
boolean = false
Whether the entire text field should be selected on focus.
selectAllOnIncrement
boolean = false
Whether the entire text field should be selected on increment.
size
Size = "medium"
Size of the input.
smalldeprecated
boolean = false
If set to true, the input will display with smaller styling. This is equivalent to setting Classes.SMALL via className on the parent control group and on the child input group.
use size="small" instead
stepSize
number = 1
The increment between successive values when no modifier keys are held.
value
number | string
The value to display in the input field.