phetsims / scenery

Scenery is an HTML5 scene graph.
MIT License
54 stars 12 forks source link

Create an HTML accessibility prototype #450

Closed samreid closed 8 years ago

samreid commented 9 years ago

At today's meeting, we discussed creating an HTML accessibility prototype. @jessegreenberg & @samreid began work on one and committed it in 0019695119cb1b3aec36d2bcf438652020dff535 . The latest version is in https://github.com/phetsims/scenery/blob/master/accessibility/forces-and-motion-basics-accessibility.html

The goal is to create the DOM in the way that we would want scenery to create it. As described in the README.md:

Experimental HTML for prototyping/testing/understanding how to produce highly accessible HTML which scenery can use as a model for accessibility support.

We are focusing on the first screen of Forces and Motion: Basics since that simulation has received the highest focus on design work for accessibility.

I recommend to follow best practices as described in http://www.amazon.com/Pro-HTML5-Accessibility-Joshue-Connor/dp/1430241942 (which I have not read, but which received good reviews) and to test with a variety of screen readers during testing and development. Once progress has been made on this issue, it should be discussed with @samreid and @jonathanolson regarding how scenery can automatically create a similar DOM structure.

Some issues we should explore in particular:

@jonathanolson please weigh in with other specific questions you want to investigate here.

Note that previous work used (a) our own accessibility support in 1.1.5-dev.4 and (b) aria on SVG in 1.1.5-dev.9. We are now investigating how to do this with native HTML DOM elements as much as possible. Ideally when this is done it will be ugly, but demonstrate keyboard navigability and screen reader access on several platforms (OS + browser + screen reader). The idea is that we will use scenery SVG or WebGL to render it, but we just need to make sure the accessibility DOM is working properly.

I also recommend to familiarize yourself with the open scenery accessibility issues https://github.com/phetsims/scenery/issues?q=is%3Aopen+is%3Aissue+label%3Aaccessibility and the previous work done for Forces and Motion: Basics in https://github.com/phetsims/forces-and-motion-basics/issues/110 (includes a possibly out-of-date design PDF) and the existing published prototypes at http://phet.colorado.edu/en/about/accessibility

samreid commented 9 years ago

An additional question:

samreid commented 9 years ago

Elaborating on the above questions, I am not sure whether focus should automatically move to newly created components, or whether focus cycles should be restricted (say, in the case of the PhET popup menu). Automatically changing focus may be confusing for some users and restricting focus to a subset of components may also be confusing (unless there is a straightforward way out). @emily-phet should weigh in here.

jonathanolson commented 9 years ago

How to handle tab indices?

Seems best to have it be DOM-order, and reorder DOM elements if necessary?

How to handle checkbox labels

I recall the label element with for= being the candidate for this?

I'm not sure about the exact questions that should be asked and explored, hopefully that's part of the process of investigating?

samreid commented 9 years ago

Seems best to have it be DOM-order, and reorder DOM elements if necessary?

I agree this sounds good to investigate, and we should look into the related question of what happens when a focused item is moved elsewhere in the DOM. Does it keep focus? Does the focus rectangle move properly? Does the supplemental focus rectangle (say, in VoiceOver) update properly? Etc.

samreid commented 9 years ago

Likewise, do any screen readers get confused (or do confusing things) if the DOM is reordered?

emily-phet commented 9 years ago

@samreid - let's talk more about this later today, but in the meantime I found this resources regarding popup behavior. Might be useful. http://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-no-extreme-changes-context.html

jessegreenberg commented 9 years ago

Above is my initial commit for the HTML accessibility prototype. This is a status commit, there is more to be done, but initial investigations suggest the following:

How to handle tab indices?

As suggested, prototype is DOM-order, except for nested elements.

How to handle dynamically created components such as the popup PhET menu or the About dialog?

How to handle nested components (i.e. restricting focus to menu items when the PhET menu has popped up)

All elements are indexed by DOM order, except for nested elements which have tabindex="-1". Some javascript is then used to set the focus to nested elements by changing their tab index on "Enter".

I treated the phet menu pop up as a nested element, and behavior is much like the SVG prototype: http://www.colorado.edu/physics/phet/dev/html/forces-and-motion-basics/1.1.5-dev.4/forces-and-motion-basics_en.html?screens=1

How to handle disabled elements, such as the "Go" button when the simulation starts up.

