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

sizeAttribute
Control size: xs, sm, md (default), lg, xl
appearanceAttribute
Visual appearance: default, rounded
minAttribute
Minimum allowed value. Falls back to the input's min attribute
maxAttribute
Maximum allowed value. Falls back to the input's max attribute
stepAttribute
Increment/decrement amount. Falls back to the input's step attribute
with-rollerAttribute
Enables the animated number roller overlay
decrement-iconAttribute
Icon name for the decrement button. Defaults to lucide:minus
increment-iconAttribute
Icon name for the increment button. Defaults to lucide:plus

Events

changeEvent
Fired when the value changes. event.detail.value contains the new value.

CSS custom properties

--border-radiusName
Border radius of the stepper container (default appearance)