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.
| Modifier | Step | Default |
|---|---|---|
| None | stepSize | 1 |
| Shift | majorStepSize | 10 |
| Alt | minorStepSize | 0.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.
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.
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 interface#
NumericInput also accepts the HTML attributes of an <input>.
interface NumericInputProps extends InputSharedProps@clawscale/react| Props | Description |
|---|---|
allowNumericCharactersOnly | boolean = trueWhether to allow only floating-point number characters in the field, mimicking the native input[type="number"]. |
asyncControl | booleanSet 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.RIGHTThe position of the buttons with respect to the input field. |
clampValueOnBlur | boolean = falseWhether 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 | stringA 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 = falseWhether the input is disabled. Inherited from InputSharedProps |
fill | booleanWhether the component should take up the full width of its container. Inherited from InputSharedProps |
inputClassName | stringClass name to apply to the Inherited from <input> element (not the InputGroup container).InputSharedProps |
inputRef | React.Ref<HTMLInputElement>Ref attached to the HTML Inherited from <input> element backing this component.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 | IntentVisual intent color to apply to element. Inherited from IntentProps |
largedeprecated | boolean = falseIf 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.ElementElement to render on the left side of input. This prop is mutually exclusive with Inherited from leftIcon.InputSharedProps |
leftIcon | IconName | MaybeElementName 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 = 10The increment between successive values when <kbd>shift</kbd> is held. Pass explicit null value to disable this interaction. |
max | numberThe maximum value of the input. |
min | numberThe minimum value of the input. |
minorStepSize | number | null = 0.1The increment between successive values when <kbd>alt</kbd> is held. Pass explicit null value to disable this interaction. |
onButtonClick | (valueAsNumber: number, valueAsString: string): voidThe callback invoked when the value changes due to a button click. |
onValueChange | (valueAsNumber: number, valueAsString: string, inputElement: HTMLInputElement | null): voidThe callback invoked when the value changes due to typing, arrow keys, or button clicks. |
placeholder | stringPlaceholder text in the absence of any value. Inherited from InputSharedProps |
readOnly | boolean = falseWhether the input is read-only. Inherited from InputSharedProps |
rightElement | React.JSX.ElementElement to render on right side of input. For best results, use a minimal button, tag, or small spinner. Inherited from InputSharedProps |
selectAllOnFocus | boolean = falseWhether the entire text field should be selected on focus. |
selectAllOnIncrement | boolean = falseWhether the entire text field should be selected on increment. |
size | Size = "medium"Size of the input. |
smalldeprecated | boolean = falseIf 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 = 1The increment between successive values when no modifier keys are held. |
value | number | stringThe value to display in the input field. |