-
Notifications
You must be signed in to change notification settings - Fork 6
Support an independent tree structure for a11y from the scene graph #365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I Iike this idea.
I am not too worried about this, it is not a problem that we have run into so far. Also, it is an unlikely case because descendants of ScreenView children that are in one of these sections should have ancestors that exist in the same section. |
Removing my assignment, but adding a11y meeting label to talk about more. |
I don't know if this made it into yesterday's discussion, but I'm leaning toward @jessegreenberg 's assessment. It also seems like this might ease in explaining descriptions to other devs. One thought, and this is mostly a style sort of thing, but would it be preferable to add nodes to the different sections through an option? Something like: var aNode = new Node( [args], { summaryParent: 'playArea' } );
this.addChild( aNode ); I really don't know why this would be useful, but perhaps it'd be useful if a given node's child needed to be added to a different section than its parent. For simplicity's/consistency's sake, I'm totally ok with keeping the |
Discussed in a11y dev meeting today, we like the idea of adding three accessible section nodes the this.sceneSummaryNode = new Node();
this.playAreaNode = new Node();
this.controlPanelNode = new Node(); We could alternatively call them As we are converting sims to accessibility, we have been manually creating these three nodes, and reorganizing the ScreenView's children into one of these three nodes anyways, so it would be generally easier to factor them out to the parent type. Since this would change code in joist that touches many simulations, marking for dev meeting. |
In some sims, I've needed to have some play area objects go behind the control panel and some go in front of the control panel. How would we categorize "floating" buttons? The ResetAllButton is typically not in a Panel instance. |
The "control panel" is loosely defined, and is implemented in what makes the most pedagogical sense. For example, in Ohm's Law, none of the sliders are in the control panel, but rather in the play area, since that is all of the "playing" for the sim. Only the sound and reset buttons are in the control panel. |
I'm mainly concerned about @samreid's thoughts. We need to use node ordering to control visual stacking, but the described separation is incompatible. I've also run into the layering case a lot. I'm curious to learn more about how this would help for a11y, as we probably can't support this as a general pattern. Area Model: Introduction's a11y support didn't require this, and the tab order switches back-and-forth between play area and control panel content anyways. |
Would it be possible to add metadata to Node that indicates what "family" or "a11y parent" it should be associated with? Then scenery a11y can take care of the implementation details? |
I'm not too versed in a11y requirements for a sim with 3 sections. |
We talked about this at dev meeting. Ideally, we need to come up with a solution for the layering problem where we structure the scene graph one way for visual layering, but need a separate structure for the accessible HTML. @jessegreenberg @jonathanolson @zepumph and @mbarlow12 (if available, he is out of town) to brainstorm so possibilities for this issue. |
On another note, I should find a better "note sharing" solution that includes a touch device with a stylus. |
API proposal:
For example, if we have the Node tree:
where parentheses indicate it the node has accessible content (i.e. will get an AccessibleInstance) This would generate the following AccessibleInstance tree:
however, if an
We would presumably have nodes for the accessible sections. Depending on the simulation, we would either place the actual content in those nodes, or place the content elsewhere (and point into the content with accessible orders). It would technically be possible to have a separated accessible node tree (a root node with nodes for each section) that is disconnected from the actual display tree, but specifies everything with The structure of the AccessibleInstance tree is essentially described by the recursive (kind-of pseudocode) function: function toInstances( node ) {
// prune subtrees that are used in an order
var effectiveChildren = node.children.filter( isAccessibleOrdered );
if ( node.accessibleOrder ) {
// fill the placeholder with the remaining children (notes below about placeholder)
effectiveChildren = node.accessibleOrder.slice().splice(
node.accessibleOrder.indexOf( PLACEHOLDER ), 1, effectiveChildren );
}
var instances = _.flatten( effectiveChildren.map( toInstances ) );
if ( this.accessibleContent ) {
return [ new AccessibleInstance( { children: instances } ) ];
}
else {
return instances;
}
} (this would be way too inefficient, and is also the "immutable" form, where we need efficient mutable operations). There are some open questions:
We'll potentially need to be careful to dispose/clear orders in nodes that we toss permanently (depending on our choices) so we either don't leak memory OR have things not show up at all. How we handle "outside the display" content (both as effective ancestors or descendants) will have a lot of impact on how things get implemented. The placeholder choice won't change the implementation much (it's mostly aesthetic and client-code maintenance related). For example, does Additionally, most of our current AccessibleInstance infrastructure ignores node trees "outside" of our display tree, so if we want to include something not displayed in an order, it will require reworking of that logic. Notably, our current system starts with the following 4 events that can cause a change to the AccessibleInstance tree:
The logic starts with This forwards to methods on the No matter what choices we make, we'll need to handle trails being pruned/unpruned (say they were added/removed from an order, or if we ignore non-display orders, whether the order they are in is now displayed / not displayed). This would basically look like Overall I think the current system is set up quite well to handle the main logic needed for our changes. We'll also need to check whether there is anything depending on accessibleInstance.trail being related to the trail of its parent/child (since now they will dramatically vary sometimes when subtrees are moved). Furthermore, we'll need to track visibility (or anything that affects subtrees) slightly differently (e.g. the voltmeter parent being invisible should "hide" it, even though the invisible parent is not in the order). As part of development, I highlight recommend making an I think discussing the open questions (and their trade-offs) needs to be done before I can provide more detail on any implementation of this, and a screen-sharing call (or in-person meeting) is probably needed to properly communicate. So is there a time where this can be discussed? Or should I fully think through the consequences of the trade-offs and provide more details (which will probably come with recommendations)? |
Also @ariel-phet, how involved should I be in the implementation of this? It mirrors a lot of the trade-offs and implementation patterns with the scenery "display" code, so it (a) would benefit from me being somewhat involved, but (b) having someone else be the full lead on implementation would be a valuable experience for understanding the constraints / patterns used elsewhere in scenery. Also priority/timeline would be good to know. |
Today, while @jessegreenberg and I were giving an a11y architecture briefing to the team, @pixelzoom brought this up as a large hindrance to converting sims. We should try to get this going before the code sprint. Renaming the issue. |
@jonathanolson as discussed yesterday, it would be great to have you involved. I believe that plan was a bit of intellectual collaboration with @jessegreenberg and @zepumph today, and then you helping to work on the issue once Area Model 1.0 is released and iOS maintenance release has occurred. |
No, only connected content for now (simplifies implementation, can change later)
Yes, we error out.
It would not show up in its "orginial" place in the tree if it is specific in any other order.
Dispose gets rid of the accessibleOrder's effect. |
I believe this is basically ready enough to work for prototyping for the sprint (if needed for sims other than area-model). Using the a11y-tree branch (for scenery and area-model-common), I'm able to successfully use the following pattern: // "Play Area" (a11y)
this.addChild( new Node( {
tagName: 'div',
labelTagName: 'h2',
labelContent: playAreaString,
accessibleOrder: [
this.areaDisplayNode,
this.factorsBox,
this.areaBox,
this.productsSelectionPanel,
this.calculationSelectionPanel,
this.partitionSelectionPanel,
this.calculationNode
].filter( function( node ) { return node !== undefined; } ) // this.partitionSelectionPanel may not exist
} ) );
// "Control Panel" (a11y)
this.addChild( new Node( {
tagName: 'div',
labelTagName: 'h2',
labelContent: controlPanelString,
accessibleOrder: [
gridCheckbox,
tileCheckbox,
countingCheckbox,
this.sceneSelectionNode,
this.resetAllButton
]
} ) ); and behaves normally. I have a decent list of questions and discussion items for @jessegreenberg and @zepumph (can wait until after the sprint), and this work is NOT yet ready to be merged into master. It will take a combination to discussion, some refinement, adding unit tests / more inline tests / fuzz tests, QA, etc. |
Also, it's not quite passing all unit tests yet (4 fail). At least one test will need to have its behavior changed to match our "new" understanding of how visibility works, but the other three seems like a buggy situation where I don't understand why things aren't focusing. |
We are meeting to discuss a few loose ends of this tomorrow. @jonathanolson, let me know if there is anything you want from me to do save that. |
NOTE: When this comes up for review, going to the branch on GitHub (https://github.com/phetsims/scenery/tree/a11y-tree) and clicking the "Compare" button (under the "Clone or download" button), then going to "Files changed" and then looking at the diffs should be invaluable. I've made significant changes along the way, so viewing commit-by-commit would be super-inefficient. |
Or there may be a good way of doing that in Intellij. |
I've merged the a11y-tree branch into master (it's passing aqua fuzzing tests, aqua a11y tests, unit tests, a11y-specific fuzzing test, sim spot tests, builds, etc.) I'll be creating more specific "additional changes" issues in the scenery repo (tagging here) for more work. I'm leaving this open for the "original" discussion about how to structure the scene graph to do this best. #365 (comment) seems to be working nicely for area-model, but I don't have a problem with having everything as children under those if the structure supports it. |
I think that we should move this to another issue as well, this issue has done it's job well, but seems old and tired. See #381 for continued discussion. Thanks @jonathanolson for the good work, anyone please feel free to reopen if there is more to discuss. |
We should work to make sure that all sims create the three main sections (Scene Summary, Play Area, and Control Panel) in the same way. I recently added specific nodes for those in
scenery-phet/js/accessibility/nodes
but perhaps there is a better way to do it. Then we should change all sims to do this. Ideally this would happen before we teach other devs how to create static descriptions. Assigning to all three of us.One thought.
What if we added three public nodes to
ScreenView.js
, so that you always have access to them if you had access to the screen view. likeWorst case this may be a little strange to then have to pass them far down the view to where they are needed. I'm not sure I even like this idea, just getting the conversation going.
The text was updated successfully, but these errors were encountered: