NumberField

A number field allows a user to enter numbers with a keyboard into a single-line input form element. The output can be formatted as a currency, decimal or percent value. The formatting of the NumberField can be changed through the formatOptions prop. The formatOptions object accepts all parameters of the built-in browser Intl.NumberFormat API.

Installyarn add @diallink-corp/convergo-react-numberfield
Version4.1.2
Usageimport {NumberField} from '@diallink-corp/convergo-react-numberfield'

Uncontrolled Value

By default, the NumberField component handles its value uncontrolled. In the uncontrolled variant you can pass in a defaultValue to set a value by default.

<NumberField label='Age' defaultValue={23} />
<NumberField label='Age' defaultValue={23} />
<NumberField
  label="Age"
  defaultValue={23}
/>

Controlled Value

You can also handle the value of the component in a controlled manner. To do so, you can pass in a value prop as well as an onChange handler to modify the value when the user types.

function Example() {
  const [value, setValue] = useState(23);

  return (
    <div>
      <NumberField 
        label='Age' 
        value={value} 
        onChange={setValue} 
      />

      <div>Value: {value}</div>
    </div>
  );
}
function Example() {
  const [value, setValue] = useState(23);

  return (
    <div>
      <NumberField 
        label='Age' 
        value={value} 
        onChange={setValue} 
      />

      <div>Value: {value}</div>
    </div>
  );
}
function Example() {
  const [
    value,
    setValue
  ] = useState(23);

  return (
    <div>
      <NumberField
        label="Age"
        value={value}
        onChange={setValue}
      />

      <div>
        Value: {value}
      </div>
    </div>
  );
}

Minimum Value

By default, the NumberField accepts both positive and negative values. If you would like to change this behaviour to only allow a minimum value, such as 0 for positive numbers, you can do this through the minValue prop.

<NumberField label='Age' minValue={0} />
<NumberField label='Age' minValue={0} />
<NumberField
  label="Age"
  minValue={0}
/>

Maximum Value

If you would like to set a maximum allowed value to the NumberField component you can use the maxValue prop.

<NumberField label='Age' maxValue={1000} />
<NumberField label='Age' maxValue={1000} />
<NumberField
  label="Age"
  maxValue={1000}
/>

Decimals

To format the NumberField with decimal values, you can use the minimumFractionDigits or maximumFractionDigits option.

<NumberField
  label="Value"
  defaultValue={19.50}
  formatOptions={{
    minimumFractionDigits: 1,
    maximumFractionDigits: 2
  }}
/>
<NumberField
  label="Value"
  defaultValue={19.50}
  formatOptions={{
    minimumFractionDigits: 1,
    maximumFractionDigits: 2
  }}
/>
<NumberField
  label="Value"
  defaultValue={19.50}
  formatOptions={{
    minimumFractionDigits:
      1,
    maximumFractionDigits:
      2
  }}
/>

Plus/Minus Sign

To display a plus or minus sign, you can leverage the signDisplay option, which will then append a plus or minus sign based on the value of the field.

<NumberField
  label="Age"
  defaultValue={23}
  formatOptions={{
    signDisplay: 'exceptZero'
  }}
/>
<NumberField
  label="Age"
  defaultValue={23}
  formatOptions={{
    signDisplay: 'exceptZero'
  }}
/>
<NumberField
  label="Age"
  defaultValue={23}
  formatOptions={{
    signDisplay:
      'exceptZero'
  }}
/>

Percentages

To format the NumberField with percentage values, you can use the style option.

<NumberField
  label="Sales tax"
  defaultValue={0.19}
  formatOptions={{
    style: 'percent'
  }}
/>
<NumberField
  label="Sales tax"
  defaultValue={0.19}
  formatOptions={{
    style: 'percent'
  }}
/>
<NumberField
  label="Sales tax"
  defaultValue={0.19}
  formatOptions={{
    style: 'percent'
  }}
/>

Currencies

To display a currency sign inside of the NumberField, you can leverage several options such as style, currency, currencyDisplay and currencySign. The style option defines that we want to use the currency formatting. The currency option then defines which currency we then want to display. If the style is "currency", the currency property must be provided. The currencyDisplay option defines how the currency formatting is displayed, so for example whether we want to use the symbol (€) or name (EUR) of the currency. Finally, the currencySign can define additional formatting. In many locales, the currencySign accounting format means to wrap the number with parentheses instead of appending a minus sign.

