Skip to main content

Module numeric_input

Module numeric_input 

Source
Expand description

Numeric input — text input with stepper buttons.

Two visual variants share one event surface:

  • Flanked (default) — [−] [text] [+]. Hit area-friendly, matches the existing widget shape.
  • Stacked[text │ ⌃/⌄]. The conventional <input type="number"> look (Tailwind UI, browser native). Opt in via NumericInputOpts::stacked.

shadcn doesn’t ship a dedicated component (web apps lean on <input type="number"> and let the browser draw spinners); for a renderer-agnostic UI kit we render the spinners explicitly so the affordance is consistent across backends.

The app owns the value as a String (matching crate::widgets::text_input) so mid-edit states like "1." aren’t clobbered by a parse-and-reformat round-trip on every keystroke. Parse to a number with s.parse::<f64>() (or i64, …) when you actually need the value.

use damascene_core::prelude::*;

struct Form {
    count: String,
    selection: Selection,
}

impl App for Form {
    fn build(&self, _cx: &BuildCx) -> El {
        let opts = NumericInputOpts::default()
            .min(0.0)
            .max(100.0)
            .step(1.0);
        numeric_input(&self.count, &self.selection, "count", opts)
    }

    fn on_event(&mut self, e: UiEvent) {
        let opts = NumericInputOpts::default()
            .min(0.0)
            .max(100.0)
            .step(1.0);
        numeric_input::apply_event(
            &mut self.count, &mut self.selection, "count", &opts, &e,
        );
    }
}

§Routed keys

  • {key}:decClick on the down/ button. Steps the value down.
  • {key}:incClick on the up/+ button. Steps the value up.
  • {key}:field — the inner crate::widgets::text_input; routed text edits / IME commits / pointer caret moves all flow through this key. ArrowUp / ArrowDown KeyDown events routed to this key are intercepted as step actions (the keyboard counterpart to the spinner buttons).

Spinner clicks parse the current value, add or subtract opts.step, clamp to opts.min/opts.max if set, and write the formatted result back. If the value can’t be parsed (empty or garbage), the spinner treats it as min when set, otherwise as 0.0.

§Modifier-scaled steps

Spinner clicks and arrow-key steps both honor modifier keys to produce coarse / fine adjustments without changing opts.step:

  • Shift — multiplies the step by 10 (coarse).
  • Alt — multiplies the step by 0.1 (fine; rounded to opts.decimals when set).

Holding both at once falls back to Shift since coarse is the more common power-user gesture.

§Dogfood note

Composes only the public widget-kit surface: a row of ghost buttons / icon_buttons and an inner text_input_with. An app crate can fork this file to add a different spinner shape (wheel-on-scroll, named units, …) without touching library internals.

Structs§

NumericInputOpts
Configuration for numeric_input / apply_event.

Constants§

DEFAULT_WIDTH
Default width of the wrapping row. Comfortable for 3–4 digit values in either layout — equivalent to Tailwind’s w-36.

Functions§

apply_event
Fold a routed UiEvent into the numeric input’s value, handling spinner clicks, arrow-key steps on the focused field, and text edits. Returns true if the event belonged to this widget (regardless of whether the value changed).
numeric_input
A numeric input field. Defaults to the flanked layout [−] [text_input] [+]; opt into the stacked-chevron variant with NumericInputOpts::stacked.