Skip to content

Play Control Buttons

PlayControlButton is the round BooleanRoundToggleButton base class behind PlayPauseButton: it always shows a triangular "play" icon for false, and takes an arbitrary Node icon for whatever true ("currently playing/running") should look like. PlayStopButton is the other built-in specialization, using a square "stop" icon instead of pause bars. RecordStopButton looks like a sibling but is actually independent — and PlayPauseStepButtonGroup is the HBox layout that combines a play/pause button with step buttons, used internally by TimeControlNode.

ts
import { PlayStopButton, RecordStopButton, PlayPauseStepButtonGroup } from 'scenerystack/scenery-phet';
import { Property } from 'scenerystack/axon';

A minimal example

ts
const isRunningProperty = new Property<boolean>( false );
const isRecordingProperty = new Property<boolean>( false );

// A play/stop toggle where stopping restarts from the beginning (unlike PlayPauseButton).
const playStopButton = new PlayStopButton( isRunningProperty, {
  tandem: tandem.createTandem( 'playStopButton' )
} );

// A record/stop toggle for a data-recording feature.
const recordStopButton = new RecordStopButton( isRecordingProperty, {
  tandem: tandem.createTandem( 'recordStopButton' )
} );

// The play/pause + step-forward group TimeControlNode builds internally.
const buttonGroup = new PlayPauseStepButtonGroup( isRunningProperty, {
  includeStepBackwardButton: true,
  tandem: tandem.createTandem( 'buttonGroup' )
} );

PlayControlButton (base class)

ts
new PlayControlButton(
  isPlayingProperty: Property<boolean>,
  endPlayingIcon: Node,
  providedOptions?: PlayControlButtonOptions
)
OptionDefaultEffect
radiusSceneryPhetConstants.PLAY_CONTROL_BUTTON_RADIUS (28)Button radius; both the play triangle and endPlayingIcon are sized relative to it
scaleFactorWhenNotPlaying1Scales the whole button up (or down) while showing the "play" icon, per PhET's convention of enlarging play buttons that don't immediately resume stepping
includeGlobalHotkeyfalseIf true (and interactive description is supported), wires a global alt+K hotkey — via the static PlayControlButton.TOGGLE_PLAY_HOTKEY_DATA — that toggles isPlayingProperty regardless of document focus
startPlayingAccessibleName / endPlayingAccessibleNamelocalized "Play" / nullPDOM accessible names for each state; subclasses fill in endPlayingAccessibleName
valueOnSoundPlayer / valueOffSoundPlayershared 'play' / 'pause' sound playersSounds played only by the global hotkey path, not by pointer presses (those use the button's own soundPlayer)

PlayPauseButton (documented separately) fixes endPlayingIcon to a two-bar pause glyph and turns includeGlobalHotkey on by default.

PlayStopButton

ts
new PlayStopButton( isPlayingProperty: Property<boolean>, providedOptions?: PlayStopButtonOptions )

A PlayControlButton subclass with endPlayingIcon fixed to a square "stop" glyph (StopIconShape). The source comment is explicit about the semantic difference from PlayPauseButton: "Unlike the PlayPauseButton, this indicates that play will re-start from the beginning after switching from play to stop" — use it wherever pressing stop resets progress rather than merely pausing it.

RecordStopButton

ts
new RecordStopButton( recordingProperty: Property<boolean>, providedOptions?: RecordStopButtonOptions )
OptionDefaultEffect
radius30Button radius
recordIconColor / stopIconColorPhetColorScheme.RED_COLORBLIND for bothColors of the record-dot and stop-square icons

RecordStopButton does not extend PlayControlButton

Despite the naming pattern, RecordStopButton is its own direct BooleanRoundToggleButton subclass (a red circle for "record," a red square for "stop") — it doesn't share PlayControlButton's radius default, hotkey support, or scaleFactorWhenNotPlaying option. Don't assume PlayControlButtonOptions apply to it.

PlayPauseStepButtonGroup

ts
new PlayPauseStepButtonGroup( isPlayingProperty: Property<boolean>, providedOptions?: PlayPauseStepButtonGroupOptions )

An HBox that lays out one PlayPauseButton alongside optional StepForwardButton/StepBackwardButton instances. This is what TimeControlNode builds internally rather than composing those buttons by hand.

OptionDefaultEffect
includeStepForwardButtontrueWhether a step-forward button is included
includeStepBackwardButtonfalseWhether a step-backward button is included
playPauseStepXSpacing10Horizontal spacing between the play/pause button and the step buttons
playPauseButtonOptions / stepForwardButtonOptions / stepBackwardButtonOptionsradius SceneryPhetConstants.DEFAULT_BUTTON_RADIUS / 15 / 15Forwarded to the respective internal button

If you don't supply an enabledProperty for the step buttons yourself, the group derives one automatically as DerivedProperty.not( isPlayingProperty ), so step buttons are enabled only while paused — you don't have to wire that up by hand the way you would using StepForwardButton/StepBackwardButton standalone.

Members

MemberDescription
playPauseButtonPublic reference to the internal PlayPauseButton, for positioning
getPlayPauseButtonCenter()Returns the PlayPauseButton's center in the group's local coordinate frame

Reach for TimeControlNode first

Unless you're building a custom layout, TimeControlNode already composes PlayPauseStepButtonGroup with an optional TimeSpeedRadioButtonGroup — most sims never need to construct PlayPauseStepButtonGroup directly.