Import the public number input directive from the package entrypoint.

number-input.ts
import { KuiNumberInput } from '@kikita-labs/ui';

Use kuiNumberInput on a native input[type=number] element. Standard HTML attributes such as min, max, step, disabled, readonly, and value are placed directly on the input.

<input type="number" kuiNumberInput min="0" max="100" aria-label="Quantity" value="4" />
<input
  type="number"
  kuiNumberInput
  size="sm"
  min="0"
  max="10"
  aria-label="Small quantity"
  value="2"
/>
<input
  type="number"
  kuiNumberInput
  disabled
  min="0"
  max="10"
  aria-label="Disabled quantity"
  value="3"
/>

variant split, with minus/plus controls on the sides, is the default and recommended for most use cases. variant stacked puts compact arrow controls on the right.

<input
  type="number"
  kuiNumberInput
  variant="stacked"
  min="0"
  max="99"
  aria-label="Compact quantity"
  value="12"
/>
<input
  type="number"
  kuiNumberInput
  variant="split"
  min="0"
  max="99"
  aria-label="Default quantity"
  value="12"
/>

Click a generated button to step by the step attribute, or by 1 when step is omitted. At min the decrement button disables; at max the increment button disables. invalid applies an error border.

<input
  type="number"
  kuiNumberInput
  min="0"
  max="20"
  step="5"
  aria-label="Step of five"
  value="10"
/>
<input
  type="number"
  kuiNumberInput
  invalid
  min="1"
  max="10"
  aria-label="Invalid quantity"
  value="0"
/>

Place the input inside kui-field to inherit label, hint, error, and id wiring. A parent field error also marks the input invalid automatically.

Choose between 1 and 10 seats

<kui-field label="Seats" hint="Choose between 1 and 10 seats">
  <input type="number" kuiNumberInput min="1" max="10" value="4" />
</kui-field>

<kui-field label="Discount" error="Discount must be at least 0%" required>
  <input type="number" kuiNumberInput invalid min="0" max="100" value="-5" />
</kui-field>

Use Angular Signal Forms [formField] on the same native input. When projected inside kui-field, the field wrapper reads the descendant [formField] and infers the required marker and first error message. Use Signal Forms min(...) and max(...) validators for range constraints instead of native min/max attributes on a [formField] input.

signal-forms-number-input.html
<kui-field label="Count" hint="Enter a value from 1 to 100">
  <input type="number" kuiNumberInput [formField]="profileForm.count" />
</kui-field>

Number Input uses the shared --kui-input-* control-chrome tokens for height, border, radius, background, text, placeholder, focus, and invalid states. Number-specific tokens remain available for the increment and decrement controls.

number-input.scss
input[kuiNumberInput] {
  --kui-input-bg: var(--kui-color-surface);
  --kui-input-border: var(--kui-color-border);
  --kui-input-radius: var(--kui-radius-md);
  --kui-number-input-btn-bg-hover: var(--kui-color-surface-elevated);
}

Set defaults.numberInput once for the application or for a subtree. Each option resolves as local input > defaults.numberInput.<option> > built-in default.

import { provideKikitaUi } from '@kikita-labs/ui';

export const appConfig: ApplicationConfig = {
  providers: [
    provideKikitaUi({
      defaults: {
        numberInput: {
          /* options below */
        },
      },
    }),
  ],
};
NameTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' — Component size. Takes precedence over the global defaults.size.
variant'stacked' | 'split' — Default variant.

Set any of these on the component or an ancestor to restyle one part. Each token is optional: when it is not set, the part uses the role or scale token in the default column.