I have not done this yet, but I imagine that this dynamic behavior could also be handled with some javascript.

What should "sprites" such as the pullers be represented as?

In prototype, I am using a <div>, though this may be limiting. Will continue to investigate.

Some new questions:

Seems best to have it be DOM-order, and reorder DOM elements if necessary?

Why is this the recommended solution? Reordering the DOM seems much more complicated than handling indices. Is reordering the DOM a better approach for generalizing in scenery?

Should toggle buttons become checkboxes in the DOM? Might be more explicit for boolean properties like "Mute".

"Enter" is retrieved by key code. This is neither portable nor accessible. What is the best way to get an "Enter" event?

samreid commented 9 years ago

@emily-phet sent this link that a collaborator at IDRC had worked on for an accessible Balloons and Static Electricity: http://terracoda.net/experimental-play/kb-access-01.html

jessegreenberg commented 9 years ago

In the commit above, I added some documentation to the prototype html, and some scripting so that tab navigation is done with event listeners. Some aria descriptions have also been added to provide overview descriptions of the sim state.

W3.org has some great information about complex keyboard navigation: http://www.w3.org/TR/2009/WD-wai-aria-practices-20090224/#keyboard

This basically lists off two proper methods of tab navigation. The first uses global tab indices and element.focus() with scripting to navigate. The other uses aria-activedescendant with grid and tree structures to manage children from root nodes.

The aria-activedescendant method looks very promising. It should reduce the amount of JavaScript needed and make the client responsible for keeping track of active elements with aria-activedescendant.

I will investigate this method by creating a new prototype. We can then compare the two different methods of keyboard navigation to see which is the most simple, behaves the best, and could be easily integrated into scenery.

emily-phet commented 9 years ago

Taliesin just introduced me to this neat tool - it highlights and colorcodes the use of ARIA http://whatsock.com/training/matrices/visual-aria.htm . This might be useful to you.

jessegreenberg commented 8 years ago

Commit 36724b3f53f82bf5c1161d334ae235b5b9959367 is the beginning of a new prototype for accessible content. Elements of this prototype are general, but specific to FAMB.

After testing with various devices, we are quickly finding that behavior of accessible content is highly platform specific. Depending on the browser, this can include quirky or even broken behavior.

It seems helpful to revisit the prototype and test on various platforms to determine how to get accessibility behavior more predictable for PhET's supported devices in combination with AT.

We have learned a lot about accessible HTML and ARIA since the initial prototypes a few months ago. The new prototypes should reflect this, and will hopefully exhibit more predictable behavior.

jessegreenberg commented 8 years ago

In the commit above, I added scripting and a live region to the accessibility prototype. In forms mode, NVDA behaves well with Windows 7 and Chrome. Will need to verify with other known platforms that have been exhibiting issues.

terracoda commented 8 years ago

Hi Jesse, Sam, Jonathan and others, I've created what I think might be a solid starting point of an HTML parallel-DOM structure for Balloons and Static Electricity.

I've focused on semantic HTML, I've used the landmarks: header, main, footer and nav. Section elements with headings are used as containers for the Play Area and the Control Panel. I've associated the labels and descriptions with some elements using aria-labelledby and aria-describedby.

The ARIA and the HTML code is all valid. There seems to be an issue with the radio buttons when checking the code with the Visual ARIA Boomarklet tool.

There are lots of comments in the code explaining my thought process and things I have yet to work out. Please let me know if the code and comments are helpful.

You can find the demo here: http://terracoda.ca/experimental-play/balloons-pdom.html

The code is in my "experimental-play" repo over at Terracoda on github. File is called balloons-pdom.html I'm not sure how to share it with you folks. Any tips? Taliesin

terracoda commented 8 years ago

Hi again, BTW, this new PDOM for Balloons and Static Electricity is an iteration on my first go around that Sam posted above back on August 13th. In this new iteration I have a much better understanding of the aria attributes I have employed. FYI, I've used duplicate ARIA and HTML semantics. This is a judgement call. Duplicate semantics can be removed. Taliesin

samreid commented 8 years ago

The code is in my "experimental-play" repo over at Terracoda on github. File is called balloons-pdom.html I'm not sure how to share it with you folks. Any tips?

Since the github repo is public, we should be able to use that to access the file and its history: https://github.com/terracoda/experimental-play/blob/master/balloons-pdom.html

