phetsims / a11y-research

a repository to track PhETs research into accessibility, or "a11y" for short
MIT License
3 stars 0 forks source link

how to handle toggle buttons whose labels change? #137

Closed pixelzoom closed 2 years ago

pixelzoom commented 5 years ago

The Gas Properties design document specifies a toggle button whose label changes when pressed:

screenshot_1134

Note that this is naturally implemented as a toggle button (versus 2 push buttons), because (1) it toggles between 2 states, (2) the button width is constant regardless of the label, and (3) PhET-iO needs to treat this as a single button.

But from ARIA Authoring Practices for buttons, https://www.w3.org/TR/wai-aria-practices-1.1/#button (with their emphasis):

Important: it is critical the label on a toggle does not change when its state changes.

Looking at other PhET sims, this principal appears to be violated elsewhere, e.g. the "Remove Wall / Add Wall" toggle button in BASE.

Please provide guidance on:

(1) What should be done in general? Is PhET following this ARIA practice? (2) What should be done specifically in Gas Properties?

pixelzoom commented 5 years ago

Here's the code in BASE ControlPanel that creates the toggle button mentioned above:

// Add/Remove wall button.
var addWallText = new MultiLineText( addWallString, ... );
var removeWallText = new MultiLineText( removeWallString, ... );
var wallToggleNode = new BooleanToggleNode( removeWallText, addWallText, model.wall.isVisibleProperty, ... );
this.wallButton = new RectangularPushButton( {
  content: wallToggleNode,
  listener: function() {
  model.wall.isVisibleProperty.set( !model.wall.isVisibleProperty.get() );
},
... 
} );

EDIT: The above is a very odd implementation. It's equivalent to BooleanRectangularToggleButton, but more complicated.

jessegreenberg commented 5 years ago

In general, toggle buttons shouldn't have changing labels and their state should be conveyed with aria-pressed. NavigationBarSoundToggleButton is an example of where we have done this. The ARIA recommendation for the buttons in Gas Properties and BASE would be to change them to a BooleanRectangularStickyToggleButton with a single label where pressed state is conveyed by sticking down and with aria-pressed.

That being said, the "Add Wall"/"Remove Wall" button in BASE has been very usable in screen reader user testing.

arouinfar commented 5 years ago

The ARIA recommendation for the buttons in Gas Properties and BASE would be to change them to a BooleanRectangularStickyToggleButton with a single label where pressed state is conveyed by sticking down and with aria-pressed.

I do not think a BooleanRectangularStickyToggleButton would be an appropriate fit for the role of the "Add Wall"/"Remove Wall" button in BASE or the "Remove Divider"/"Reset" buttons in GasProps, and would result in poorer UX for the majority of users.

That being said, the "Add Wall"/"Remove Wall" button in BASE has been very usable in screen reader user testing.

Given the extensive amount of research that went into the a11y design of BASE, I think we can safely follow the same pattern in Gas Properties.

terracoda commented 5 years ago

Hey folks, the label change in BASE very clearly communicates the changed state. That is why we don't use a traditional web/aria toggle button in this case for accessibility. In addition, we provide a custom alert confirming the changed state.

My belief as to why the current interaction works so well in BASE is three-fold:

  1. Interaction is understood by users.
    • Users know what to do when they hear "button". The visual design also communicates a button, so nice parallel here.
  2. The action-oriented labels make the state of the button interaction very clear. Users can easily guess what will happen if they activate the button when they hear, "Remove wall, button" or "Add wall, button". The visual labels also communicate these states same states with words.
  3. The bonus confirmation alert (a custom aria-live alert) provides confirmation that the interaction was successful, "Wall removed from play area." or "Wall added play area."

Summary: A user pushes the button to remove the wall and also pushes the button to add the wall. The button doesn't have a pressed state, per se, because the button's label is communicating the two different states.

