Skip to content

Number Input

The bq-number-input component is a numeric field with stepper buttons, range clamping and step snapping.

Basic Usage

html
<bq-number-input label="Quantity" value="1" min="1" max="99"></bq-number-input>

Step and Precision

Values are snapped to the step grid and clamped to [min, max]:

html
<bq-number-input label="Weight" value="2.5" min="0" max="10" step="0.5"></bq-number-input>

Display precision is derived from stepstep="0.5" shows one decimal — which also avoids floating-point drift such as 0.30000000000000004. Override it with precision:

html
<bq-number-input value="1" step="0.1" precision="3"></bq-number-input>

Prefix and Suffix

html
<bq-number-input label="Price" value="20" min="0" step="0.01">
  <span slot="prefix">€</span>
</bq-number-input>

<bq-number-input label="Duration" value="30" min="0" step="5">
  <span slot="suffix">min</span>
</bq-number-input>

Hint and Error

html
<bq-number-input label="Seats" value="4" hint="Between 1 and 20"></bq-number-input>
<bq-number-input label="Seats" value="99" error="Maximum is 20"></bq-number-input>

States

html
<bq-number-input label="Locked" value="5" readonly></bq-number-input>
<bq-number-input label="Unavailable" value="5" disabled></bq-number-input>

Handling Changes

js
input.addEventListener('bq-input', (event) => {
  console.log('typing', event.detail.value);
});

input.addEventListener('bq-change', (event) => {
  console.log('committed', event.detail.value);
});

bq-input fires on each keystroke with the raw value. bq-change fires on commit (blur or a stepper button) with the normalized value — typing is never interrupted by mid-edit clamping.

Forms

html
<form>
  <bq-number-input name="quantity" value="2" min="1"></bq-number-input>
  <button type="submit">Send</button>
</form>

Properties

PropertyTypeDefaultDescription
valuenumber0Current value
minnumber-∞Lower bound
maxnumber+∞Upper bound
stepnumber1Increment and snapping grid
precisionnumber-1Decimal places (-1 derives them from step)
labelstring''Field label
placeholderstring''Placeholder text
namestring''Form field name
sizestring'md'sm | md | lg
disabledbooleanfalseDisable the field
readonlybooleanfalsePrevent editing
requiredbooleanfalseMark the field required
errorstring''Error message; marks the field invalid
hintstring''Helper text

Slots

SlotDescription
prefixContent before the field, e.g. a currency
suffixContent after the field, e.g. a unit

Events

EventDetailDescription
bq-input{ value: number }The field value changed while typing
bq-change{ value: number }A normalized value was committed

CSS Parts

PartDescription
fieldThe outer wrapper
labelThe label element
controlThe input row
inputThe native input
decrementThe decrement button
incrementThe increment button
hintHelper text
errorError message

Accessibility

  • The label is a real <label> bound to the input via for/id.
  • Hint and error text are linked with aria-describedby; an error also sets aria-invalid and role="alert".
  • Stepper buttons carry localized aria-labels and are removed from the tab order — the field itself is the tab stop, and native / already step the value.
  • A stepper button is disabled once its bound is reached, so the limit is conveyed non-visually.
  • The native spin buttons are hidden in favour of the styled ones, which stay full-size and easy to hit on touch.

Released under the MIT License.