I tested the link http://terracoda.ca/experimental-play/balloons-pdom.html with VoiceOver in Safari and Chrome and had some questions. The text says:

Select any Arrow key to grab the balloon and start dragging. Select Tab for next item. Select K or question mark for keyboard help.

Is this support provided yet? I tried the arrows, K and ? and wasn't sure if they were working.

terracoda commented 8 years ago

@samreid, The P-Dom I created is just a snapshot of the very basic sim on page load. The interactions are not part of the P-DOM prototype. The actual Keyboard Help menu is not implemented yet. @jessegreenberg has begun some implementation on Balloons and Static Electricity, but I am not sure where it is at. In our first iteration, I created a "Balloon Interactions" Menu. I think @jessegreenberg started with that concept, but then we decided it made more sense to have a general Keyboard Help menu.

Does that clarify?

Also, just to clarify, my approach to sim descriptions is to include both descriptions of the visuals and descriptions of the interactions. Taliesin

terracoda commented 8 years ago

@samreid @jessegreenberg I see that I did not follow your naming conventions. Sorry about that. I'll be more careful on the next iteration.

samreid commented 8 years ago

Thanks for the explanation @terracoda!

jessegreenberg commented 8 years ago

@terracoda, thanks for posting your prototype accessibility DOM! I will review the landmarks and html elements you chose to represent the application interface. I am less familiar with landmark roles so this will be very helpful.

jessegreenberg commented 8 years ago

In https://github.com/phetsims/scenery/blob/master/accessibility/DOMPrototype.html, I have been using a new method of navigation control that uses the hidden attribute instead of tabindex.

This has been useful for two reasons: 1) This restricts what the AT has access to. Elements with tabindex=-1 can still be navigated to with screen reader controls without the tab key, so the user could find something that should otherwise be hidden.

2) It is easier to implement in sim code. Rather than worrying about toggling the tab index for every element in the DOM, entire groups can be hidden by setting the hidden attribute on parent elements.

jessegreenberg commented 8 years ago

In https://github.com/phetsims/scenery/commit/29c4c62d34fc1b29b9e6c5c7af6f5fc8fa4a3ea2#commitcomment-14671448,

@terracoda said:

I think it might be a good idea to separate static content from dynamic content. You can use a span to wrap the the piece of content that changes and keep the description in a paragraph. For example:

A rope is attached to the right side of the cart. The rope has 4 knots spaced equally along the rope. A group of four puller people are standing near this rope.

The rope is always there and the knots are always on the rope; however, the number of pullers near the rope and on the rope is not static. Could the last piece of the description be brought in dynamically?

Yes, this last piece alone could be brought in dynamically. This is a good idea as it would reduce the length of our descriptions in translatable string files. Does the span element serve a purpose for AT? The JavaScript code would reduce in complexity if we could use standard string concatenation.

I think that we will also need aria-atomic=true so that the text change makes sense in the context of the whole description.

samreid commented 8 years ago

The JavaScript code would reduce in complexity if we could use standard string concatenation.

I didn't know exactly what you meant by string concatenation, but it seemed like the way to internationalize and make the last sentence dynamic is with:

englishText = 'A group of {0} puller people are standing near this rope.'

and then to use StringUtils.format to internationalize.

terracoda commented 8 years ago

@samreid @jessegreenberg The span element has no purpose for AT. Span and div lack any semantics. I'm a front-end developer, so wrapper something in an element is one way of targeting it for JS or CSS. I like the concatenation idea way better, and yes, of course, only the number in the sentence needs to change.

terracoda commented 8 years ago

@samreid @jessegreenberg I tested the plain HTML Balloons-PDOM with JAWS on FF and IE. JAWS reads out the aria descriptions and labels a bit differently depending on the browser (of course - argh). After listening, I am not sure we need to use the aria-labelledby so extensively. It causes a lot of repetition. If the headings themselves are accessible, I think the description associations are enough. If the headings are not accessible content, the use of aria-labelledby then become more important. Does that make sense? @jessegreenberg we can discuss at today's PhET meeting or before implementation.

For example, entering and leaving a landmark is announced by AT. When the landmark is associated with a label, the label is also read out upon entering and leaving the landmark.

Thus, upon exiting the banner, JAWS says: "The Scene for Balloons and Static Electricity Banner End". Without the label, it would just say: "Banner End".

