From 64b27c7faf56e9e6109465c8e74f4b4818783ca6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 16:41:03 +0000 Subject: [PATCH] Fix dark-theme ComboBox contrast and flatten button appearance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preset ComboBoxes in both control panels drew near-white item text without a matching buttonFill/listFill, so they fell back to SceneryStack's default white chrome — near-invisible against the default (dark) color profile. Give them dark buttonFill/listFill from SolarSystemModelsColors, matching the pattern already used in OscillationsAndChaos. Also add SolarSystemModelsButtonOptions.ts with a FlatAppearanceStrategy bundle (mirroring RotatingSky's RotatingSkyButtonOptions.ts) and apply it to every RectangularPushButton, ResetAllButton, and TimeControlNode play/pause/step button so the sim uses a flat button look instead of SceneryStack's default 3-D bevel. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_018svZaRUmD44JWTQJLUYdmx --- src/common/SolarSystemModelsButtonOptions.ts | 51 +++++++++++++++++++ .../view/ConfigurationsControlPanel.ts | 10 ++++ .../view/ConfigurationsScreenView.ts | 2 + src/ptolemaic/view/PtolemaicControlPanel.ts | 7 +++ src/ptolemaic/view/PtolemaicScreenView.ts | 2 + src/ptolemaic/view/PtolemaicTimeControls.ts | 7 +++ 6 files changed, 79 insertions(+) create mode 100644 src/common/SolarSystemModelsButtonOptions.ts diff --git a/src/common/SolarSystemModelsButtonOptions.ts b/src/common/SolarSystemModelsButtonOptions.ts new file mode 100644 index 0000000..416fd39 --- /dev/null +++ b/src/common/SolarSystemModelsButtonOptions.ts @@ -0,0 +1,51 @@ +/** + * SolarSystemModelsButtonOptions.ts + * + * Shared flat button appearance for the sim. Rectangular and round push buttons + * (RectangularPushButton, ResetAllButton, TimeControlNode's nested play/pause/step + * buttons) default to SceneryStack's 3-D beveled appearance; spread these options + * (or the nested bundle) in to get a flat look everywhere instead. + * + * Also exports the ComboBox chrome used for preset selectors: the sim's default + * color profile is dark (SolarSystemModelsColors.backgroundColorProperty / + * panelBackgroundColorProperty), and ComboBox item labels are drawn with the + * near-white SolarSystemModelsColors.textColorProperty, so the ComboBox itself + * must be given matching dark buttonFill/listFill — otherwise it silently falls + * back to SceneryStack's default white chrome, producing near-invisible + * near-white-on-white text in the default profile. + */ + +import type { PlayPauseStepButtonGroupOptions } from "scenerystack/scenery-phet"; +import { ButtonNode, type ComboBoxOptions } from "scenerystack/sun"; +import SolarSystemModelsColors from "../SolarSystemModelsColors.js"; + +export const FLAT_BUTTON_APPEARANCE_OPTIONS = { + buttonAppearanceStrategy: ButtonNode.FlatAppearanceStrategy, +} as const; + +/** Options for RectangularPushButton and similar rectangular buttons. */ +export const FLAT_RECTANGULAR_BUTTON_OPTIONS = FLAT_BUTTON_APPEARANCE_OPTIONS; + +/** Options for ResetAllButton (extends RoundPushButton). */ +export const FLAT_RESET_ALL_BUTTON_OPTIONS = FLAT_BUTTON_APPEARANCE_OPTIONS; + +/** Nested options for TimeControlNode's play / pause / step round buttons. */ +export const FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS = { + playPauseButtonOptions: FLAT_BUTTON_APPEARANCE_OPTIONS, + stepForwardButtonOptions: FLAT_BUTTON_APPEARANCE_OPTIONS, + stepBackwardButtonOptions: FLAT_BUTTON_APPEARANCE_OPTIONS, +} satisfies PlayPauseStepButtonGroupOptions; + +/** + * Combo-box chrome for preset selectors on the dark panel. Pairs the panel's own + * dark background/border colors with the ComboBox so its near-white item text + * (SolarSystemModelsColors.textColorProperty) stays readable in both the default + * (dark) and projector (light) profiles. + */ +export const SOLAR_SYSTEM_MODELS_COMBO_BOX_OPTIONS = { + buttonFill: SolarSystemModelsColors.panelBackgroundColorProperty, + listFill: SolarSystemModelsColors.panelBackgroundColorProperty, + buttonStroke: SolarSystemModelsColors.panelBorderColorProperty, + listStroke: SolarSystemModelsColors.panelBorderColorProperty, + highlightFill: SolarSystemModelsColors.panelBorderColorProperty, +} satisfies Pick; diff --git a/src/configurations/view/ConfigurationsControlPanel.ts b/src/configurations/view/ConfigurationsControlPanel.ts index e39da73..7f4cc3b 100644 --- a/src/configurations/view/ConfigurationsControlPanel.ts +++ b/src/configurations/view/ConfigurationsControlPanel.ts @@ -4,6 +4,11 @@ import { HBox, Text, VBox } from "scenerystack/scenery"; import { NumberControl, PhetFont, TimeControlNode } from "scenerystack/scenery-phet"; import { AquaRadioButtonGroup, ComboBox, HSlider, RectangularPushButton } from "scenerystack/sun"; import type { Tandem } from "scenerystack/tandem"; +import { + FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS, + FLAT_RECTANGULAR_BUTTON_OPTIONS, + SOLAR_SYSTEM_MODELS_COMBO_BOX_OPTIONS, +} from "../../common/SolarSystemModelsButtonOptions.js"; import { SolarSystemModelsPanel } from "../../common/SolarSystemModelsPanel.js"; import { StringManager } from "../../i18n/StringManager.js"; import SolarSystemModelsColors from "../../SolarSystemModelsColors.js"; @@ -51,11 +56,13 @@ export class ConfigurationsControlPanel extends SolarSystemModelsPanel { })); const preset1Combo = new ComboBox(model.preset1IndexProperty, observer1Items, listParent, { + ...SOLAR_SYSTEM_MODELS_COMBO_BOX_OPTIONS, accessibleName: a11y.controls.observerPlanetStringProperty, }); preset1Combo.addLinkedElement(model.preset1IndexProperty); const preset2Combo = new ComboBox(model.preset2IndexProperty, observer2Items, listParent, { + ...SOLAR_SYSTEM_MODELS_COMBO_BOX_OPTIONS, accessibleName: a11y.controls.targetPlanetStringProperty, }); @@ -109,7 +116,9 @@ export class ConfigurationsControlPanel extends SolarSystemModelsPanel { // ── TimeControlNode ─────────────────────────────────────────────────── const timeControlNode = new TimeControlNode(model.timer.isPlayingProperty, { playPauseStepButtonOptions: { + ...FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS, stepForwardButtonOptions: { + ...FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS.stepForwardButtonOptions, listener: () => { if (!model.timer.isPlayingProperty.value) { model.step(1 / 60); @@ -135,6 +144,7 @@ export class ConfigurationsControlPanel extends SolarSystemModelsPanel { content: new Text(s.resetTimeStringProperty, labelOpts), listener: () => model.resetTime(), accessibleName: a11y.controls.resetTimeStringProperty, + ...FLAT_RECTANGULAR_BUTTON_OPTIONS, }); // ── Event action radio group ────────────────────────────────────────── diff --git a/src/configurations/view/ConfigurationsScreenView.ts b/src/configurations/view/ConfigurationsScreenView.ts index 403be8e..40a90d5 100644 --- a/src/configurations/view/ConfigurationsScreenView.ts +++ b/src/configurations/view/ConfigurationsScreenView.ts @@ -9,6 +9,7 @@ import type { ScreenViewOptions } from "scenerystack/sim"; import { ScreenView } from "scenerystack/sim"; import { Tandem } from "scenerystack/tandem"; import { CelestialBodyNode } from "../../common/CelestialBodyNode.js"; +import { FLAT_RESET_ALL_BUTTON_OPTIONS } from "../../common/SolarSystemModelsButtonOptions.js"; import { ZodiacConstellationNode } from "../../common/ZodiacConstellationNode.js"; import { StringManager } from "../../i18n/StringManager.js"; import SolarSystemModelsColors from "../../SolarSystemModelsColors.js"; @@ -232,6 +233,7 @@ export class ConfigurationsScreenView extends ScreenView { }, right: this.layoutBounds.maxX - SCREEN_VIEW_MARGIN, bottom: this.layoutBounds.maxY - SCREEN_VIEW_MARGIN, + ...FLAT_RESET_ALL_BUTTON_OPTIONS, }); this.addChild(resetAllButton); diff --git a/src/ptolemaic/view/PtolemaicControlPanel.ts b/src/ptolemaic/view/PtolemaicControlPanel.ts index 768f5df..99ca683 100644 --- a/src/ptolemaic/view/PtolemaicControlPanel.ts +++ b/src/ptolemaic/view/PtolemaicControlPanel.ts @@ -3,6 +3,10 @@ import { HBox, type Node, Text, VBox } from "scenerystack/scenery"; import { NumberControl, PhetFont } from "scenerystack/scenery-phet"; import { AquaRadioButtonGroup, ComboBox, RectangularPushButton } from "scenerystack/sun"; import type { Tandem } from "scenerystack/tandem"; +import { + FLAT_RECTANGULAR_BUTTON_OPTIONS, + SOLAR_SYSTEM_MODELS_COMBO_BOX_OPTIONS, +} from "../../common/SolarSystemModelsButtonOptions.js"; import { SolarSystemModelsPanel } from "../../common/SolarSystemModelsPanel.js"; import { StringManager } from "../../i18n/StringManager.js"; import SolarSystemModelsColors from "../../SolarSystemModelsColors.js"; @@ -48,6 +52,7 @@ export class PtolemaicControlPanel extends SolarSystemModelsPanel { }); const presetComboBox = new ComboBox(model.presetKeyProperty, comboItems, listParent, { + ...SOLAR_SYSTEM_MODELS_COMBO_BOX_OPTIONS, accessibleName: a11y.controls.planetPresetStringProperty, }); @@ -135,6 +140,7 @@ export class PtolemaicControlPanel extends SolarSystemModelsPanel { }), listener: () => model.storeMemory(), accessibleName: a11y.controls.memoryStoreStringProperty, + ...FLAT_RECTANGULAR_BUTTON_OPTIONS, }); const recallButton = new RectangularPushButton({ content: new Text(strings.memoryRecallStringProperty, { @@ -143,6 +149,7 @@ export class PtolemaicControlPanel extends SolarSystemModelsPanel { }), listener: () => model.recallMemory(), accessibleName: a11y.controls.memoryRecallStringProperty, + ...FLAT_RECTANGULAR_BUTTON_OPTIONS, }); const content = new VBox({ diff --git a/src/ptolemaic/view/PtolemaicScreenView.ts b/src/ptolemaic/view/PtolemaicScreenView.ts index 5575d2d..ab036e8 100644 --- a/src/ptolemaic/view/PtolemaicScreenView.ts +++ b/src/ptolemaic/view/PtolemaicScreenView.ts @@ -8,6 +8,7 @@ import type { ScreenViewOptions } from "scenerystack/sim"; import { ScreenView } from "scenerystack/sim"; import { Tandem } from "scenerystack/tandem"; import { CelestialBodyNode } from "../../common/CelestialBodyNode.js"; +import { FLAT_RESET_ALL_BUTTON_OPTIONS } from "../../common/SolarSystemModelsButtonOptions.js"; import { ZodiacConstellationNode } from "../../common/ZodiacConstellationNode.js"; import { StringManager } from "../../i18n/StringManager.js"; import SolarSystemModelsColors from "../../SolarSystemModelsColors.js"; @@ -313,6 +314,7 @@ export class PtolemaicScreenView extends ScreenView { }, right: this.layoutBounds.maxX - SCREEN_VIEW_MARGIN, bottom: this.layoutBounds.maxY - SCREEN_VIEW_MARGIN, + ...FLAT_RESET_ALL_BUTTON_OPTIONS, }); this.addChild(resetAllButton); diff --git a/src/ptolemaic/view/PtolemaicTimeControls.ts b/src/ptolemaic/view/PtolemaicTimeControls.ts index 1d02832..be89d55 100644 --- a/src/ptolemaic/view/PtolemaicTimeControls.ts +++ b/src/ptolemaic/view/PtolemaicTimeControls.ts @@ -2,6 +2,10 @@ import { Dimension2, Range } from "scenerystack/dot"; import { Text, VBox } from "scenerystack/scenery"; import { PhetFont, TimeControlNode } from "scenerystack/scenery-phet"; import { HSlider, RectangularPushButton } from "scenerystack/sun"; +import { + FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS, + FLAT_RECTANGULAR_BUTTON_OPTIONS, +} from "../../common/SolarSystemModelsButtonOptions.js"; import { SolarSystemModelsPanel } from "../../common/SolarSystemModelsPanel.js"; import { StringManager } from "../../i18n/StringManager.js"; import SolarSystemModelsColors from "../../SolarSystemModelsColors.js"; @@ -19,7 +23,9 @@ export class PtolemaicTimeControls extends SolarSystemModelsPanel { const timeControlNode = new TimeControlNode(model.timer.isPlayingProperty, { playPauseStepButtonOptions: { + ...FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS, stepForwardButtonOptions: { + ...FLAT_PLAY_PAUSE_STEP_BUTTON_OPTIONS.stepForwardButtonOptions, listener: () => { if (!model.timer.isPlayingProperty.value) { model.step(1 / 60); @@ -64,6 +70,7 @@ export class PtolemaicTimeControls extends SolarSystemModelsPanel { }), listener: () => model.resetTime(), accessibleName: a11y.controls.resetTimeStringProperty, + ...FLAT_RECTANGULAR_BUTTON_OPTIONS, }); const content = new VBox({