phetsims / chipper

Tools for developing and building PhET interactive simulations.
MIT License
11 stars 14 forks source link

Add accessibility content to html templates #472

Closed jessegreenberg closed 8 years ago

jessegreenberg commented 8 years ago

From https://github.com/phetsims/john-travoltage/issues/89 and https://github.com/phetsims/balloons-and-static-electricity/issues/151, we discovered that 'aria-live' elements need to be added before body.onload is fired. Screen readers generally do not add observers to 'aria-live' elements that are added dynamically after onload. This has caused some erratic or missing alert messages when a screen reader is in use.

Would it be possible to add some content to sim-development.html and sim.html templates that could contain elements with for alert messages? We will need to design this content a bit, but it could look like this:

<div id='live-content'>
  <p id='live-assertive' aria-live='assertive'></p>
  <p id='live-polite' aria-live='polite'></p>
  <p id='live-log' role='log'></p>
  <p id='live-status' role='status'></p>
  <p id='live-alert' role='alert'></p>
  <p id='live-progressbar' role='progressbar'></p>
  <p id='live-marquee' role='marquee'></p>
  <p id='live-timer' role='timer'></p>
</div>

When a new message needs to be announced by the screen reader, we can reference the element with the desired role and set its new textContent.

The 'live-content' div may need to be hidden or have aria-hide=true so that content is hidden from the cursor (if screen readers will allow it).

jessegreenberg commented 8 years ago

Tagging @jobara, @jhung, and @terracoda in case they have recommendations for this content.

We will also want to have an element for each of 'aria-atomic' or 'aria-relevant' attributes

  <p id='live-assertive-atomic' aria-live='assertive' aria-atomic='true'></p>
  <p id='live-assertive' aria-live='assertive' aria-atomic='false'></p>
  <p id='live-polite-atomic' aria-live='polite' aria-atomic='true'></p>
  <p id='live-polite' aria-live='polite' aria-atomic='false'></p>

...and so on. It may be difficult to use 'aria-relevant' in this static content if the reference id is generated dynamically by the sim.

jobara commented 8 years ago

@jessegreenberg have you had a chance to test out if the "aria-atomic" and "aria-relevant" be static? I'm hoping that just having the "aria-live" static will be enough for the browsers to track them.

Also I've been thinking about this a bit. I believe for the special case live regions like "status", "alert" and "log" it makes sense to have a single per sim region. I'm not sure this is true for generic "aria-live" regions, in terms of semantics, but don't have a specific use case to think about this concretely. How do you find they are being used in BASE right now? Assuming you have live regions that are triggered by distinct elements/interactions that don't fall under one of the special case live regions, does it make sense to group them all under the same element?

jessegreenberg commented 8 years ago

have you had a chance to test out if the "aria-atomic" and "aria-relevant" be static?

No, not yet. They haven't been needed yet in balloons-and-static-electricity, but we should test them out. I misunderstood the aria-relevent role, it takes a string value like 'additions', not an element id, so it should be fine in the static content.

In BASE it does make sense to group them all together, but I haven't thought about how they might be separated. The one downside to this structure is that it is difficult for a user to find with cursor keys since these elements are separate from the main content. They don't have any context outside of when the alert is triggered. But maybe they should be hidden? Is it important for a user to be able to find aria-live text after the new content has been announced by the reader?

jobara commented 8 years ago

The one downside to this structure is that it is difficult for a user to find with cursor keys since these elements are separate from the main content. They don't have any context outside of when the alert is triggered. But maybe they should be hidden? Is it important for a user to be able to find aria-live text after the new content has been announced by the reader?

I think it depends on both the type of live-region and the context for its use. If it's a general alert, they probably don't have to find it and it can be hidden on it's own at some point, although probably nothing wrong with it being discoverable. This is what we are currently doing in John Travoltage. However, for something like the status, that should probably be discoverable and consistent. Other cases like the form validation case for alerts that @jhung mentioned should probably also be discoverable.

jessegreenberg commented 8 years ago