The label was already announced upon entering the banner. If the heading is an accessible piece of content in the page, the user may hear the same content again there, resulting in at least three utterances of "The Scene for Balloons and Static Electricity". This might be overkill :-)

terracoda commented 8 years ago

@jessegreenberg The PDOM for Forces and Motion Basics is looking nice. http://doccenter.freedomscientific.com/doccenter/archives/training/jawskeystrokes.html

For buttons that do not show words or do not have text that is readable by a screen reader, you use the aria-label attribute to create an accessible label. This will be read out by AT every time. Labels are essential information. Descriptions are considered secondary extra information that seems to not be read out every time a control is accessed. You use the aria-label when there is no other content in the page that can be associated as a label via aria-labelledby. Both techniques create an "accessible label."

<!-- GO button with auditory description --> <input tabindex="0" type='button' value='Go' aria-disabled='true' aria-label="Go." aria-describedby='goButtonDescription'> <p id='goButtonDescription'>Select to start pullers</p> <!-- PAUSE button with auditory description --> <input tabindex="0" type='button' value='Pause' aria-disabled='true' aria-label="Pause." aria-describedby='pauseButtonDescription'> <p id='pauseButtonDescription'>Select to pause pullers</p>

Next go around, I'll try to make my out commit :-)

terracoda commented 8 years ago

Oops the code was too real and disappeared! Fixed it.

jessegreenberg commented 8 years ago

...englishText = 'A group of {0} puller people are standing near this rope.' and then to use StringUtils.format to internationalize.

@samreid, thanks for the reminder. Yes, that is the way to go for simplicity and i18n.

jessegreenberg commented 8 years ago
<!-- GO button with auditory description -->
<input tabindex="0" type='button' value='Go' aria-disabled='true' aria-describedby='goButtonDescription'>
<p id='goButtonDescription'>Select to start pullers</p>

In the 12/1/15 accessibility meeting, it was pointed out that description paragraphs like the one above could be navigated to with AT, without navigating to the button. This allows description paragraphs to be read out of context, so the description should be written with care.

It was suggested that use of good labels could make descriptions unnecessary.

As suggested above by @terracoda, the aria-label is likely the way to go for the buttons in the example above.

jessegreenberg commented 8 years ago

From phetsims/balloons-and-static-electricity#103, the following is a formatted copy of the accessible DOM generated for balloons-and-static-electricity.

