> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Number Field - Web

> Number Field is the standard component for accepting numerical input, featuring optional increment/decrement buttons and configurable step values.

> [!NOTE]
>
> For development, import `NumberField` from
> `@servicetitan/anvil2`. For design, find it in the
> [Anvil2 file](https://www.figma.com/design/xaNQsvRKczoxu7pj0M6QT8/Anvil2-v3?node-id=234-3070).

![](https://mintcdn.com/servicetitan/uz2PQSvO75TRhQ38/images/docs/web/components/shared/main-image-of-number-field.png?fit=max\&auto=format\&n=uz2PQSvO75TRhQ38\&q=85\&s=d3715d7ae36c2be21e44d993cd66b767)

## Anatomy

The Number Field consists of seven primary elements that work together to accept numerical input.

![number field
anatomy](https://mintcdn.com/servicetitan/aip5_7K1pHSn1Axn/images/docs/web/components/number-field/design/number-field-anatomy.png?fit=max\&auto=format\&n=aip5_7K1pHSn1Axn\&q=85\&s=0658f58638611710f88631e9924952a2)

1. Label
2. Field
3. Placeholder
4. Increment/Decrement buttons
5. Prefix
6. Suffix
7. Helper texts

## Options

The Number Field supports the following configurations to accommodate various numerical input scenarios.

### Sizes

numberfield-size

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-size?file=src/App.tsx)

```tsx lines theme={null}
import { NumberField, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex direction="column" gap="3">
      <NumberField defaultValue={0} size="small" />
      <NumberField defaultValue={0} size="medium" />
      <NumberField defaultValue={0} size="large" />
    </Flex>
  );
}

export default App;
```

| Size | Height |
| - | - |
| Small | 2rem (32px) |
| Medium (default) | 2.5rem (40px) |
| Large | 3rem (48px) |

### Prefix

numberfield-prefix

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-prefix?file=src/App.tsx)

```tsx lines theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField defaultValue={0} prefix="Qty:" />;
}

export default App;
```

### Suffix

numberfield-suffix

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-suffix?file=src/App.tsx)

```tsx lines theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField defaultValue={0} suffix="items" />;
}

export default App;
```

## Behavior

The Number Field responds to user interaction with distinct visual states and flexible width behaviors.

### Overflow

numberfield-overflow

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-overflow?file=src/App.tsx)

```tsx lines theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <NumberField defaultValue={1000000000000} style={{ maxWidth: "180px" }} />
  );
}

export default App;
```

For long number entries, the content within a Number Field will scroll horizontally. The visible portion of the text will automatically follow the cursor, ensuring the user can always see what they're typing.

### Visual States

numberfield-data-interactive

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-data-interactive?file=src/App.tsx)

```tsx lines theme={null}
import { NumberField, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex direction="column" gap="3">
      <NumberField defaultValue={0} />
      <NumberField defaultValue={0} readOnly />
      <NumberField defaultValue={0} error />
      <NumberField defaultValue={0} loading />
    </Flex>
  );
}

export default App;
```

### Widths

numberfield-width

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-width?file=src/App.tsx)

```tsx lines theme={null}
import { NumberField, Grid } from "@servicetitan/anvil2";

function App() {
  return (
    <Grid gap="6">
      <div style={{ width: "100px" }}>
        <NumberField label="Label" />
      </div>
      <div style={{ width: "200px" }}>
        <NumberField label="Label" />
      </div>
      <NumberField label="Label" />
    </Grid>
  );
}

export default App;
```

Number Fields should generally be sized to the expected length of the value a user will enter. Unless a specific width is set, the field will automatically fill all available horizontal space.

## Usage Guidelines

Number Field is the standard component for any numeric input that doesn't have a dedicated component. It's designed for general-purpose numeric values and allows you to use decimals, define step values, and set boundary limits.

| Standard | Requirement |
| - | - |
| DoEntering quantities | Use Number Field for counts, such as the number of items in an order. |
| DoEntering measurements | Use Number Field for values like height, weight, or distance, and add a suffix to show the unit. |
| DoEntering numeric IDs and codes | Use Number Field for numerical identifiers, such as account numbers. |

**Note:** Dedicated components such as Percentage Field and Currency Field are planned to handle those specific use cases.

### How to Use

#### Read-only

Using a read-only Number Field is the recommended way to display information that users can review but not change. Unlike a disabled field, a read-only field remains fully accessible: users can still copy the text, focus the input, and interact with it using a screen reader. Additionally, it maintains the necessary contrast for optimal readability.

#### Prefixes and suffixes

Prefixes and suffixes provide clear context for a Number Field, preventing any misunderstanding of the value being entered.

##### Prefix

Use a prefix to add a descriptive label to the left of the input. For example, using Qty: helps a user immediately understand the purpose of the number they are entering.

##### Suffix

Use a suffix to provide a unit of measurement or another clarifying label to the right of the input. This is useful for units like items, minutes, or lbs.

##### Hiding/Showing the +/- controls