Yes, that makes sense. My concern for finding alert content is if they discover content with the cursor that is stale and no longer representative of what is happening in the simulation. Presumably that wouldn't happen if text content is linked properly to the model.

For the status and validation alerts that need to be discoverable, maybe they should be separate with some additional information that lets the user know 'Come here to find text content from alerts'. Or maybe we just need a different structure for these alerts.

jessegreenberg commented 8 years ago

I wonder if it is possible to move the alerts around once they have been added to the top of the document? I am not sure if screen readers would agree with this, but if we did something like

This way aria-live elements can be discoverable and have context if necessary.

jobara commented 8 years ago

Hmm.. that's interesting. It'd be worth trying out. We should also talk over the use cases for the live-regions. It could be that a single consistent alert, log, and status region may be enough.

jessegreenberg commented 8 years ago

It could be that a single consistent alert, log, and status region may be enough.

Very true, if sufficient, keeping a single and consistent region for these alerts would be much more simple.

jessegreenberg commented 8 years ago

We need to do some testing to determine how much needs to be in the template. For instance can we dynamically set aria-relevant and aria-atomic attributes?

terracoda commented 8 years ago

@jessegreenberg, @jobara, I'm not sure I am thinking about the design of the descriptions in a way that fits perfectly with the ARIA specification. My thinking of how the descriptions work in the design is more simple. Currently, my model contains 3 main categories:

  1. Static Descriptions
  2. Dynamic Descriptions
  3. Interaction Descriptions (or Interaction Alerts)

Static Descriptions are pretty straight forward as their content does not change. Dynamic Descriptions describe the changing science content (level of charge, position, effect on other sim objects). I see both these as discoverable during interaction and while reading with the cursor keys.

In the design of BASE, the Interaction descriptions, only make sense at the time of interaction, so I do not see these descriptions as discoverable content. For example, a student has grabbed the balloon, they hear that they have the yellow balloon and that it is on the upper right side of the play area and that it has a neutral charge. They also hear a navigation cue about the WASD keys, so they press A (they want to go to the sweater). They hear the screen reader key press and an interaction alert: "A, Left towards sweater." If they were to tab away from the balloon at this point and use the cursor keys to read a description of the balloon, they would not find "left towards sweater" anywhere. They would first hear a release description which would contain elements of the balloon's description, then if they navigated with the cursor keys to find the balloon they would find/hear something along the lines of, "Yellow balloon, upper center of play area, neutral charge, no more negative charges than positive ones."

A simpler example is the operation of the switch to add or remove the second balloon. When the green balloon is added, the user immediately hears, "Green balloon added to Play Area." If they Tab to find the balloon, they will find the grab green balloon button, but if they use the cursor keys to find it they should find the green balloon (Label, position, level of charge and perhaps a hint to look for the grab button). By reading through the PDOM, the user would never find the Interaction Alert, "Green Balloon added to Play Area."

I see the "Green balloon added" or "Wall removed" as straight forward non-discoverable interaction alerts. However, the description of the action of dragging the balloon through the Play Area is more complex. Also, successive rubs on the Sweater must convey a lot of information with fewer and fewer words. I don't see these interaction descriptions as "discoverable". I am understanding "discoverable" to mean findable with any navigation mechanism available to the user.

jessegreenberg commented 8 years ago

@terracoda that categorization makes sense, and it should be possible.

The above commit is a test suite so that we can determine if screen readers modify behavior for aria-live observers when attributes such as 'atomic' or 'relevant' are changed dynamically.

terracoda commented 8 years ago

@jessegreenberg, thanks for the clarification.

jessegreenberg commented 8 years ago

I tested the above in Windows 10 with NVDA and JAWS, each with latest Google, Firefox and IE. Here was my test for changing aria-atomic dynamically:

Results -

This surprised me, so I also tested adding aria-atomic=false to the aria-live element statically (before the onload event is fired). For everything except NVDA + Chrome, the aria-live element behaved as if aria-atomic=true! This leads me to believe that aria-atomic=false is widely unsupported.

