feat(record-inputs): tap-to-adjust steppers + inputmode keypad hint

Adds [-] / [+] buttons around every numeric input in the Record Inputs
dialog (single-value, dual-entry, and pass_fail+range branches). Tap
to increment / decrement by the recipe-author-derived step size
(stepFor() already computes this from target_min/target_max precision,
falling back to input-type defaults).

- Decrement clamps at 0 (typical qty/time/temp on a plating floor
  doesn't go negative; if needed, operator can still tap the input
  and type a negative value)
- Increment uses _stepRound() to avoid floating-point fuzz on decimals
- Center-aligned monospace-ish input between the buttons for clarity
- inputmode='decimal' (or 'numeric' for time fields) hint so when the
  operator does tap the input, the iPad shows a number keypad instead
  of the full keyboard

Touches single-value, dual-entry (min/max), and pass_fail+range. Other
multi-field widgets (multi-point thickness, bath chemistry panel) still
use plain inputs — separate request if they need steppers too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-24 19:43:00 -04:00
parent 8d4c85cc52
commit 7dab5fb9c6
4 changed files with 201 additions and 34 deletions

View File

@@ -120,11 +120,26 @@
<!-- Numeric — single value (no range defined) -->
<div t-if="isNumeric(row) and !hasRangeEntry(row)"
class="o_fp_ri_numeric">
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric"
t-att-step="stepFor(row)"
t-model.number="row.value_number"
t-att-placeholder="row.target_min or '0.00'"/>
<div class="o_fp_ri_stepper">
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_minus"
t-on-click="() => this.onDecrement(row, 'value_number')"
aria-label="Decrease">
<i class="fa fa-minus"/>
</button>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric o_fp_ri_stepper_input"
t-att-inputmode="inputModeFor(row)"
t-att-step="stepFor(row)"
t-model.number="row.value_number"
t-att-placeholder="row.target_min or '0.00'"/>
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_plus"
t-on-click="() => this.onIncrement(row, 'value_number')"
aria-label="Increase">
<i class="fa fa-plus"/>
</button>
</div>
<t t-set="hint" t-value="rangeHint(row)"/>
<span t-if="hint"
class="o_fp_ri_range_hint"
@@ -138,22 +153,52 @@
Constrained to numeric so it doesn't duplicate
the pass_fail+range branch above. -->
<div t-if="isNumeric(row) and hasRangeEntry(row)" class="o_fp_ri_dual">
<label class="o_fp_ri_dual_field">
<div class="o_fp_ri_dual_field">
<span class="o_fp_ri_dual_label">Min Reading</span>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric"
t-att-step="stepFor(row)"
t-model.number="row.value_min"
t-att-placeholder="row.target_min or '0.00'"/>
</label>
<label class="o_fp_ri_dual_field">
<div class="o_fp_ri_stepper">
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_minus"
t-on-click="() => this.onDecrement(row, 'value_min')"
aria-label="Decrease">
<i class="fa fa-minus"/>
</button>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric o_fp_ri_stepper_input"
t-att-inputmode="inputModeFor(row)"
t-att-step="stepFor(row)"
t-model.number="row.value_min"
t-att-placeholder="row.target_min or '0.00'"/>
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_plus"
t-on-click="() => this.onIncrement(row, 'value_min')"
aria-label="Increase">
<i class="fa fa-plus"/>
</button>
</div>
</div>
<div class="o_fp_ri_dual_field">
<span class="o_fp_ri_dual_label">Max Reading</span>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric"
t-att-step="stepFor(row)"
t-model.number="row.value_max"
t-att-placeholder="row.target_max or '0.00'"/>
</label>
<div class="o_fp_ri_stepper">
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_minus"
t-on-click="() => this.onDecrement(row, 'value_max')"
aria-label="Decrease">
<i class="fa fa-minus"/>
</button>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric o_fp_ri_stepper_input"
t-att-inputmode="inputModeFor(row)"
t-att-step="stepFor(row)"
t-model.number="row.value_max"
t-att-placeholder="row.target_max or '0.00'"/>
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_plus"
t-on-click="() => this.onIncrement(row, 'value_max')"
aria-label="Increase">
<i class="fa fa-plus"/>
</button>
</div>
</div>
<t t-set="dhint" t-value="dualRangeHint(row)"/>
<span t-if="dhint"
class="o_fp_ri_range_hint o_fp_ri_dual_hint"
@@ -169,22 +214,52 @@
prompt (e.g. Bore inspection: 0.005-0.007 in). -->
<t t-if="isPassFail(row) and hasRangeEntry(row)">
<div class="o_fp_ri_dual">
<label class="o_fp_ri_dual_field">
<div class="o_fp_ri_dual_field">
<span class="o_fp_ri_dual_label">Min Reading</span>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric"
t-att-step="stepFor(row)"
t-model.number="row.value_min"
t-att-placeholder="row.target_min or '0.00'"/>
</label>
<label class="o_fp_ri_dual_field">
<div class="o_fp_ri_stepper">
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_minus"
t-on-click="() => this.onDecrement(row, 'value_min')"
aria-label="Decrease">
<i class="fa fa-minus"/>
</button>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric o_fp_ri_stepper_input"
t-att-inputmode="inputModeFor(row)"
t-att-step="stepFor(row)"
t-model.number="row.value_min"
t-att-placeholder="row.target_min or '0.00'"/>
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_plus"
t-on-click="() => this.onIncrement(row, 'value_min')"
aria-label="Increase">
<i class="fa fa-plus"/>
</button>
</div>
</div>
<div class="o_fp_ri_dual_field">
<span class="o_fp_ri_dual_label">Max Reading</span>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric"
t-att-step="stepFor(row)"
t-model.number="row.value_max"
t-att-placeholder="row.target_max or '0.00'"/>
</label>
<div class="o_fp_ri_stepper">
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_minus"
t-on-click="() => this.onDecrement(row, 'value_max')"
aria-label="Decrease">
<i class="fa fa-minus"/>
</button>
<input type="number"
class="o_fp_ri_input o_fp_ri_input_numeric o_fp_ri_stepper_input"
t-att-inputmode="inputModeFor(row)"
t-att-step="stepFor(row)"
t-model.number="row.value_max"
t-att-placeholder="row.target_max or '0.00'"/>
<button type="button"
class="o_fp_ri_stepper_btn o_fp_ri_stepper_plus"
t-on-click="() => this.onIncrement(row, 'value_max')"
aria-label="Increase">
<i class="fa fa-plus"/>
</button>
</div>
</div>
<t t-set="dhint" t-value="dualRangeHint(row)"/>
<span t-if="dhint"
class="o_fp_ri_range_hint o_fp_ri_dual_hint"