Hide the +/- controls when the value is something a user needs to type precisely rather than step through, such as an account number or ID. In those cases, the buttons add no value and should be omitted.

Show the +/- buttons when the value has a meaningful, predictable step, such as a quantity. When users will nudge a value up or down by a consistent amount and the range is small enough to navigate that way, the buttons make the interaction faster and more forgiving than typing. This works well when the value has a defined step and range.

#### Labels and Help text

For guidance on labels and help text, check out our [Labels and Help](https://anvil.servicetitan.com/docs/patterns/forms/web.md#labels-and-help) pattern.

#### Validation

For form validation guidance, check out our [Form Errors and Validation](https://anvil.servicetitan.com/docs/patterns/errors-and-warnings/web.md#form-errors-and-validation) pattern.

## Content

Content within the Number Field should clearly communicate the expected numerical value through labels, prefixes, and suffixes.

## Keyboard Interaction

Users can navigate the Number Field using standard keyboard controls.

## Code

**Implementation**

numberfield-playground

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-playground?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <NumberField
      label="Label"
      placeholder="Placeholder"
      hint="Hint text"
      moreInfo="More info"
      size="large"
      required
      loading
      error={false}
      style={{ maxWidth: "180px" }}
    />
  );
}

export default App;
```

## Common Examples

```tsx theme={null}
import { NumberField } from "@servicetitan/anvil2";

function ExampleComponent() {
  return <NumberField label="Quantity" />;
}
```

### Default values

A default value can given to `NumberField` to use the field in an uncontrolled mode.

numberfield-defaultvalue

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-defaultvalue?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField defaultValue={1337} />;
}

export default App;
```

### Controlled usage

The `NumberField` can be controlled. This means you can maintain the state outside the component. Listen for new values with `onChange` and supply state back into the `value` prop.

numberfield-controlled

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-controlled?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField, Flex, Button } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [value, setValue] = useState<number | null>(null);

  const handleChange = (value: number | null) => {
    setValue(value);
  };

  return (
    <Flex direction="column" gap="4">
      <NumberField
        label="Controlled Example"
        value={value}
        onChange={handleChange}
      />
      <Button
        onClick={() => {
          setValue(11);
        }}
      >
        Set to 11
      </Button>
    </Flex>
  );
}

export default App;
```

### Empty

The `NumberField` allows not only `0`, but also the ability for the input to be completely cleared out. This is represented by `null` in the `onChange`, `value`, and `defaultValue` props.

numberfield-null

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-null?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField, Flex, Button } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [value, setValue] = useState<number | null>(null);

  const handleChange = (value: number | null) => {
    setValue(value);
  };

  return (
    <Flex direction="column" gap="4">
      <NumberField label="Example" value={value} onChange={handleChange} />
      <Button
        onClick={() => {
          setValue(null);
        }}
      >
        Set to null
      </Button>
    </Flex>
  );
}

export default App;
```

### Step value

The increment and decrement functionality of the `NumberField` defaults to adding or subtracting `1`, but can be modified to add or subtract another number. This value applies to the visual +/- buttons as well as keyboard up/down keys.

numberfield-step

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-step?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField label="Step by 3" step={3} />;
}

export default App;
```

Note that `step` does not enforce that the value is a multiple of the step. Instead, it will add to or subtract from the current value.

### Min and max values

The `minValue` and `maxValue` props define the bounds of the `NumberField`. The stepper buttons and keyboard up/down keys clamp the value between `minValue` and `maxValue`: if `value` + `step` > `maxValue`, the result of incrementing is `maxValue`, and if `value` - `step` \< `minValue`, the result is `minValue`.

numberfield-minvaluemaxvalue

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-minvaluemaxvalue?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <NumberField
      label="Step by 3"
      defaultValue={13}
      step={3}
      minValue={11}
      maxValue={22}
      description="Min 11, max 22"
    />
  );
}

export default App;
```

> [!WARNING]
>
> `minValue` and `maxValue` do not strongly prevent the user from entering an out-of-bounds value by typing or pasting. The component does not validate input internally. When bounds must be enforced, handle validation in your own code and surface feedback via the `error` prop. See [Errors](#errors) for an example.

numberfield-validation

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-validation?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <NumberField
      defaultValue={123456789}
      maxValue={100}
      description={"Max value: 100"}
    />
  );
}

export default App;
```

### Negative values

The `NumberField` defaults to a minimum of `0`, but supports negative number inputs by setting a lower `minValue`.

numberfield-negative

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-negative?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField defaultValue={-100} minValue={-1000} />;
}

export default App;
```

### Fractional values

The `NumberField` defaults to integers, but supports decimal number inputs with the `maximumFractionDigits` and `minimumFractionDigits` props.

numberfield-minimumfractiondigits

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-minimumfractiondigits?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <NumberField
      label="Decimal numbers"
      defaultValue={3.5}
      minimumFractionDigits={2}
    />
  );
}

