NumberField

Github
Storybook

A numeric input field with increment/decrement controls, value clamping, and keyboard support.

Importing

The component can be imported via:

import { NumberField } from '@customerio/pluma-components/react';

Usage

A NumberField accepts a numeric value and an onChange callback that receives a number | undefined. When the input is empty, onChange is called with undefined.

Like other form components, the component requires a label (or an ariaLabel or ariaLabelledby).

The value is: 5

import { NumberField, Paragraph } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState(5);

  return <>
    <NumberField
      label="Quantity"
      value={value}
      onChange={(value) => {
        setValue(value);
      }}
    />

    <Paragraph mt="100">
      The value is: {value === undefined ? 'empty' : value}
    </Paragraph>
  </>
}

Min, max, and step

The min and max props constrain the value. On blur, the value is clamped to these bounds. The step prop controls how much the value changes when using the increment/decrement controls or arrow keys. Defaults to 1.

The value is: 50

import { NumberField, Paragraph } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState(50);

  return <>
    <NumberField
      label="Opacity"
      min={0}
      max={100}
      step={5}
      value={value}
      onChange={(value) => {
        setValue(value);
      }}
    />

    <Paragraph mt="100">
      The value is: {value === undefined ? 'empty' : value}
    </Paragraph>
  </>
}

Precision

Use the precision prop to control the number of decimal places displayed.

import { NumberField } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState(3.14);

  return <NumberField
    label="Price"
    precision={2}
    step={0.01}
    min={0}
    value={value}
    onChange={(value) => {
      setValue(value);
    }}
  />
}

Hiding controls

Set withControls={false} to hide the increment/decrement buttons. Arrow key stepping still works.

import { NumberField } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState(10);

  return <NumberField
    label="Count"
    withControls={false}
    value={value}
    onChange={(value) => {
      setValue(value);
    }}
  />
}

Size

The size prop supports md (default) and sm.

import { NumberField, Stack } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [mdValue, setMdValue] = useState(10);
  const [smValue, setSmValue] = useState(10);

  return <Stack gap="200">
    <NumberField
      label="Medium"
      size="md"
      value={mdValue}
      onChange={setMdValue}
    />
    <NumberField
      label="Small"
      size="sm"
      value={smValue}
      onChange={setSmValue}
    />
  </Stack>
}

Disabled

import { NumberField } from '@customerio/pluma-components/react';

export default function Example() {
  return <NumberField
    label="Disabled field"
    value={5}
    isDisabled
  />
}

Error

Use the error prop for validation messages, or isInvalid for the red border alone.

import { NumberField } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState(150);

  return <NumberField
    label="Percentage"
    min={0}
    max={100}
    value={value}
    onChange={setValue}
    error={value !== undefined && value > 100 ? 'Must be 100 or less' : undefined}
  />
}

API

Element (or elements) that describe the form field. Also used for error messages, as aria-errormessage isn't supported in all assistive technologies: https://a11ysupport.io/tech/aria/aria-errormessage_attribute

String value that labels the form field.

Element (or elements) that label the form field.

Additional classes to be applied to the top-level container.

A description for the field, providing additional context or hints.

An error message associated with the form field. Boolean: Ember-only. If the error named block is used, this prop can be set to true to indicate an error is present, which will make the error block render.

An optional id to be assigned to the input element. Also used to generate ids for labels and error messages. If one isn't provided, it will be generated.

Whether the form field is disabled.

Whether the form field is in an invalid state.

The label text to show with the form field.

The maximum allowed value.

The minimum allowed value.

The name attribute is used for HTML forms

Called when the value changes. Receives undefined when the field is empty.

Placeholder text to show inside the field.

Default:0

Number of decimal places to display.

Whether to allow browser autofill and password managers. When false (default), adds attributes to disable password managers (1Password, LastPass, Bitwarden, Dashlane). Set to true for fields where autofill is desired (e.g., email, password, address fields).

Whether the generated description id should be included in the input's aria-describedby attribute. Disable this when a label`` tag surrounds the input as well as it's description text, for example in an OptionCard` component.

Whether the generated label id should be included in the input's aria-labelledby attribute. Disable this when the label tag surrounds the input as well as it's label text, for example in an OptionCard component.

By default, form elements will throw an error if no label or aria-label is provided. Disable this to suppress the error, for example when building a custom form element, and you want to handle labeling yourself.

Default:md

The size of the input element.

Default:1

The amount to increment or decrement by.

Pluma internal property to set a component name used for logging.

Additional classes to be applied to the description element.

Additional classes to be applied to the error element.

Additional classes to be applied to the field node.

Additional classes to be applied to the footer element.

Ember-only: this is used internally to detect whether a label named block is present, and to ignore empty label props if so.

Additional classes to be applied to the input node.

Sets the size attribute on the input element. This controls the visible width of the input in characters.

Additional classes to be applied to the div that wraps the input element.

Whether the component should render with "legacy" styles.

Additional classes to be applied to the label node.

The current numeric value. Pass undefined for an empty field.

Whether to apply the center-baseline variant.

Default:true

Whether to show the increment/decrement controls.

Ember only: a modifier to apply on the input's wrapper element.

React only: a ref to the input's wrapper element.