The aria-pressed attribute is a way to make a traditional button communicate natively that it toggles between two states. The AT automatically communicates the interaction differently as a "toggle button". The AT can also communicate the actual pressed state (pressed or not pressed) which is why it generally works best if there is no label change. An additional label change communicating the changed state is redundant and can be confusing.

Here's how the Mute Sound toggle button sounds with VoiceOver in Safari/MacOS with my VoiceOver settings:

  1. "Mute Sound, toggle button", (not state is communicated with my settings) but other AT with other user settings might say,
    • When sim sound is on: "Mute Sound, toggle button, pressed"
    • and when sound is off, "Mute Sound, toggle button, not pressed"
  2. In addition we still provide the custom confirmation alerts:
    • "Sim sound off" and
    • "Sim sound on"

@jessegreenberg, can you confirm if we are actively hiding the pressed state on the Mute Sound button implementation? It might be something that I have turned on in my settings to make things less verbose.

Personally, I'd like to see/understand the differences between the mentioned PhET Button types

and then we can make a reasonable decision about what to do generally with buttons with or without label changes and specifically what is needed for Gas Properties.

The challenge in see in Gas Properties is that the visual labels are quite different and may need to be more similar to communicate the state, like in BASE. I haven't used the sim, but something like this:

I am not sure that would work as I think returning the divider also resets something, so maybe these two labels would be more appropriate:

Then some good help text could clarify the interaction for non-visual learners. I am not 100% sure what the help text should be without being familiar with the sim.

terracoda commented 5 years ago

@arouinfar, could you explain your comment more:

I do not think a BooleanRectangularStickyToggleButton would be an appropriate fit for the role of the "Add Wall"/"Remove Wall" button in BASE or the "Remove Divider"/"Reset" buttons in GasProps, and would result in poorer UX for the majority of users.

I am curious to know if there is something specific about the visual design of the interaction, or if it is something specific about the function of the interaction that makes it inappropriate in the cases of BASE and GasProps.

terracoda commented 5 years ago

And @jessegreenberg, can you confirm if we are actively hiding the pressed state on the Mute Sound button implementation? Or, if it might be something that I have turned on in my settings to make things less verbose.

terracoda commented 5 years ago

I do not want to start a new thread or issue, but I just want to mention for the record that:

when we designed BASE I am not sure if aria-pressed was well supported. @jessegreenberg and I did indeed explore different implementations for the Remove Wall/Add Wall buttons. We may have tried a toggle button with aria-pressed (not sure). But whatever we tried didn't sound or feel right to us or to users.

After the first couple of interviews, I know I adjusted the help text to be more about the sim and less about the interaction. The help text for the Wall button is "Play with or without the wall." which works for both states. I try very hard to design help text to be more about the sim whenever and wherever possible. In my opinion, this approach makes the guidance we provide (in text) more encouraging and less prescriptive in nature, much more akin to and in lign with our visual implicit scaffolding techniques. I try to reserve explicit instructions for custom interactions.

Honestly, for BASE, we had much more of a challenge with the "Two-balloon Experiment" interaction which visually has no word-based label or labels. The help text here is "Play with two balloons or just one." You can see/hear in both cases how the label words, the interaction's function, and the help text words all come together to communicate things to the user.

pixelzoom commented 5 years ago

@terracoda said:

Personally, I'd like to see/understand the differences between the mentioned PhET Button types

RectangularPushButton BooleanRectangularToggleButton BooleanRectangularStickyToggleButton

These are documented at the top of their respective JavaScript files, and demonstrated in the "Buttons" screen of the sun demo application. In a nutshell:

General terminology:

The first 2 are standard UI terms; "sticky" is a PhET term.

For the classes that you asked about:

screenshot_1138 screenshot_1137

screenshot_1140 screenshot_1139

screenshot_1142 screenshot_1141

screenshot_1143 screenshot_1144

