From 2acceb0eab02714ce08783f6739a54c058b29d1a Mon Sep 17 00:00:00 2001 From: Marla Schulz Date: Fri, 31 Jan 2025 15:00:14 -0800 Subject: [PATCH] Add accessible names and strings for UI elements in Number Pairs, see: https://github.com/phetsims/number-pairs/issues/78 --- js/NumberPairsStrings.ts | 18 +++++++ js/common/model/RepresentationType.ts | 10 ++++ .../view/LocationCountingObjectsLayerNode.ts | 3 +- js/common/view/NumberLineNode.ts | 2 + js/common/view/NumberPairsScreenView.ts | 9 ++++ .../view/RepresentationRadioButtonGroup.ts | 7 ++- .../view/SceneSelectionRadioButtonGroup.ts | 2 + js/common/view/ShowHideAddendButton.ts | 2 + number-pairs-strings_en.json | 54 +++++++++++++++++++ 9 files changed, 105 insertions(+), 2 deletions(-) diff --git a/js/NumberPairsStrings.ts b/js/NumberPairsStrings.ts index 1639f56..1a43169 100644 --- a/js/NumberPairsStrings.ts +++ b/js/NumberPairsStrings.ts @@ -37,6 +37,24 @@ type StringsType = { 'totalJumpStringProperty': LocalizedStringProperty; 'automaticallyHearPhraseStringProperty': LocalizedStringProperty; 'automaticallyHearPhraseDescriptionStringProperty': LocalizedStringProperty; + 'hearNumberSentenceStringProperty': LocalizedStringProperty; + 'organizeObjectsStringProperty': LocalizedStringProperty; + 'organizeObjectsHelpTextStringProperty': LocalizedStringProperty; + 'swapAddendsStringProperty': LocalizedStringProperty; + 'makesAreaVisibleStringProperty': LocalizedStringProperty; + 'firstAddendNoJumpStringProperty': LocalizedStringProperty; + 'firstAddendJumpStringProperty': LocalizedStringProperty; + 'sceneSelectionRadioButtonGroupStringProperty': LocalizedStringProperty; + 'applesStringProperty': LocalizedStringProperty; + 'soccerBallsStringProperty': LocalizedStringProperty; + 'butterfliesStringProperty': LocalizedStringProperty; + 'oneCardsStringProperty': LocalizedStringProperty; + 'kittensStringProperty': LocalizedStringProperty; + 'beadsStringProperty': LocalizedStringProperty; + 'numberLineStringProperty': LocalizedStringProperty; + 'representationTypeStringProperty': LocalizedStringProperty; + 'locationCountingObjectsStringProperty': LocalizedStringProperty; + 'numberLineSliderStringProperty': LocalizedStringProperty; }; const NumberPairsStrings = getStringModule( 'NUMBER_PAIRS' ) as StringsType; diff --git a/js/common/model/RepresentationType.ts b/js/common/model/RepresentationType.ts index 96db3cf..2db4efb 100644 --- a/js/common/model/RepresentationType.ts +++ b/js/common/model/RepresentationType.ts @@ -23,6 +23,8 @@ import NumberPairsColors from '../NumberPairsColors.js'; import NumberLineIcon from '../view/NumberLineIcon.js'; // eslint-disable-next-line phet/no-view-imported-from-model import OneCard from '../view/OneCard.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; +import TProperty from '../../../../axon/js/TProperty.js'; const ICON_MAX_WIDTH = 25; @@ -32,6 +34,7 @@ export default class RepresentationType extends EnumerationValue { public static readonly APPLES = new RepresentationType( 'apples', + NumberPairsStrings.applesStringProperty, NumberPairsColors.locationSumColorProperty, NumberPairsColors.locationLeftAddendColorProperty, NumberPairsColors.locationRightAddendColorProperty, @@ -39,6 +42,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly SOCCER_BALLS = new RepresentationType( 'soccerBalls', + NumberPairsStrings.soccerBallsStringProperty, NumberPairsColors.locationSumColorProperty, NumberPairsColors.locationLeftAddendColorProperty, NumberPairsColors.locationRightAddendColorProperty, @@ -46,6 +50,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly BUTTERFLIES = new RepresentationType( 'butterflies', + NumberPairsStrings.butterfliesStringProperty, NumberPairsColors.locationSumColorProperty, NumberPairsColors.locationLeftAddendColorProperty, NumberPairsColors.locationRightAddendColorProperty, @@ -53,6 +58,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly ONE_CARDS = new RepresentationType( 'oneCards', + NumberPairsStrings.oneCardsStringProperty, NumberPairsColors.locationSumColorProperty, NumberPairsColors.locationLeftAddendColorProperty, NumberPairsColors.locationRightAddendColorProperty, @@ -60,6 +66,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly KITTENS = new RepresentationType( 'kittens', + NumberPairsStrings.kittensStringProperty, NumberPairsColors.attributeSumColorProperty, NumberPairsColors.attributeLeftAddendColorProperty, NumberPairsColors.attributeRightAddendColorProperty, @@ -67,6 +74,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly BEADS = new RepresentationType( 'beads', + NumberPairsStrings.beadsStringProperty, NumberPairsColors.numberLineSumColorProperty, NumberPairsColors.numberLineLeftAddendColorProperty, NumberPairsColors.numberLineRightAddendColorProperty, @@ -74,6 +82,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly NUMBER_LINE = new RepresentationType( 'numberLine', + NumberPairsStrings.numberLineStringProperty, NumberPairsColors.numberLineSumColorProperty, NumberPairsColors.numberLineLeftAddendColorProperty, NumberPairsColors.numberLineRightAddendColorProperty, @@ -83,6 +92,7 @@ export default class RepresentationType extends EnumerationValue { public constructor( public readonly label: string, + public readonly accessibleName: TProperty, public readonly totalColorProperty: Property, public readonly leftAddendColorProperty: Property, public readonly rightAddendColorProperty: Property, diff --git a/js/common/view/LocationCountingObjectsLayerNode.ts b/js/common/view/LocationCountingObjectsLayerNode.ts index 4a8cbc8..014f0de 100644 --- a/js/common/view/LocationCountingObjectsLayerNode.ts +++ b/js/common/view/LocationCountingObjectsLayerNode.ts @@ -22,6 +22,7 @@ import DynamicProperty from '../../../../axon/js/DynamicProperty.js'; import LocationCountingObjectNode from './LocationCountingObjectNode.js'; import NumberPairsConstants from '../NumberPairsConstants.js'; import CountingAreaNode from './CountingAreaNode.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type LocationCountingObjectsLayerNodeOptions = WithRequired; @@ -32,7 +33,7 @@ export default class LocationCountingObjectsLayerNode extends Node { public constructor( private readonly model: NumberPairsModel, countingAreaNode: CountingAreaNode, providedOptions: LocationCountingObjectsLayerNodeOptions ) { const options = optionize()( { - accessibleName: 'Location Counting Objects' + accessibleName: NumberPairsStrings.locationCountingObjectsStringProperty }, providedOptions ); super( options ); diff --git a/js/common/view/NumberLineNode.ts b/js/common/view/NumberLineNode.ts index b8fc5f0..4adc9dc 100644 --- a/js/common/view/NumberLineNode.ts +++ b/js/common/view/NumberLineNode.ts @@ -22,6 +22,7 @@ import CurvedArrowNode from './CurvedArrowNode.js'; import NumberLineSlider from './NumberLineSlider.js'; import NumberRectangle from './NumberRectangle.js'; import Dimension2 from '../../../../dot/js/Dimension2.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type SelfOptions = { numberLineRange: Range; @@ -56,6 +57,7 @@ export default class NumberLineNode extends Node { trackModelViewTransform, model.showTickValuesProperty, { + accessibleName: NumberPairsStrings.numberLineSliderStringProperty, numberLineRange: options.numberLineRange, numberLineWidth: numberLineWidth, tandem: options.tandem.createTandem( 'slider' ) diff --git a/js/common/view/NumberPairsScreenView.ts b/js/common/view/NumberPairsScreenView.ts index 4147edb..091f66c 100644 --- a/js/common/view/NumberPairsScreenView.ts +++ b/js/common/view/NumberPairsScreenView.ts @@ -38,6 +38,7 @@ import SpeechSynthesisControl from '../../../../number-suite-common/js/common/vi import LocaleSwitch from '../../../../number-suite-common/js/common/view/LocaleSwitch.js'; import NumberPairsPreferences from '../model/NumberPairsPreferences.js'; import { NumberPairsUtils } from '../model/NumberPairsUtils.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type SelfOptions = { numberSentenceContent: Node; @@ -128,6 +129,9 @@ export default class NumberPairsScreenView extends ScreenView { * Create the buttons along the left edge of each screen */ const speechSynthesisControl = new SpeechSynthesisControl( numberPairsSpeechSynthesisAnnouncer, numberPairsUtteranceQueue, { + speechSynthesisButtonOptions: { + accessibleName: NumberPairsStrings.hearNumberSentenceStringProperty + }, x: this.layoutBounds.minX + NumberPairsConstants.SCREEN_VIEW_X_MARGIN, y: this.layoutBounds.minY + NumberPairsConstants.SCREEN_VIEW_Y_MARGIN, tandem: options.tandem.createTandem( 'speechSynthesisControl' ) @@ -151,6 +155,8 @@ export default class NumberPairsScreenView extends ScreenView { const sumTenFrameBounds = COUNTING_AREA_BOUNDS.erodedX( COUNTING_AREA_BOUNDS.width / 3.5 ); const tenFrameBounds = options.sumScreen ? [ sumTenFrameBounds ] : NumberPairsUtils.splitBoundsInHalf( COUNTING_AREA_BOUNDS ); const tenFrameButton = new TenFrameButton( { + accessibleName: NumberPairsStrings.organizeObjectsStringProperty, + helpText: NumberPairsStrings.organizeObjectsHelpTextStringProperty, tandem: options.tandem.createTandem( 'tenFrameButton' ), listener: () => { this.interruptSubtreeInput(); @@ -166,6 +172,7 @@ export default class NumberPairsScreenView extends ScreenView { } ); const commutativeButton = new CommutativeButton( { + accessibleName: NumberPairsStrings.swapAddendsStringProperty, listener: () => { this.interruptSubtreeInput(); model.swapAddends.bind( model )(); @@ -300,6 +307,8 @@ export default class NumberPairsScreenView extends ScreenView { top: COUNTING_AREA_BOUNDS.bottom + COUNTING_AREA_Y_MARGIN, left: COUNTING_AREA_BOUNDS.left, visibleProperty: numberLineVisibleProperty, + valueAAccessibleName: NumberPairsStrings.firstAddendNoJumpStringProperty, + valueBAccessibleName: NumberPairsStrings.firstAddendJumpStringProperty, toggleSwitchOptions: { size: new Dimension2( 36, 18 ) }, diff --git a/js/common/view/RepresentationRadioButtonGroup.ts b/js/common/view/RepresentationRadioButtonGroup.ts index 53515d1..e9a95d2 100644 --- a/js/common/view/RepresentationRadioButtonGroup.ts +++ b/js/common/view/RepresentationRadioButtonGroup.ts @@ -16,6 +16,7 @@ import { Color, Node } from '../../../../scenery/js/imports.js'; import RectangularRadioButtonGroup, { RectangularRadioButtonGroupOptions } from '../../../../sun/js/buttons/RectangularRadioButtonGroup.js'; import numberPairs from '../../numberPairs.js'; import RepresentationType, { ICON_MAX_HEIGHT } from '../model/RepresentationType.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type SelfOptions = EmptySelfOptions; type CountingRepresentationRadioButtonGroupOptions = SelfOptions & PickRequired & @@ -29,12 +30,16 @@ export default class RepresentationRadioButtonGroup extends RectangularRadioButt return { value: countingRepresentationType, createNode: () => new Node( { children: [ countingRepresentationType.icon ] } ), - tandemName: countingRepresentationType.label + 'RadioButton' + tandemName: countingRepresentationType.label + 'RadioButton', + options: { + accessibleName: countingRepresentationType.accessibleName + } }; } ) || []; const buttonMargin = 3; const options = optionize()( { + accessibleName: NumberPairsStrings.representationTypeStringProperty, orientation: 'horizontal', radioButtonOptions: { baseColor: Color.WHITE, diff --git a/js/common/view/SceneSelectionRadioButtonGroup.ts b/js/common/view/SceneSelectionRadioButtonGroup.ts index ded5696..e99dfcd 100644 --- a/js/common/view/SceneSelectionRadioButtonGroup.ts +++ b/js/common/view/SceneSelectionRadioButtonGroup.ts @@ -16,6 +16,7 @@ import { Text } from '../../../../scenery/js/imports.js'; import RectangularRadioButtonGroup, { RectangularRadioButtonGroupOptions } from '../../../../sun/js/buttons/RectangularRadioButtonGroup.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsScene from '../model/NumberPairsScene.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type SelfOptions = { sceneRange: Range; @@ -26,6 +27,7 @@ export default class SceneSelectionRadioButtonGroup extends RectangularRadioButt public constructor( selectedSceneModelProperty: PhetioProperty, sceneModels: NumberPairsScene[], providedOptions: SceneSelectionRadioButtonGroupOptions ) { const options = optionize()( { + accessibleName: NumberPairsStrings.sceneSelectionRadioButtonGroupStringProperty, radioButtonOptions: { size: new Dimension2( 40, 40 ) } diff --git a/js/common/view/ShowHideAddendButton.ts b/js/common/view/ShowHideAddendButton.ts index 07cd082..a4d6c2d 100644 --- a/js/common/view/ShowHideAddendButton.ts +++ b/js/common/view/ShowHideAddendButton.ts @@ -19,6 +19,7 @@ import eyeSolidShape from '../../../../sherpa/js/fontawesome-5/eyeSolidShape.js' import RectangularPushButton, { RectangularPushButtonOptions } from '../../../../sun/js/buttons/RectangularPushButton.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsConstants from '../NumberPairsConstants.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type SelfOptions = { secondAddendVisibleProperty?: BooleanProperty | null; @@ -30,6 +31,7 @@ export default class ShowHideAddendButton extends RectangularPushButton { public constructor( addendVisibleProperty: BooleanProperty, providedOptions: ShowHideAddendButtonOptions ) { const initialOptions = optionize()( { + accessibleName: NumberPairsStrings.makesAreaVisibleStringProperty, size: new Dimension2( NumberPairsConstants.RECTANGULAR_PUSH_BUTTON_OPTIONS.size.width, 40 ), secondAddendVisibleProperty: null, baseColor: Color.WHITE diff --git a/number-pairs-strings_en.json b/number-pairs-strings_en.json index 05e0818..b85e4fe 100644 --- a/number-pairs-strings_en.json +++ b/number-pairs-strings_en.json @@ -61,5 +61,59 @@ }, "automaticallyHearPhraseDescription": { "value": "Hear the phrase update automatically as you interact." + }, + "hearNumberSentence": { + "value": "Hear Number Sentence" + }, + "organizeObjects": { + "value": "Organize Objects" + }, + "organizeObjectsHelpText": { + "value": "Organizes objects into groups of five." + }, + "swapAddends": { + "value": "Swap Addends" + }, + "makesAreaVisible": { + "value": "Makes area visible." + }, + "firstAddendNoJump": { + "value": "First Addend No Jump" + }, + "firstAddendJump": { + "value": "First Addend Jump" + }, + "sceneSelectionRadioButtonGroup": { + "value": "Scene Selection Radio Button Group" + }, + "apples": { + "value": "Apples" + }, + "soccerBalls": { + "value": "Soccer Balls" + }, + "butterflies": { + "value": "Butterflies" + }, + "oneCards": { + "value": "One Cards" + }, + "kittens": { + "value": "Kittens" + }, + "beads": { + "value": "Beads" + }, + "numberLine": { + "value": "Number Line" + }, + "representationType": { + "value": "Representation Type" + }, + "locationCountingObjects": { + "value": "Location Counting Objects" + }, + "numberLineSlider": { + "value": "Number Line Slider" } } \ No newline at end of file