<div class="accessibility" style="position: absolute; left: 0px; top: 0px; width: 0px; height: 0px; clip: rect(0px 0px 0px 0px);">
    <div class="ScreenView">
        <header role="banner" aria-labelledby="scene-label-14-35" aria-describedby="scene-descripion-14-35">
            <h1 id="scene-label-14-35">‪The scene for Balloons and Static Electricity‬</h1>
            <div id="scene-descripion-14-35">
                <p>‪A balloon floats evenly between a large woolly sweater and a removable wall. The sweater is to the left and the wall is to the right.  Each object shows negative and positive charges. Charges are shown in pairs. Currently, the sweater and the wall have many pairs of charges, the balloon, just a few. The control panel has controls to add a second balloon, adjust charge views and to reset the entire experiment. Select Tab for next item. Select K or question mark for keyboard help. Select H for a heading outline.‬</p>
            </div>
        </header>
        <div class="ScreenViewContainer" role="main">
            <section id="play-area-14-35-37" aria-labelledby="heading-node-36">
                <h2 id="heading-node-14-35-37-36">‪Play Area‬</h2>
                <div id="sweater-14-35-37-38" aria-labelledby="sweater-label-14-35-37-38" aria-describedby="sweater-description-14-35-37-38">
                    <h3 id="sweater-label-14-35-37-38">‪Sweater‬</h3>
                    <p id="sweater-description-14-35-37-38">‪The sweater has a neutral charge, no more positive charges than negative ones.‬</p>
                </div>
                <div id="wall-14-35-37-156" aria-labelledby="[object HTMLHeadingElement]">
                    <h3 id="wall-label-14-35-37-156">‪Wall‬</h3>
                    <p id="wall-description-14-35-37-156">‪The wall has a neutral charge, no more positive charges than negative ones.‬</p>
                </div>
                <button role="slider" title="Balloon" id="balloon-14-35-37-270-342" draggable="true" class="Balloon" aria-labelledby="balloon-label-14-35-37-270-342" aria-describedby="balloon-description-14-35-37-270-342">
                    <h3 id="balloon-label-14-35-37-270-342">‪Balloon one‬</h3>
                    <div id="balloon-description-14-35-37-270-342">
                        <p>‪The balloon has a neutral charge, no more negative charges than positive ones. Currently, positioned at equal distance between sweater and wall. The sweater is to the left and the wall is to the right. The top of the balloon is level with the chest area of the sweater. Select any Arrow key to grab the balloon and start dragging. Select Tab for next item. Select K or question mark for keyboard help.‬</p>
                    </div>
                </button>
                <button role="slider" title="Balloon" id="balloon-14-35-37-270-271" draggable="true" class="Balloon" hidden aria-labelledby="balloon-label-14-35-37-270-271" aria-describedby="balloon-description-14-35-37-270-271">
                    <h3 id="balloon-label-14-35-37-270-271">‪Balloon two‬</h3>
                    <div id="balloon-description-14-35-37-270-271">
                        <p>‪The balloon has a neutral charge, no more negative charges than positive ones. Currently, positioned at equal distance between sweater and wall. The sweater is to the left and the wall is to the right. The top of the balloon is level with the chest area of the sweater. Select any Arrow key to grab the balloon and start dragging. Select Tab for next item. Select K or question mark for keyboard help.‬</p>\
                    </div>
                </button>
            </section>
            <section id="control-panel-14-35-413" aria-labelledby="heading-node-414">
                <h2 id="heading-node-14-35-413-414">‪Control Panel‬</h2>
                <input type="button" value="‪Remove Wall‬" aria-describedby="reset-all-description-14-35-413-485-427"></input>
                <fieldset id="radio-button-group-14-35-413-488-480-470" role="radiogroup" aria-describedby="radio-group-description-14-35-413-488-480-470">
                    <legend id="legend-14-35-413-488-480-470-490">‪Balloon Controls‬</legend>
                    <input id="radio-button-14-35-413-488-480-470-464" type="radio" role="radio" name="16" aria-label="‪Remove green balloon‬" aria-checked="true">
                    <input id="radio-button-14-35-413-488-480-470-467" type="radio" role="radio" name="16" aria-label="‪Add green balloon‬" aria-checked="false">
                    <p id="radio-group-description-14-35-413-488-480-470">‪Toggle to conduct experiments with two balloons or just one.‬</p>
                </fieldset>]
                <input type="button" value="‪Reset Balloons‬" aria-describedby="reset-all-description-14-35-413-488-480-477"></input>
                <fieldset id="radio-button-group-14-35-413-488-486-457" role="radiogroup" aria-describedby="radio-group-description-14-35-413-488-486-457">
                    <legend id="legend-14-35-413-488-486-457-489">‪Charge Settings‬</legend>
                    <input id="radio-button-14-35-413-488-486-457-439" type="radio" role="radio" name="11" aria-label="‪Show all charges‬" aria-checked="true">
                    <input id="radio-button-14-35-413-488-486-457-447" type="radio" role="radio" name="11" aria-label="‪Show no charges‬" aria-checked="false">
                    <input id="radio-button-14-35-413-488-486-457-455" type="radio" role="radio" name="11" aria-label="‪Show charge differences‬" aria-checked="false">
                    <p id="radio-group-description-14-35-413-488-486-457">‪Select how you want to see or hear the charges.‬</p>
                </fieldset>
                <input type="reset" value="‪Reset All‬" aria-describedby="reset-all-description"></input>
            </section>
        </div>
    </div>
</div>
terracoda commented 8 years ago

@jessegreenberg, How's this for a draft version of Keyboard Help. Use H1 and H2's if you put it in a modal dialog. Use H2's and H3's if you put it directly in the p-dom content hierarchy and wrap it in a section.

<h1>Keyboard Help</h1>
<h2>Balloon Interactions</h2>
<ul>
    <li>Arrow Keys: Grabs &amp; moves balloon in any direction.</li>
    <li>Spacebar or Control plus Enter: Releases balloon.</li>
    <li>Shift plus Arrow Key: Grabs &amp; Moves balloon with bigger steps.</li> 
</ul>
<h2>Quick Move Hotkey Combinations</h2>
<ul>
    <li>J plus S: Jumps to edge of Sweater.</li> 
    <li>J plus W: Jumps to Wall.</li>
    <li>J plus N: Jumps to Near Wall.</li>
    <li>J plus M: Jumps to Middle of Play Area.</li>  
