Skip to content

Momentary Buttons

A momentary button sets a bound Property<T> to valueOn while the pointer holds it down, and back to valueOff the instant it's released — unlike Sticky Toggle Buttons, it never latches. scenerystack/sun exports RectangularMomentaryButton<T> and RoundMomentaryButton<T>, both built on the shared MomentaryButtonModel<T>. Reach for these for "hold to activate" controls — a horn, a temporary boost, a press-and-hold camera shutter — where releasing should immediately undo the effect.

ts
import { RectangularMomentaryButton } from 'scenerystack/sun';
import { Text } from 'scenerystack/scenery';
import { Property } from 'scenerystack/axon';
import { Tandem } from 'scenerystack/tandem';

const hornStateProperty = new Property<'off' | 'on'>( 'off' );

const hornButton = new RectangularMomentaryButton(
  hornStateProperty,
  'off', // valueOff
  'on',  // valueOn
  {
    content: new Text( 'Horn' ),
    baseColor: 'orange',
    tandem: Tandem.REQUIRED
  }
);

RoundMomentaryButton has the identical (property, valueOff, valueOn, options?) constructor — only the button shape differs, same as RoundPushButton/RectangularPushButton.

MomentaryButtonModel

Both classes construct a MomentaryButtonModel<T> internally, the non-visual model (extending the shared ButtonModel base documented on PushButtonModel, not PushButtonModel itself) that owns the on/off logic: downProperty transitioning to true sets valueProperty to valueOn; transitioning to false sets it back to valueOff. For alternative-input (keyboard/switch) activation, it behaves like a toggle instead — one activation turns it on, the next turns it off — and it always reverts to valueOff if the button loses focus while on.

Property.valueComparisonStrategy must be 'reference' (the default) for the bound Property, since the model compares valueProperty.value against valueOn/valueOff with ===.

Options

Both classes accept the same appearance options as their non-momentary counterparts (RectangularButtonOptions / RoundButtonOptions) plus:

OptionEffect
valueOffSoundPlayerSound played when the button releases back to valueOff (default: shared 'toggleOff' player)
valueOnSoundPlayerSound played when the button is pressed to valueOn (default: shared 'toggleOn' player)
accessibleContextResponseValueOn / accessibleContextResponseValueOffAlertable spoken/announced content for each transition

Momentary buttons render aria-pressed, not a toggle-switch semantic

Both classes set the aria-pressed PDOM attribute to reflect whether property.value === valueOn, but the underlying interaction is still "hold to activate" — don't confuse this with Sticky Toggle Buttons, which use ariaRole: 'switch' and latch until pressed again.