Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelogApp ShellAspect GridAuth ShellCenterContainerDashboard GridFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbarAnchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkStepper NavTabsTop BarTree ViewAccordionAspect RatioAvatarAvatar GroupCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSkeletonSpinnerStackVideoVirtual ListActivity HeatmapAnimated NumberBadgeBar ListChartClockComparisonCountdown TimerData GridDescription ListDiffGaugeJSON TreeKanbanLevel MeterListMeterSparklineStatStepperTagTimelineUptimeValue CardWaveformBlockquoteCode BlockCode GroupGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriterButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerField ListFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree SelectAlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuHover CardLoading OverlayNotification PanelPopoverProgressSheetToastTooltip
ARC UIARC Radiant Components
v4.9DocsComponentsTokensSynthesizer
Getting StartedFrameworksServer RenderingDesign TokensThemingTheme SynthesizerTypographyUtilitiesAll ComponentsAccessibilityBrowser SupportChangelogContributingStatsApp ShellAspect GridAuth ShellCenterContainerDashboard GridFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbarAnchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkStepper NavTabsTop BarTree ViewAccordionAspect RatioAvatarAvatar GroupCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSkeletonSpinnerStackVideoVirtual ListActivity HeatmapAnimated NumberBadgeBar ListChartClockComparisonCountdown TimerData GridDescription ListDiffGaugeJSON TreeKanbanLevel MeterListMeterSparklineStatStepperTagTimelineUptimeValue CardWaveformBlockquoteCode BlockCode GroupGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriterButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerField ListFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree SelectAlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuHover CardLoading OverlayNotification PanelPopoverProgressSheetToastTooltip

Number Input

A numeric stepper input with decrement and increment buttons flanking a central text field, supporting min/max clamping, step increments, and keyboard shortcuts.

ComponentsNumber Input
inputinteractive
<arc-number-input>

Overview

NumberInput combines a native numeric text field with decrement and increment buttons to make a numeric stepper. The three elements are presented as a unified control with a shared border and rounded corners, where the buttons sit on either side of the input field separated by subtle inner borders. When the control receives focus, the entire border shifts to accent-primary with a focus ring, which gives clear visual feedback. The component enforces value boundaries through automatic clamping. When `min` or `max` props are set, the value is clamped to stay within range, and the corresponding button becomes disabled and visually dimmed when the limit is reached. The `step` prop controls the increment granularity for both button clicks and keyboard interactions. Holding Shift while pressing arrow keys multiplies the step by 10, for quick large adjustments without repeated clicks. When a `label` is provided, it renders as an uppercase accent-font label above the control, connected to the input via a generated `id` and `for` attribute for accessibility. The events mirror the native control: typing fires `arc-input` alone on each keystroke, and the value commits with `arc-change` on blur or Enter. A stepper button click or an arrow key fires both, because each of those is an edit and a commit in one gesture. Every event carries the new value in its detail.

Guidelines

When to use

  • Use NumberInput when the user needs to enter or adjust an exact numeric value
  • Set `min` and `max` to prevent invalid values and provide clear boundary feedback
  • Choose a `step` that matches your data precision: 1 for integers, 0.1 for decimals
  • Provide a `label` so the input is properly announced by screen readers
  • Use the Shift+Arrow shortcut tip in help text for power users who need fast adjustments

When not to use

  • Do not use NumberInput for approximate values or large ranges; use Slider instead
  • Do not omit `min` and `max` when there are logical boundaries for the value
  • Do not set a `step` of 0: it prevents the buttons from changing the value
  • Do not use NumberInput for non-numeric data like phone numbers; use a standard Input with a pattern
  • Avoid stacking many number inputs without labels: each one needs context for usability

Features

  • Inline decrement and increment buttons flanking a centered numeric text field
  • Automatic value clamping to `min` and `max` boundaries with buttons disabled at limits
  • Configurable `step` for increment granularity, with Shift+Arrow for 10x step multiplier
  • Focus-within styling applies accent-primary border and ring to the entire control group
  • Label rendered as uppercase accent-font text above the control with proper `for` association
  • Native `spinbutton` ARIA role with `aria-valuenow`, `aria-valuemin`, and `aria-valuemax`
  • Hides browser-native spin buttons so the control looks the same across platforms
  • Disabled state at 40% opacity with pointer events blocked

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available. Use the Web Component directly or a framework wrapper.

<arc-number-input label="Quantity" value="3" min="1" max="99" step="1"></arc-number-input>

API

valuenumber0
Current numeric value. Reflected as an attribute and updated on user interaction.
stepnumber1
Increment and decrement step size. Arrow keys use this value, Shift+Arrow uses 10x this value.
labelstring''
Label text displayed above the control in uppercase accent font.
namestring''
disabledbooleanfalse
Disables interaction, reducing opacity to 40% and blocking pointer events.
minnumber0
Minimum allowed value. The decrement button is disabled when the value reaches this limit.
maxnumber0
Maximum allowed value. The increment button is disabled when the value reaches this limit.
readonlybooleanfalse
Prevents value changes from typing, stepper buttons, and arrow keys while keeping the field focusable and its value submitted.
size'sm' | 'md' | 'lg''md'
Control size. md is the default; sm and lg scale the field padding.
formAssociatedbooleantrue
propertiesobject{ // flag(), unlike `disabled`. The exclusion in props.js is specifically // about form-associated *platform* semantics: a `disabled` content // attribute that is merely present makes the element actually disabled // per the HTML spec, and formDisabledCallback assigns the property back, // so no converter can win. Neither of these is platform-mapped: // `required` is enforced by _computeValidity() below and `readonly` by // each component's own interaction handlers, so the stock converter buys // nothing here and costs the usual bug: `required="false"` read as true, // blocking submission of a form the author meant to leave optional. // Finding #48's shape, across all 26 form controls at once. required: flag(false), readonly: flag(false), }
Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. required participates in constraint validation below; readonly reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
autoValidatesbooleantrue
Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
form
validity
validationMessage
requiredbooleanfalse

Methods

checkValidity()boolean
Whether the control currently satisfies its constraints, per the native constraint-validation API. Fires invalid on the element when it does not, and reports nothing to the user.
reportValidity()boolean
As checkValidity(), but also shows the browser's validation message against the control when it fails.

Events

arc-inputdetail:{ value: number }
Fired on every edit, including each keystroke while typing. Use for live previews.
arc-changedetail:{ value: number }
Fired when the value is committed: blur or Enter after typing, or immediately on a stepper click or arrow key, which are edit and commit in one gesture.

See Also