</ul>
<h2>Sim Navigation &amp; Help</h2>  
<ul>
    <li>Tab key: Goes to next focusable item.</li>
    <li>Question Mark: Opens keyboard help.</li>
</ul>
jessegreenberg commented 8 years ago

This looks good @terracoda! I will add something like this to the accessibility tree for balloons-and-static-electricity.

terracoda commented 8 years ago

@jessegreenberg Ok, great. Thanks.

terracoda commented 8 years ago

@jessegreenberg You do need a close button, that is true. Would this work for the dialog?

<div role="dialog" aria-labelledby="dialog1Title"  aria-describedby="dialog1Desc">
<h1 id="dialog1Title">Keyboard Help</h1>
    <section id="dialog1Desc">
        <h2>Balloon Interactions </h2>
        <ul>
            <li>Arrow Keys: Grabs &amp; moves balloon in any direction.</li>
            <li>Spacebar or Control plus Enter: Releases balloon.</li>
            <li>Shift plus Arrow Key: Grabs &amp; Moves balloon with bigger steps.</li> 
        </ul>
        <h2>Quick Move Hotkey Combinations</h2>
        <ul>
            <li>J plus S: Jumps to edge of Sweater.</li> 
            <li>J plus W: Jumps to Wall.</li>
            <li>J plus N: Jumps to Near Wall.</li>
            <li>J plus M: Jumps to Middle of Play Area.</li>  
        </ul>
        <h2>Sim Navigation &amp; Help</h2>  
        <ul>
            <li>Tab key: Goes to next focusable item.</li>
            <li>Question Mark: Opens keyboard help.</li>
        </ul>
    </section>
  <button>Close</button> 
</div> ```
jessegreenberg commented 8 years ago

@terracoda, exactly! That's just what I had in mind. In phetsims/balloons-and-static-electricity#105 I documented some possibilities to contain the content with an aria-description above a close button (https://github.com/phetsims/balloons-and-static-electricity/issues/105#issuecomment-165296677).

I am assuming that the stylized header has something like 'aria-describedby="dialog1Desc"' as an attribute.

terracoda commented 8 years ago

@jessegreenberg, the h1 has the id="dialog1Title" attribute. The dialog must have a label. The div dialog has the aria-labelledby="dialog1Title". There is a section element that wraps everything from the first h2 to the last closing list and then the button is outside the section wrapper.

jessegreenberg commented 8 years ago

I see, that makes sense. Labelled by the 'h1' and described by everything under the section.

terracoda commented 8 years ago

@jessegreenberg, actually labelledby and describedby go on the div with the role dialog and the id's go on the actual elements h1 and section. The h1 is the label and the section is the description.

terracoda commented 8 years ago

@jessegreenberg, yes I think you got it, sorry I'm tired :-)

jessegreenberg commented 8 years ago

The Parallel DOM currently does not behave well with JAWS and VoiceOver. Comments from @terracoda:

Just had a quick peak with Jaws on Windows. The sim is not working as expected when Jaws is enabled - it is super sluggish. Keyboard interactions work fine without Jaws on.

There are issues with the arrows keys as well.

The radio buttons do not work as they do natively with arrow keys. I have to do some weird combo of tab key and space bar to activate the charge radios.

Arrow through PDOM is not working either - getting lots of numbers.

Was able to open keyboard dialog and arrow down into the content.

I am observing very similar behavior in VoiceOver.

jessegreenberg commented 8 years ago

This issue is getting a bit long, I am going to distribute some comments to a new issue involving parallel DOM behavior outside of the prototype.

jessegreenberg commented 8 years ago

I think this issue can now be closed. The parallel DOM has proven to be a valuable method of adding accessible content to PhET simulations. To summarize the benefits:

  1. We can tap into the HTML accessibility community, using the WAI-ARIA standard for markup
  2. aria for SVG is years behind the HTML aria spec in browser and AT support
  3. The parallel DOM dramatically reduces accessibility work, since we can focus all efforts on accessible HTML. If we were to use something like SVG accessibility, we would have to implement solutions for both SVG and canvas.
  4. Keyboard navigation support comes from native HTML

Screen readers and browsers do behave with drastic variance, and do not support all attributes of the aria standard. But the community is moving forward quickly.

For a recent example of the Parallel DOM, see https://github.com/phetsims/balloons-and-static-electricity/issues/103#issuecomment-164102608