Files
suaveplan/packages/ui/react/react-control-surface/src/controls/button-latching/button-latching.md
2026-05-27 23:47:53 +01:00

2.0 KiB

<ButtonLatching>

(no submodules)

Purpose

<ButtonLatching> is the sticky toggle: a click latches the button on, the next click latches it off. It is the counterpart to <ButtonMomentary> and reuses the same aria-pressed pattern so users who navigate by screen reader experience continuity across the two variants — the only behavioural difference is when the value flips.

Unlike the momentary variant, the latched state is read entirely from the schema's numeric value via a midpoint threshold. There is no local state to track because the press has no second "release" event that needs synchronisation with the visual chrome.

Features

  • Single-click toggle.
  • Keyboard activation via Space and Enter with event.repeat suppression.
  • WAI-ARIA aria-pressed reflection of the latched state.
  • Telemetry: control_surface_interactions_total{kind="button-latching"} on every toggle.
  • Pure isButtonLatchingOn helper for unit testing the threshold.

Usage: Basic

<ButtonLatching
    value={looping ? 1 : 0}
    onChange={(v) => setLooping(v === 1)}
    min={0}
    max={1}
    label="Loop"
/>

Usage: Advanced

<ButtonLatching
    value={state}
    onChange={(v) => registry.dispatch(binding, v)}
    min={0}
    max={1}
    label="Bypass"
    ariaLabel="Bypass effect chain"
    disabled={readOnly}
    className="bypass"
/>

API Reference

  • <ButtonLatching> props: BoundControlProps & { className?, style? }.
  • isButtonLatchingOn(value, min, max) — pure threshold helper.

Implementation Notes

event.repeat is suppressed in the keyboard handler so an OS-level auto-repeat does not flip the latch on every key event while the user holds Space. The midpoint threshold is the same as <Switch2> — these two controls differ only in their visual chrome; if a surface designer prefers a chunky push-button rather than a thin toggle they can pick the latching button with no behavioural change.