Number Input
A numeric input with increment and decrement buttons for precise value control.
Interactive
Requires:
veritheme.js
JS init: automatic
Default
Basic number input with +/- buttons.
html
<div class="vt-number-input vt-bg-surface-card" data-number-input="">
<button type="button" class="vt-number-input-btn" data-action="decrement">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-4 vt-h-4">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="1" min="0" max="99" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums" data-number-value="" aria-label="Value">
<button type="button" class="vt-number-input-btn" data-action="increment">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
With Label
Number input paired with a label and helper text.
html
Select between 1 and 99
<div class="vt-space-y-2">
<label class="vt-text-sm vt-font-medium vt-block" for="number-input-2-1">Quantity</label>
<div class="vt-number-input vt-bg-surface-card" data-number-input="">
<button type="button" class="vt-number-input-btn" data-action="decrement">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-4 vt-h-4">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="3" min="1" max="99" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums" data-number-value="" id="number-input-2-1" aria-describedby="number-input-2-2">
<button type="button" class="vt-number-input-btn" data-action="increment">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
<p class="vt-text-xs vt-text-foreground-muted" id="number-input-2-2">Select between 1 and 99</p>
</div>
Sizes
Small, medium, and large number input variants.
html
<div class="vt-number-input vt-number-input-sm vt-bg-surface-card" data-number-input="">
<button type="button" class="vt-number-input-btn" data-action="decrement">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-3 vt-h-3">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="2" min="0" max="99" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums" data-number-value="" aria-label="Value">
<button type="button" class="vt-number-input-btn" data-action="increment">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-3 vt-h-3">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
<div class="vt-number-input vt-bg-surface-card" data-number-input="">
<button type="button" class="vt-number-input-btn" data-action="decrement">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-4 vt-h-4">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="5" min="0" max="99" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums" data-number-value="" aria-label="Value">
<button type="button" class="vt-number-input-btn" data-action="increment">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
<div class="vt-number-input vt-number-input-lg vt-bg-surface-card" data-number-input="">
<button type="button" class="vt-number-input-btn" data-action="decrement">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-5 vt-h-5">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="8" min="0" max="99" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums" data-number-value="" aria-label="Value">
<button type="button" class="vt-number-input-btn" data-action="increment">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-5 vt-h-5">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
Min / Max
Number input with min and max constraints. Buttons disable at boundaries.
html
Min: 1, Max: 10
<div class="vt-space-y-2 vt-text-center">
<div class="vt-number-input vt-bg-surface-card" data-number-input="">
<button type="button" class="vt-number-input-btn disabled:vt-opacity-30 disabled:vt-pointer-events-none" data-action="decrement" disabled="">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-4 vt-h-4">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="1" min="1" max="10" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums" data-number-value="" aria-label="Value" aria-describedby="number-input-4-1">
<button type="button" class="vt-number-input-btn disabled:vt-opacity-30 disabled:vt-pointer-events-none" data-action="increment">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
<p class="vt-text-xs vt-text-foreground-muted" id="number-input-4-1">Min: 1, Max: 10</p>
</div>
Disabled
Disabled state for read-only display.
html
<div class="vt-number-input vt-bg-surface-subtle vt-opacity-50 vt-pointer-events-none">
<button type="button" class="vt-number-input-btn" disabled="">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-minus vt-w-4 vt-h-4">
<path d="M5 12h14"></path>
</svg>
</button>
<input type="number" value="5" disabled="" class="vt-number-input-value vt-bg-transparent vt-outline-none vt-tabular-nums vt-text-foreground-disabled" aria-label="Value">
<button type="button" class="vt-number-input-btn" disabled="">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
</div>
Shopping Cart Example
Number input in a product card context.
🎧
Wireless Headphones
Premium noise cancelling
$299
Guidelines
Precise numeric values with +/- steppers. Ranges where exact value matters less → slider.
Min: 1, Max: 10
Do
Don't
API Reference
All data attributes and utility classes available for the Number Input component.
| Class | Type | Description |
|---|---|---|
[data-number-input] |
Container | Wrapper element that groups buttons and input together |
[data-action="decrement"] |
Button | Decrement button — decreases value by 1 |
[data-action="increment"] |
Button | Increment button — increases value by 1 |
[data-number-value] |
Input | The number input field itself |
vt-h-8 |
Size | Small size variant (height 32px) |
vt-h-10 |
Size | Default size variant (height 40px) |
vt-h-12 |
Size | Large size variant (height 48px) |
disabled |
State | Disabled state — reduced opacity, pointer events none |
Accessibility
Keyboard and screen reader support.
| Feature | Details |
|---|---|
| Keyboard | Arrow keys work in the input, buttons are keyboard accessible via Tab |
| Screen Reader | Input announces current value and constraints (min/max) |
| ARIA | Use aria-label on increment/decrement buttons for clarity |
| Min/Max | Buttons auto-disable at boundaries, preventing invalid values |
| Focus | Input receives focus ring, buttons show hover/focus states |