<NumberField
  label="Amount"
  defaultValue={55}
  formatOptions={{
    style: 'currency',
    currency: 'EUR',
    currencyDisplay: 'code',
    currencySign: 'accounting'
  }}
/>
<NumberField
  label="Amount"
  defaultValue={55}
  formatOptions={{
    style: 'currency',
    currency: 'EUR',
    currencyDisplay: 'code',
    currencySign: 'accounting'
  }}
/>
<NumberField
  label="Amount"
  defaultValue={55}
  formatOptions={{
    style: 'currency',
    currency: 'EUR',
    currencyDisplay:
      'code',
    currencySign:
      'accounting'
  }}
/>

Units

If you want to display a numeric value in units, such as inches or centimeters, you can do so by leveraging the style, unit and unitDisplay options. You can see a list of all available units in the ECMAScript definition. Pairs of simple units can be concatenated with "-per-" to make a compound unit. The unitDisplay option defines whether the unit should be fully spelled out or abbreviated.

<NumberField
  label="Container width"
  defaultValue={6}
  minValue={0}
  formatOptions={{
    style: 'unit',
    unit: 'inch',
    unitDisplay: 'long'
  }}
/>
<NumberField
  label="Container width"
  defaultValue={6}
  minValue={0}
  formatOptions={{
    style: 'unit',
    unit: 'inch',
    unitDisplay: 'long'
  }}
/>
<NumberField
  label="Container width"
  defaultValue={6}
  minValue={0}
  formatOptions={{
    style: 'unit',
    unit: 'inch',
    unitDisplay: 'long'
  }}
/>

Step Values

To snap the value of the NumberField to certain increments you can use the step prop. The allowed values are calculated starting from the minValue. So if you have a step=5 and a minValue=3, then the allowed values would be 3, 8, 13, 18, etc. If no minValue is defined, then the steps are calculated starting from 0 and can be moved in both positive and negative directions. You can always type any step, but on lur of the input, the value is being snapped back to the allowed step values.

<NumberField label="Step" step={10} />
<NumberField label="Step, minValue" step={6} minValue={6} />
<NumberField
  label="Step, minValue, maxValue"
  step={6}
  minValue={12}
  maxValue={60}
/>
<NumberField label="Step" step={10} />
<NumberField label="Step, minValue" step={6} minValue={6} />
<NumberField
  label="Step, minValue, maxValue"
  step={6}
  minValue={12}
  maxValue={60}
/>
<NumberField
  label="Step"
  step={10}
/>
<NumberField
  label="Step, minValue"
  step={6}
  minValue={6}
/>
<NumberField
  label="Step, minValue, maxValue"
  step={6}
  minValue={12}
  maxValue={60}
/>

Step Buttons

The NumberField renders two step buttons by default. These step buttons allow users to increase or decrease the value by simply clicking on them. On large devices, we render an up and down caret. On mobile devices, we change these buttons to plus and minus signs, which are attached to the left and right side of the component. Additionally, the user can change the values of the NumberField by using their scroll wheel, while focusing the component. However, you can also hide these step buttons with the showStepButtons prop. There is no need to pass the showStepButtons=, as it's assigned as a default value.

<NumberField label="With Step Buttons" showStepButtons={true} />
<NumberField label="Without Step Buttons" showStepButtons={false} />
<NumberField
  label="With Step Buttons"
  showStepButtons={true}
/>
<NumberField
  label="Without Step Buttons"
  showStepButtons={false}
/>
<NumberField
  label="With Step Buttons"
  showStepButtons={true}
/>
<NumberField
  label="Without Step Buttons"
  showStepButtons={false}
/>

Labeling

A NumberField component should be labeled with a visual text through the label prop. If the NumberField does not include a textual label, an aria-label or aria-labelledby prop need to be provided to support assistive technology such as screen readers.

<NumberField label='Age' />
<NumberField label='Age' />
<NumberField label="Age" />

Label Alignment

For languages that are read left-to-right (LTR), such as English, the label of the NumberField component is displayed on the left side of the input. For right-to-left (RTL) languages, such as Arabic, this is flipped. You can control the position of the label through the labelPlacement prop.