NameTypeDefaultDescription
--kui-number-input-btn-color-hoverCSS custom property--kui-color-textBtn color, hover
--kui-number-input-btn-bg-activeCSS custom property--kui-color-borderBtn background, active
--kui-number-input-btn-color-activeCSS custom property--kui-color-textBtn color, active
--kui-number-input-btn-color-disabledCSS custom property--kui-color-text-disabledBtn color, disabled
--kui-number-input-arrow-color-hoverCSS custom property--kui-color-textArrow color, hover
--kui-number-input-arrow-bg-activeCSS custom property--kui-color-borderArrow background, active
--kui-number-input-arrow-color-activeCSS custom property--kui-color-textArrow color, active
--kui-number-input-arrow-color-disabledCSS custom property--kui-color-text-disabledArrow color, disabled
--kui-number-input-btn-color-readonlyCSS custom property--kui-color-text-secondaryBtn color, readonly
NameTypeDefaultDescription
--kui-number-input-field-padding-inlineCSS custom property--kui-space-3Field padding, inline

Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.

NameTypeDefaultDescription
decreasestring — Decrease button. Default Decrease value.
increasestring — Increase button. Default Increase value.

Inputs verified against @kikita-labs/ui v2.0.0 public typings.

NameTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' | undefinedundefinedControl height from --kui-control-height-*; generated buttons scale to match. Resolved from defaults.numberInput.size, then the parent field, then the global defaults.size, then md.
variant'stacked' | 'split' | undefinedundefinedButton layout. split places minus/plus controls on the sides (recommended); stacked stacks compact arrows on the right. Falls back to defaults.numberInput.variant, then split.
invalidbooleanfalseApplies an error border. Also inherited automatically from a parent kui-field with an error.
idstring | undefined-Id override for the native input. Falls back to the parent kui-field control id.
minstring | number-Native HTML attribute placed directly on the input. Decrement stops and disables at this value.
maxstring | number-Native HTML attribute placed directly on the input. Increment stops and disables at this value.
stepstring | number1Native HTML attribute. Amount the generated buttons and arrow keys step by.
disabledbooleanfalseNative HTML attribute. Sets data-kui-disabled on the container and disables both generated buttons.
readonlybooleanfalseNative HTML attribute. Sets data-kui-readonly on the container and disables both generated buttons.
--kui-input-bgCSS custom propertyFieldShared control background color.
--kui-input-bg-disabledCSS custom propertyvar(--kui-input-bg)Shared background color used for disabled and readonly states.
--kui-number-input-borderCSS custom property--kui-input-borderOptional number-input border override; falls back to the shared input border.
--kui-number-input-dividerCSS custom property--kui-color-borderDivider color between the buttons and the native input.
--kui-number-input-btn-bgCSS custom propertytransparentGenerated button background in the default state.
--kui-number-input-btn-bg-hoverCSS custom property--kui-color-surface-elevatedGenerated button background on hover.
--kui-number-input-btn-textCSS custom property--kui-color-text-secondaryGenerated button icon color.
KuiNumberInputOptionsinterface-Shape of defaults.numberInput: size and variant.

The native input[type=number] keeps its built-in keyboard and screen-reader semantics.

  • Provide an accessible name through aria-label or a kui-field label.
  • Generated buttons are named by the numberInput.decrease and numberInput.increase messages (Decrease value and Increase value by default), plus native disabled and aria-disabled="true" when stepping is not available.
  • Native keyboard behavior on the input remains available: ArrowUp, ArrowDown, Home, and End.
  • Press and hold a generated button for repeated stepping after a 400 ms delay; Enter or Space on a focused button steps once.
  • A disabled or readonly native input sets data-kui-disabled or data-kui-readonly on the container and disables both buttons.
  • Place the input inside kui-field to inherit label, hint, error, and id wiring instead of wiring ARIA by hand.

Consumer-visible changes of @kikita-labs/ui 2.0 for Number Input.

  • The directive class is KuiNumberInput; the Directive suffix is gone.
  • variant values are split (side controls, default) and stacked; the old b and a names are gone.
  • Size and variant defaults moved to provideKuiDefaults({ numberInput: { size, variant } }); the inputs are now undefined until set.
  • The decrease and increase button names come from the numberInput.decrease and numberInput.increase messages.
  • Button hover, active, disabled and readonly states have colour tokens, and the field padding has --kui-number-input-field-padding-inline.