Skip to content

Input stepper <l-input-stepper>

A stepper control that enhances a native <input type="number"> with decrement/increment buttons and an animated number track.

HTML tag<l-input-stepper>
Native HTML
Progressive
Custom
Shadow DOM
Progressive Custom Element

Options

Code
html
<l-input-stepper>
  <input
    type="number"
    value="1"
  />
</l-input-stepper>

Appearance

Pick a visual style via appearance. Each appearance has its own CSS import.

Default

Bordered box with inline buttons.

css
@import 'luxen-ui/css/input-stepper/default';

Rounded

Circular standalone buttons with no container border — Airbnb-style.

css
@import 'luxen-ui/css/input-stepper/rounded';

Size

Set the size attribute: xs, sm, md (default), lg, xl.

Code
html
<div class="flex items-center gap-4">
  <l-input-stepper size="xs">
    <input
      type="number"
      value="1"
    />
  </l-input-stepper>

  <l-input-stepper size="sm">
    <input
      type="number"
      value="1"
    />
  </l-input-stepper>

  <l-input-stepper size="md">
    <input
      type="number"
      value="1"
    />
  </l-input-stepper>

  <l-input-stepper size="lg">
    <input
      type="number"
      value="1"
    />
  </l-input-stepper>

  <l-input-stepper size="xl">
    <input
      type="number"
      value="1"
    />
  </l-input-stepper>
</div>

Not defined

Before JS loads (:not(:defined)), CSS provides a styled fallback with zero layout shift.

Code
html
<l-input-stepper>
  <input
    type="number"
    value="1"
  />
</l-input-stepper>

The CSS reserves space for the stepper buttons via padding-inline and matches the exact dimensions of the hydrated component. Once defined, the custom element replaces the padding with its own buttons.

Min / Max

Constrain the value range via min and max on the <input>.

Code
html
<l-input-stepper>
  <input
    type="number"
    min="0"
    max="10"
    value="5"
  />
</l-input-stepper>

Disabled

Native disabled attribute on the <input>.

Code
html
<l-input-stepper>
  <input
    type="number"
    value="3"
    disabled
  />
</l-input-stepper>

Roller

Enable the animated number roller overlay with with-roller.

Code
html
<l-input-stepper with-roller>
  <input
    type="number"
    min="0"
    max="99"
    value="5"
  />
</l-input-stepper>

Accessibility

Criteria

Role

Uses native <input type="number"> and native <button> elements — built-in semantics

WCAG4.1.2
RGAA11.1
Accessible name

The input must have an associated label via <label> or aria-label

WCAG1.3.1
RGAA11.1
Disabled state

Buttons disabled at min/max bounds; entire stepper disabled via disabled on the input

WCAG4.1.2
Form integration

Native <input> participates in form submission and validation directly

WCAG4.1.2

Keyboard interactions

ArrowUp
Increments the value (native number input behavior)
ArrowDown
Decrements the value (native number input behavior)
Tab
Moves focus between the decrement button, input, and increment button

API reference

Importing

js
import 'luxen-ui/input-stepper';
css
@import 'luxen-ui/css/input-stepper/default';
/* or */
@import 'luxen-ui/css/input-stepper/rounded';

Attributes & Properties

minnumber | undefinedProperty
Minimum allowed value. Falls back to the input's min attribute.
maxnumber | undefinedProperty
Maximum allowed value. Falls back to the input's max attribute.
stepnumber | undefinedProperty
Step increment. Falls back to the input's step attribute.
sizeInputStepperSizedefault:'md'Property
Control size.
with-rollerbooleandefault:falseProperty
Enable the animated number roller overlay.
decrement-iconstringdefault:'lucide:minus'Property
Icon name for the decrement button.
increment-iconstringdefault:'lucide:plus'Property
Icon name for the increment button.

Events

changeEvent
Fired when the value changes. Detail: { value: number }.

CSS custom properties

--border-colordefault:--l-color-borderCustom property
Border color of the stepper container (default appearance) and of each button (rounded appearance).
--border-radiusdefault:--radius-mdCustom property
Border radius of the stepper container (default appearance).