EDIT: Test can be found here: https://github.com/phetsims/scenery/blob/master/accessibility/tests/aria-live/aria-live-test.html

jessegreenberg commented 8 years ago

I did a similar test with aria-relevant:

Results - For every platform, changing aria-relevant had no impact on screen reader output, even when the attribute was set statically before document's onload event. The only interesting thing I found was that nothing is announced in Chrome + NVDA when text content is removed, regardless of the aria-relevant status.

Support might be better for VoiceOver, but based on these results it seems that we should avoid anything other than aria-atomic=true and aria-relevant="additions text" (the default) until support is improved.

jessegreenberg commented 8 years ago

During testing, I also noticed that role=alert was the only alert that seemed to have unique behavior from aria-live. Before speaking the text content, the screen reader will say 'alert'. The other roles didn't seem to have any unique behavior.

Also, JAWS + Chrome was the only platform where aria-live=polite was broken (polite alerts read but not queued).

jessegreenberg commented 8 years ago

The following could be added to the top level HTML file:

<div id='aria-live-elements'> <!-- styling would make all of this 'invisible'.  hidden and aria-hidden prevent aria-live utterances. -->
  <p id="assertive" aria-live="assertive" aria-atomic="true"></p>
  <p id="polite" aria-live="polite" aria-atomic="true"></p>
  <p id="assertive-alert" aria-live="assertive" role="alert" aria-atomic="true"></p>
  <p id="polite-status" aria-live="polite" role="status" aria-atomic="true"></p>
</div>

This would allow us to

jobara commented 8 years ago

@jessegreenberg, the role="alert" has an implicit aria-live="assertive" and aria-atomic=true so the explicit declarations shouldn't be needed, although it shouldn't hurt either. Have you found that it is needed?

http://www.w3.org/TR/wai-aria/roles#alert

Also, I think there is a typo in the last element. Did you mean?

<p id="polite-status" aria-live="polite" role="status" aria-atomic="true"></p>
jobara commented 8 years ago

@jessegreenberg, I wonder if having the 4 aria-live regions in each page would be confusing for users when the sim doesn't use all of them. Have you noticed anything in your testing that might indicate that they are announced in any way when they are not used?

jessegreenberg commented 8 years ago

...the explicit declarations shouldn't be needed, although it shouldn't hurt either. Have you found that it is needed?

Agreed, but I just included them because I read here that adding them could maximize compatibility.

Also, I think there is a typo in the last element. Did you mean?

Yes, thanks! I edited the comment.

Have you noticed anything in your testing that might indicate that they are announced in any way when they are not used?

We haven't done any testing with all four aria-live regions, but I hope that it would be similar to having two regions, which is what BASE and john-travoltage use now. They should go unnoticed since the paragraphs are invisible until filled with text content. The text content can be found with the virtual cursor after the user has played with the simulation, but I don't think we have seen that as confusing for users in any tests.

jessegreenberg commented 8 years ago

In developer meeting 8/18/16 we decided that it should be fine to proceed with adding the content in https://github.com/phetsims/chipper/issues/472#issuecomment-239031147.

To do this, we should

In addition (and probably first) we should verify some behavior

jessegreenberg commented 8 years ago

Verify that an empty alert box isn't announced in some way on page load

I just tested this on

The only platform that had this issue was Chrome + NVDA.

john-travoltage uses aria-hidden on the alert until the content needs to be announced. Perhaps we can do something similar here.

jessegreenberg commented 8 years ago

In balloons-and-static-electricity, I have been trying a new type that handles sending new content to the aria-live elements. This type could easily handle hiding/unhiding of the content to fix the issue mentioned in https://github.com/phetsims/chipper/issues/472#issuecomment-241538758.

jessegreenberg commented 8 years ago

generate development html files

I will do this tonight during quieter hours to avoid conflicts with team commits.

jessegreenberg commented 8 years ago

Accessibility content has been added to all simulations via the grunt task. Closing.