export default App;
```

> [!WARNING]
>
> Be careful! Forgetting to set `minimumFractionDigits` or `maximumFractionDigits` can result in your numbers being rounded unexpectedly.

numberfield-rounding

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-rounding?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField defaultValue={3.5} description="Default value: 3.5" />;
}

export default App;
```

### Hiding increment/decrement buttons

numberfield-hide-controls

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-hide-controls?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";

function App() {
  return <NumberField label="Account Number" hideControls />;
}

export default App;
```

The +/- buttons can be optionally hidden using the `hideControls` prop. When hidden, users can still change the value by typing directly into the input or using keyboard up/down arrow keys.

### Errors

Error messages can be applied to the component via the `error` prop.

numberfield-error

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-error?file=src/App.tsx)

```tsx lines expandable theme={null}
import { NumberField } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [value, setValue] = useState<number | null>(0);

  return (
    <NumberField
      label="Quantity"
      description="Type an even number"
      value={value}
      onChange={setValue}
      error={(value ?? 0) % 2 !== 0 ? "Must be an even amount" : ""}
    />
  );
}

export default App;
```

> [!WARNING]
>
> The component does not do validation internally. For example, it may be possible for a user to enter a value outside the `minValue`/`maxValue` without knowing it unless you provide an error message. See [Min and max values](#min-and-max-values) for details.

### Markdown in labels

The `label` prop supports inline markdown: bold (`**text**`), italic (`*text*`), bold and italic (`***text***`), highlight (`==text==`), and code (`` `text` ``).

numberfield-markdownlabel

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-markdownlabel?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Flex, NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex direction="column" gap="4" style={{ maxWidth: 400 }}>
      <NumberField label="**Bold** label" />
      <NumberField label="*Italic* label" />
      <NumberField label="***Bold and italic*** label" />
      <NumberField label="==Highlight== label" />
      <NumberField label="`Code` label" />
    </Flex>
  );
}

export default App;
```

### Hide the label

Use `hideLabel` to visually hide the label. The `label` string is converted to an `aria-label` on the input so it remains accessible to screen readers — any inline markdown is stripped to plain text.

numberfield-hidelabel

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/numberfield-hidelabel?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Flex, NumberField } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex
      direction="row"
      gap="2"
      alignItems="flex-end"
      style={{ maxWidth: 400 }}
    >
      <NumberField label="Quantity" hideLabel suffix="qty" />
      <NumberField label="Unit price" hideLabel prefix="$" />
    </Flex>
  );
}

export default App;
```

**NumberField Props**

```tsx theme={null}
<NumberField
  label="Quantity"
  minValue={0}
  maxValue={100}
  step={1}
  maximumFractionDigits={0}
  minimumFractionDigits={0}
  value={10}
  defaultValue={0}
  hideControls={false}
  onChange={(value) => console.log(value)}
  description="Enter a quantity"
  error="Invalid value"
  hint="Must be between 0 and 100"
  size="medium"
  loading={false}
  disabled={false}
  readOnly={false}
  required={false}
  placeholder="Enter quantity"
/>
```

## `NumberField` Props

### Properties

**defaultValue** `number | null`

Default value for uncontrolled number field.

**hideControls** `boolean` (default: false)

Whether to hide the increment/decrement buttons.

**maximumFractionDigits** `number` (default: 0)

Maximum number of decimal places to display and allow.

**maxValue** `number`

Maximum allowed value for the number field.

**minimumFractionDigits** `number` (default: 0)

Minimum number of decimal places to display.

**minValue** `number`

Minimum allowed value for the number field.

**onChange** `(value: number | null) =\> void`

Callback fired when the value changes.

**step** `number` (default: 1)

Step value for increment/decrement operations.

**value** `number | null`

Controlled value of the number field.

### Additional field props

The component also support the following props which are common to most field components:

**description** `string`

Descriptive text displayed below the input field

**disabled** `boolean` (default: false)

Whether the number field is disabled

**errorAriaLive** `"off" | "polite" | "assertive"` (default: assertive)

ARIA live region setting for error announcements

**error** `ReactElement | string | boolean`

Error message or element to display below the input

**hideLabel** `boolean` (default: false)

Visually hides the label while keeping it accessible to screen readers via `aria-label`.

**hint** `string`

Hint text displayed below the input field

**isHighlighted** `boolean` (default: false)

When `true`, applies a subdued primary background to draw attention to the field.

**label** `string`

Label for the field. Supports inline markdown formatting.

> [!WARNING]
>
> Omitting `label` is deprecated and will be required in v4.0.0. Use `hideLabel` to visually hide it.

**labelProps** `object`

Additional props to pass to the `Label` component

**loading** `boolean` (default: false)

Whether to show a loading spinner in the input field

**moreInfo** `string`

Additional information to display with the label

**placeholder** `string`

Placeholder text when no value is present

**prefix** `string | ReactElement`

**readOnly** `boolean` (default: false)

Whether the number field is read-only

**required** `boolean` (default: false)

Whether the number field is required

**size** `"small" | "medium" | "large"` (default: medium)

Size variant of the number field

**suffix** `string | ReactElement`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.