As we've discussed previously, it's also useful to be familiar with the class hierarchy, and how the MVC (Model-View Controller) pattern is applied (similar to Java and other standard UI toolkits). For example , BooleanRectangularToggleButton is a subclass (specific to boolean states) of the more general RectangularToggleButton, it's view is a RectangularButtonView, it's model is a ToggleButtonModel.

pixelzoom commented 5 years ago

@terracoda said:

@arouinfar, could you explain your comment more: I do not think a BooleanRectangularStickyToggleButton would be an appropriate fit for the role of the "Add Wall"/"Remove Wall" button in BASE or the "Remove Divider"/"Reset" buttons in GasProps, and would result in poorer UX for the majority of users. I am curious to know if there is something specific about the visual design of the interaction, or if it is something specific about the function of the interaction that makes it inappropriate in the cases of BASE and GasProps.

A sticky toggle button (see description and examples above) has no button label. So I agree that BooleanRectangularStickyToggleButton is inappropriate for both sims. A RectangularToggleButton (boolean or otherwise), on the other hand, is appropriate. It does change its label when state changes, but it sounds like we're not concerned about the ARIA directive to avoid doing that.

EDIT: fixed a typo above.

pixelzoom commented 5 years ago

@arouinfar said:

Given the extensive amount of research that went into the a11y design of BASE, I think we can safely follow the same pattern in Gas Properties.

And @terracoda suggested some different labels for the button states in https://github.com/phetsims/a11y-research/issues/137#issuecomment-482796376.

I'm going to proceed with using a RectangularToggleButton (or perhaps its boolean subclass), with the labels specified in the design document. @arouinfar let me know if you'd like to adjust those labels.

terracoda commented 5 years ago

@pixelzoom, thanks for these examples.

What is the difference between RectangularToggleButton and its subclass BooleanRectangularToggleButton? Is it that one has a single Scenery node and the other has two nodes?

@pixelzoom, I think theBooleanRectangularStickyToggleButton visually maps perfectly to the toggle button defined in https://www.w3.org/TR/wai-aria-practices-1.1/#button . It toggles between 2 states (pressed and not pressed) and there is no label change.

For screen reader access, however, there will need to be a text-based label, e.g.

<button aria-pressed="false">Flash light</button>
<button aria-pressed="true">Flash light</button>

Read out by a screen reader, each state would sound something like:

With our custom alerts, confirmation would sound something like:

I had a look at Gas Properties, the keyboard accessibility is excellent. Awesome work. Keyboard accessibility, however, does not always equal screen reader accessibility.

If the Gas Properties' Remove Divider button is implemented as a "common UI toggle button", i.e., a button element with the aria-pressed attribute , the button might look like this in html:

<button aria-pressed="false">Remove Divider</button>
<button aria-pressed="true">Reset</button>

Read out by a screen reader, each state would sound something like:

With our custom alerts, confirmation might sound something like the following, though I am not sure as visually, there is a lot going on:

I personally think the Remove Divider/Reset button is more like BASE's Remove Wall/Add Wall button. When the sim has accessible labels the interaction will not sound good as a traditional web toggle button with aria-pressed.

@pixelzoom, I finally get it!!! There is a disconnect between the visual button type, BooleanRectangularStickyToggleButton, and what we implemented for accessibility in BASE.

@pixelzoom, I now understand your questions.

(1) What should be done in general? Is PhET following this ARIA practice? (2) What should be done specifically in Gas Properties?

This is what I think:

  1. In general, for screen reader access, I would say a toggle button (button with aria-pressed) is likely best without a label change. PhET indeed, very carefully follows the ARIA Practices and we test our accessible designs with users with disabilities.
  2. I think, once there are accessible labels on these buttons in Gas Properties, the buttons will not need to be toggle buttons. That is to say, the button interactions here in Gas Properties will not benefit users by being communicated as toggle buttons.

This was a great discussion. I learned a lot. I hope there was some mutual learning.

