Files
skills/docs/ui/react/react-control-surface/src/controls/button-momentary/button-momentary.md
2026-05-29 08:20:56 +01:00

2.2 KiB

<ButtonMomentary>

(no submodules)

Purpose

<ButtonMomentary> is the press-and-hold trigger control. Pressing it emits max into onChange; releasing it emits min. The release also fires when the pointer leaves the button while still pressed, so a user who drags off the button mid-hold doesn't get stuck in the held state. Keyboard interaction follows the same edge model: Space / Enter down emit max, the corresponding up emits min, and event.repeat is suppressed so OS auto-repeat doesn't generate a stream of duplicate "down" events.

The pressed state is tracked locally in useState so the visual chrome updates synchronously with the user input. The schema's numeric value is informational; the rendered chrome follows the user's gesture rather than waiting for a round-trip through the binding registry.

Features

  • Press-down / release edge dispatch.
  • Pointer-leave releases stuck holds.
  • Keyboard activation via Space and Enter with event.repeat suppression.
  • WAI-ARIA aria-pressed reflection.
  • Telemetry: control_surface_interactions_total{kind="button-momentary"} on every press.
  • disabled blocks both pointer and keyboard activation.

Usage: Basic

<ButtonMomentary
    value={triggered ? 1 : 0}
    onChange={(v) => setTriggered(v === 1)}
    min={0}
    max={1}
    label="Trigger"
/>

Usage: Advanced

<ButtonMomentary
    value={state}
    onChange={(v) => {
        registry.dispatch(binding, v);
        if (v === 1) sampler.trigger();
    }}
    min={0}
    max={1}
    label="One-shot"
    ariaLabel="Trigger one-shot sample (Space to hold)"
/>

API Reference

  • <ButtonMomentary> props: BoundControlProps & { className?, style? }.

Implementation Notes

The local pressed state guards against double-press without an intervening release — a second pointer-down with no release is dropped. This is essential under touch input where rapid taps can interleave. The pointer-leave handler only fires release when the button is currently pressed; a stray leave with no prior press is a no-op. Disabled state short-circuits before the state mutation so a disabled component never contributes to the press counter.