Do not use qds-numeric-input for identifiers that merely look numeric — account numbers, CUSIPs, phone numbers. Those are text: they have leading zeros, they are never arithmetic, and thousands separators would corrupt them. Use qds-text-input with a pattern. This distinction is the single most common mistake in financial UIs.
The qds-numeric-input component is a form-associated custom element for numeric, currency, and percentage entry. It maintains a strict three-layer value contract so nothing rounds by accident:
value property: number | null (empty is null, never 0)value attribute / form value: canonical string, no grouping, . decimal (e.g. "1234567.891")"$1,234,567.89")Display formatting is presentation only and never feeds back into value. On focus, display collapses to the editable canonical form. On blur, it re-formats. The user always edits the number they typed and always reads it formatted.
value is the number the user sees. 12.5 with mode="percent" displays 12.5% and submits "12.5". It does not submit "0.125". Silent x100 conversion is a defect factory — this component never converts.
Rounding on blur is to decimals when set, using half-up (not half-even). Half-even would be defensible for statistics; half-up matches what a finance user expects from a data-entry field.
<qds-numeric-input label="Quantity" value="100" step="10"></qds-numeric-input>
<qds-numeric-input mode="currency" currency="USD" value="1234.56" label="Amount"></qds-numeric-input>
<qds-numeric-input mode="percent" value="12.5" decimals="2" label="Rate"></qds-numeric-input>
<qds-numeric-input mode="currency" currency="EUR" locale="de-DE" value="-1234" negative-style="parens" label="Balance"></qds-numeric-input>
value - The numeric value as a canonical string (e.g. "1234.56"). Empty or absent maps to null on the property, never 0.mode - Formatting mode: number, currency, or percent. Default number.currency - ISO 4217 currency code (e.g. USD, EUR, JPY). Default USD. Currency mode only.locale - BCP 47 locale tag (e.g. en-US, de-DE). Defaults to the document locale.min - Minimum value. Violations set rangeUnderflow.max - Maximum value. Violations set rangeOverflow.step - Step increment for arrow keys and steppers. Default 1.decimals - Decimal places for display and rounding. Mode default: number unlimited, currency 2, percent 2.allow-negative - When false, blocks the minus key and rejects negative paste. Default true.negative-style - Display style for negative values: minus, parens, or parens-red. Default minus. Display only — value is always the signed number.grouping - Show thousands separators in display. Default true.steppers - Show increment/decrement buttons. Default false.align - Text alignment: start or end. Default end (right-align).name - Form field name. Reflected.label - Label text rendered as a real <label for>.hint - Helper text displayed below the control.error-text - Error message; overrides the built-in validation message.placeholder - Placeholder text.size - Control size: sm, md, or lg. Default md.disabled - Not focusable, not submitted.readonly - Focusable, submitted, not editable.required - Required field. Empty sets valueMissing.invalid - Author-forced invalid state.validate-on - When validation runs: blur, input, or submit. Default blur.value - number | null. Empty is null, never 0.validity - QdsValidity (read-only). Falls back to a local QdsValidity when ElementInternals is unavailable.willValidate - boolean.checkValidity() - () => boolean.reportValidity() - () => boolean. Also shows the error.setCustomValidity(msg) - (string) => void. Empty string clears.container - Outer wrapper.label - Label element.required - Required marker span.wrapper - Control surface wrapper.input - The input element.affix-prefix - Prefix affix (currency symbol).affix-suffix - Suffix affix (currency symbol or percent sign).stepper-up - Increment stepper button.stepper-down - Decrement stepper button.hint - Helper text.error - Error message.--qds-numeric-align - Text alignment override (default from align attribute).--qds-control-height-*, --theme-*, --button-* tokens from q-base.css.input - Fires on keystroke and stepper press. Read .value (number). Bubbles, composed.change - Fires on value commit (blur or Enter). Bubbles, composed.qds-validity-change - Fires on validity transition. Bubbles, composed.ArrowUp / ArrowDown - Increment / decrement by step, clamped to min/max.Shift + arrows - Increment / decrement by step x 10.PageUp / PageDown - Increment / decrement by step x 10.Home / End - Jump to min / max when both are set.Escape - Reverts to the value at focus time.Enter - Commits the value (rounds, formats, fires change).- (when allowed), the locale decimal separator, and clipboard/navigation keys.Paste is sanitised: strip currency symbols, spaces, grouping separators, and parentheses; convert (1,234) to -1234; reject anything that is not a valid number with no value change.
<form>
<qds-numeric-input
mode="currency"
currency="USD"
label="Invoice Amount"
value="1500.00"
min="0"
step="50"
steppers
required
hint="Minimum $0"
></qds-numeric-input>
<button type="submit">Submit</button>
</form>
<script type="module" src="https://cdn.q360.ai/assets/components/numeric-input/qds-numeric-input.js"></script>