<NumberField label='Age' labelPlacement='top end' />
<NumberField label='Age' labelPlacement='top end' />
<NumberField
  label="Age"
  labelPlacement="top end"
/>

Label Position

By default, the label of the NumberField component is displayed above the input. With the labelPlacement prop this placement can be adjusted to be on the side of the input.

<NumberField label='Age' labelPlacement='side end' />
<NumberField label='Age' labelPlacement='side end' />
<NumberField
  label="Age"
  labelPlacement="side end"
/>

Required

To indicate to the user that the NumberField is required you can use the isRequired prop.

<NumberField label='Age' isRequired />
<NumberField label='Age' isRequired />
<NumberField
  label="Age"
  isRequired
/>

Validation

The NumberField component has built-in accessible validation support. To indicate whether the field is valid or not you can use the errorMessage prop.

function Example() {
  const [value, setValue] = useState(17);

  const isValidAge = value >= 18;

  return (
    <NumberField 
      label='Age' 
      value={value}
      onChange={setValue}
      errorMessage={!isValidAge && 'You must be atleast 18 years old.'} 
    />
  );
}
function Example() {
  const [value, setValue] = useState(17);

  const isValidAge = value >= 18;

  return (
    <NumberField
      label="Age"
      value={value}
      onChange={setValue}
      errorMessage={!isValidAge &&
        'You must be atleast 18 years old.'}
    />
  );
}
function Example() {
  const [
    value,
    setValue
  ] = useState(17);

  const isValidAge =
    value >= 18;

  return (
    <NumberField
      label="Age"
      value={value}
      onChange={setValue}
      errorMessage={!isValidAge &&
        'You must be atleast 18 years old.'}
    />
  );
}

Description

To give further instructions or more verbose examples to the user about a NumberField you can provide a description prop. Avoid using error like tone of voice of the message. If an errorMessage prop is provided it will replace the description.

<NumberField
  label="Age"
  description="An enumeration of the essential qualities of a thing or species"
/>
<NumberField
  label="Age"
  description="An enumeration of the essential qualities of a thing or species"
/>
<NumberField
  label="Age"
  description="An enumeration of the essential qualities of a thing or species"
/>

Placeholder

To give further instructions or examples to the user about a NumberField you can provide a placeholder prop.

<NumberField label='Age' placeholder='23' />
<NumberField label='Age' placeholder='23' />
<NumberField
  label="Age"
  placeholder="23"
/>

Contextual Help

To offer the user contextual help, the NumberField supports passing a contextualHelp prop, that accepts a ReactNode.

<NumberField 
  label='Age' 
  contextualHelp={(
    <ContextualHelp variant="info">
      <Header>
        <Heading>Lorem Ipsum</Heading>
      </Header>
      <Content>
        <Text>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        </Text>
      </Content>
    </ContextualHelp>
  )} 
/>
<NumberField
  label="Age"
  contextualHelp={
    <ContextualHelp variant="info">
      <Header>
        <Heading>Lorem Ipsum</Heading>
      </Header>
      <Content>
        <Text>
          Lorem ipsum dolor sit amet, consectetur
          adipiscing elit.
        </Text>
      </Content>
    </ContextualHelp>
  }
/>
<NumberField
  label="Age"
  contextualHelp={
    <ContextualHelp variant="info">
      <Header>
        <Heading>
          Lorem Ipsum
        </Heading>
      </Header>
      <Content>
        <Text>
          Lorem ipsum
          dolor sit
          amet,
          consectetur
          adipiscing
          elit.
        </Text>
      </Content>
    </ContextualHelp>
  }
/>

Disabled

The NumberField component can be disabled via the isDisabled prop.

<NumberField label='Age' defaultValue={23} isDisabled />
<NumberField label='Age' defaultValue={23} isDisabled />
<NumberField
  label="Age"
  defaultValue={23}
  isDisabled
/>

Read Only

The NumberField component can be marked as read only via the isReadOnly prop.

<NumberField label='Age' defaultValue={23} isReadOnly />
<NumberField label='Age' defaultValue={23} isReadOnly />
<NumberField
  label="Age"
  defaultValue={23}
  isReadOnly
/>

Accessibility

In order to support internationalization, provide a localized string to the label or aria-label prop.

API