# NumberInput

> Numeric field with decrement/increment buttons that clamp to min/max, disable themselves at the bounds, and step fractional values without float drift.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: Forms
- Tags: number, stepper, form, input, quantity
- Docs: https://fancy-ui.rama.app/docs/components/number-input
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/number-input

## Import

```svelte
<script lang="ts">
  import { NumberInput } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { NumberInput } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `number \| null` | `null` | Current value; bindable. null when the field is empty |
| `onValueChange` | `(value: number \| null) => void` | — | Called with the new value on every change, including a clear to null |
| `min` | `number` | — | Lower bound. Leave unset for no lower bound |
| `max` | `number` | — | Upper bound. Leave unset for no upper bound |
| `step` | `number` | `1` | Increment size, including fractional steps |
| `disabled` | `boolean` | `false` | Blocks focus, typing and the step buttons; excluded from form submission. Overridden by a surrounding FormField |
| `readonly` | `boolean` | `false` | Blocks typing and the step buttons but stays focusable and is still submitted, unlike disabled |
| `required` | `boolean` | `false` | Native required. Overridden by a surrounding FormField |
| `invalid` | `boolean` | `false` | Drives the error border and aria-invalid. Overridden by a surrounding FormField |
| `id` | `string` | — | Element id. Overridden by a surrounding FormField's own controlId |
| `name` | `string` | — | Native name, read on form submission |
| `label` | `string` | — | Accessible name — for a control with no visible Label next to it |
| `class` | `string` | — | Additional CSS classes, applied to the outer bordered wrapper |
| `ref` | `HTMLInputElement \| null` | `null` | Reference to the underlying input type=number |
| `sound` | `boolean` | `false` | Plays the tick cue on each step, once the user has enabled sound |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { NumberInput } from "fancy-ui-svelte";

	let quantity = $state<number | null>(12);
</script>

<NumberInput sound bind:value={quantity} label="Quantity" />
```

### With Limits

Bounded 1–8 with the buttons disabling at the edges.

```svelte
<script lang="ts">
	import { NumberInput } from "fancy-ui-svelte";

	let seats = $state<number | null>(2);
</script>

<NumberInput sound bind:value={seats} min={1} max={8} label="Seats" />
```

### Fractional Steps

0.1 steps over a 0–1 range, without float drift.

```svelte
<script lang="ts">
	import { NumberInput } from "fancy-ui-svelte";

	let opacity = $state<number | null>(0.5);
</script>

<NumberInput sound bind:value={opacity} min={0} max={1} step={0.1} label="Opacity" />
```
