Skip to content

PhetColorScheme, SceneryPhetColors, and SceneryPhetConstants

PhetColorScheme, SceneryPhetColors, and SceneryPhetConstants (all from scenerystack/scenery-phet) are three small plain-object modules of shared defaults, in the same spirit as scenerystack/sun's ColorConstants/SunConstants: reuse a fixed value from one of these tables instead of re-picking an RGB triple or a magic number every time a physics quantity or a round button shows up in a new sim. None of the three is a class — all are read directly as properties on a plain object (or, for SceneryPhetColors, a plain object of ProfileColorProperty instances).

ts
import { PhetColorScheme, SceneryPhetColors, SceneryPhetConstants } from 'scenerystack/scenery-phet';
import { GaugeNode } from 'scenerystack/scenery-phet';

A minimal example

ts
// Color a force vector consistently with every other PhET sim that shows applied force:
const arrowFill = PhetColorScheme.APPLIED_FORCE;

// Size a custom round button the same as scenery-phet's own round buttons:
const buttonRadius = SceneryPhetConstants.DEFAULT_BUTTON_RADIUS;

// Read (or link to) the currently-active fill for a beaker drawing:
const beakerFill = SceneryPhetColors.solutionFillProperty.value;

PhetColorScheme

A flat table of Color (from scenerystack/scenery) and one plain hex-string constant, mostly named after the physical quantity each color conventionally represents in PhET sims (kinetic/potential energy, forces, momentum, and so on) — the exact palette PhET's own physics sims (Forces and Motion, Energy Skate Park, etc.) draw from so a "kinetic energy" bar chart segment looks the same color from one sim to the next.

ConstantValueNotes
ACCELERATIONColor(255, 255, 50)
APPLIED_FORCEColor(236, 153, 55)
BUTTON_YELLOWColor(254, 225, 5)Same value as PHET_LOGO_YELLOW
ELASTIC_POTENTIAL_ENERGYColor(0, 204, 255)
FRICTION_FORCEColor(255, 85, 0)Same value as RED_COLORBLIND
GRAVITATIONAL_FORCEColor(50, 130, 215)
GRAVITATIONAL_POTENTIAL_ENERGYColor(55, 130, 215)
HEAT_THERMAL_ENERGYColor(255, 85, 0)Same value as RED_COLORBLIND
IMAGINARY_PARTColor(153, 51, 102)
KINETIC_ENERGYColor(30, 200, 45)
MOMENTUMColor(50, 50, 255)
NET_WORKColor(0, 200, 0)"Dark green"
NORMAL_FORCEColor(255, 235, 0)
PHET_LOGO_BLUEColor(106, 206, 245)The blue in the PhET logo
PHET_LOGO_YELLOWColor(254, 225, 5)The yellow in the PhET logo
POSITIONColor.BLUEScenery's built-in blue
REAL_PARTColor(255, 153, 0)
RED_COLORBLINDColor(255, 85, 0)Reads well in colorblindness tests; used in place of plain 'red' throughout PhET sims
GREEN_COLORBLINDColor(0, 135, 0)Pairs correctly with RED_COLORBLIND in colorblindness tests
RESET_ALL_BUTTON_BASE_COLORColor(247, 151, 34)The standard PhET orange — ResetAllButton's default baseColor
TOTAL_ENERGYColor(180, 180, 0)
TOTAL_FORCEColor(0, 200, 0)Same value as NET_WORK
VELOCITYColor(50, 255, 50)
WALL_FORCEColor(153, 51, 0)
SCREEN_ICON_FRAME'#dddddd'The one plain CSS-string constant in the table (not a Color instance)

Prefer RED_COLORBLIND/GREEN_COLORBLIND over plain 'red'/'green'

These two are called out by name in the source comments as deliberately colorblind-safe substitutes — reach for them instead of literal 'red'/'green' whenever a sim needs a red/green pair that must stay distinguishable under common color-vision deficiencies.

SceneryPhetColors

Unlike PhetColorScheme, every value here is a ProfileColorProperty (from scenerystack/scenery) rather than a bare Color — meaning these support PhET's color-profile system (e.g. a "projector mode" palette swap) and should be linked to, not read once, if you want a component to update live when the active profile changes. All are used for the beaker drawings shared by state-of-matter/fractions-style sims.

PropertyDefault
emptyBeakerFillPropertyColor(249, 253, 255, 0.2)
solutionFillPropertyColor(165, 217, 242)
beakerShineFillPropertyColor(255, 255, 255, 0.4)
solutionShadowFillPropertyColor(142, 198, 221)
solutionShineFillPropertyColor(180, 229, 249)
beakerStroke'black'
tickStroke'black'

SceneryPhetConstants

The smallest of the three — just two numbers, used to keep round buttons visually consistent in size across components that don't otherwise share a base class.

ConstantValueUsed for
DEFAULT_BUTTON_RADIUS20.8Default radius for most round buttons (e.g. ResetAllButton)
PLAY_CONTROL_BUTTON_RADIUS28Default radius for PlayControlButton and its subtypes (play/pause, step)

PhetColorScheme values are plain Colors; SceneryPhetColors values are ProfileColorPropertys

Passing PhetColorScheme.APPLIED_FORCE directly as a fill works exactly like passing any other Color. Passing SceneryPhetColors.solutionFillProperty the same way is also valid (scenery accepts a TReadOnlyProperty<Color> as a paint), but reading .value off of it up front (as in the minimal example) discards the live color-profile updates you'd otherwise get for free — prefer passing the Property itself as the fill/stroke option when you want profile changes to repaint automatically.