Edited to clarify and re-arrange the sentence starting with "If the Gas Properties' Remove Divider button" and change "might sound like this" to "might look like this in html"

pixelzoom commented 5 years ago

@terracoda said:

What is the difference between RectangularToggleButton and its subclass BooleanRectangularToggleButton? Is it that one has a single Scenery node and the other has two nodes?

RectangularToggleButton can toggle between 2 states of any type. BooleanRectangularToggleButton toggle is a subclass of RectangularToggleButton that is specialized to toggle between boolean states true and false. Both have 2 scenery Nodes to represent the 2 states.

I had a look at Gas Properties, the keyboard accessibility is excellent. Awesome work.

I haven't done anything related to a11y for Gas Properties, any accessibility that's working came "for free" with common code. So awesome work by the a11y team.

Keyboard accessibility, however, does not always equal screen reader accessibility.

Agreed, which is why I brought this up. It seemed like a potential design problem that could require changes later. At some point, a11y considerations need to become part of the general design process.

I think, once there are accessible labels on these buttons in Gas Properties, the buttons will not need to be toggle buttons. That is to say, the button interactions here in Gas Properties will not benefit users by being communicated as toggle buttons.

I think that what you're saying here is that this button will not have ARIA role "toggle button". In general UI (and PhET) terminology, this button will be a toggle button, regardless of whether its label changes, and regardless of whether ARIA identifies it as such. Perhaps part of the communication problem here is that ARIA taxonomy does not (necessarily) map to standard/typical UI taxonomy. So we need to indicate which taxonomy (or taxonomies) we're referring to.

This was a great discussion. I learned a lot. I hope there was some mutual learning.

👍

terracoda commented 5 years ago

@pixelzoom said:

I think that what you're saying here is that this button will not have ARIA role "toggle button". In general UI (and PhET) terminology, this button will be a toggle button, regardless of whether its label changes, and regardless of whether ARIA identifies it as such. Perhaps part of the communication problem here is that ARIA taxonomy does not (necessarily) map to standard/typical UI taxonomy. So we need to indicate which taxonomy (or taxonomies) we're referring to.

Yes, that's what I mean (sort of) ;-) More correctly, for accessibility the button will not benefit screen reader users by being called a "toggle button" upon focus, nor will it benefit screen reader users to indicate its current state with the words like: "pressed" and "not-pressed". Thus, the button will not need aria-pressed.

For clarity and accuracy, if the interaction is a button, it will always have role="button" which is implicit if the button element is implemented in the HTML. The aria-pressed attribute does not not change the role of the element, only how it is communicated to Assistive Technology. The aria-pressed attribute is indeed a "boolean" from a logic perspective. It toggles between:

@pixelzoom, I agree we are using the same word, "toggle", to refer to different things - different types of interactions. Which taxonomy represents a "standard" is irrelevant to the end users of the sims we build. We just need to understand what we are saying to each other :-) so users get a good experience in the end.

Edited for typos.

jessegreenberg commented 5 years ago

can you confirm if we are actively hiding the pressed state on the Mute Sound button implementation?

The NavigationBarSoundToggleButton is using aria-pressed. I just tested in NVDA and on focus it sound like: "Mute Sound toggle button, not pressed"

And when pressed NVDA says "pressed".

terracoda commented 5 years ago

Thanks @jessegreenberg. That's perfect. I know I have heard "not pressed" and "pressed" with VoiceOver, too. I just didn't hear it when I tested the other day. I only heard, "Mute Sound toggle button". Thanks for checking.

terracoda commented 5 years ago

@jessegreenberg, can we close this issue? Or perhaps I should make it into a design-pattern to-do for our eventual binder of PhET A11y design patterns?

jessegreenberg commented 5 years ago

@terracoda I think this issue can be closed now. I am unfamiliar with binder work but feel free to document in the appropriate place if there are notes or TODOs from this that shouldn't be forgotten.

terracoda commented 2 years ago

This is an old issue slated to close, so closing.