feat(a11y): Add keyboard navigation, focus management, and ARIA labels to pipeline nodes and groups - #322
Conversation
|
/cc @danreed-rh |
d304dff to
35bcbf9
Compare
| interface LabelActionIconProps { | ||
| className?: string; | ||
| icon: React.ReactElement; | ||
| 'aria-label'?: string; |
There was a problem hiding this comment.
Since we are defining aria-label as the prop name here, and adding it to the calling definition, but then immediately re-casting it as 'ariaLabel' below, can we just have it as ariaLabel here as well? Do we expect this component to be called like a normal html element where a user might pass in 'aria-label' as a prop and that's why we do it this way? I see it used a couple of times in this PR, made me curious
There was a problem hiding this comment.
fwiw, in the base PatternFly react repo, that's how we handle aria props (use kebab case, but later use camel case). Just for consistency probably better to keep it like this here as well.
There was a problem hiding this comment.
Yes, I was just following PatternFly conventions.
|
When going through the demo (and I'm not sure if me experiencing this in the demo means a user would experience it when implemented), I noticed that if I tab through the items and then select an item with space or keyboard, I visually see the item gain focus. Presumably this would open a details window if that was available like in odh-dashboard. When I focus on an item, and then press tab, tab focus returns to the browser tabs at the top of the screen, as if I had reached the end of focusable content on the page. I think each time you select an item it puts it on the bottom of the dom tree, by selecting items by clicking them or tabbing to them and pressing space, I'm able to re-order them in the tree, each item I select gets added to the bottom of the stack. |
Thanks @danreed-rh. I've looked into this some more. I found the reason to be due to how I have updated the demo to use I also updated the |
| <TaskNode | ||
| element={element} | ||
| tabIndex={data.tabIndex} | ||
| labelTooltipTrigger="mouseenter" |
There was a problem hiding this comment.
The context menus are not able to be opened or focused via keyboard.
If you add an actionIconAriaLabel to these TaskNodes, i think that should give it a tabindex because of the logic on LabelActionIcon.tsx:507
There was a problem hiding this comment.
It will, this is for the Set tab indices option. When that is off, no data.tabIndex will be set.
| onChange={(_event, checked) => pipelineOptions.setSetTabIndices(checked)} | ||
| label="Set tab indices" | ||
| /> | ||
| </ToolbarItem> |
There was a problem hiding this comment.
I don't understand what this option is for... when I check it, i cannot keyboard into the pipeline at all.
As far as i can tell, the tab order is correct without needing to check the 'Set tab indices' box...
There was a problem hiding this comment.
This is a demo where we set an ordered tabIndex on each node. Focus does go out the the browser before coming back to the graph. You can see that the tab order is slightly different in that it does not tab to the groups first before tabbing to the nodes.
There was a problem hiding this comment.
I think this demo is too confusing. I'm removing it.
thatblindgeye
left a comment
There was a problem hiding this comment.
In addition to file comments below we likely want to give nodes and groups an actual semantic role, plus allow providing other attributes as necessary. Right now the nodes are just being announced as "graphics symbol", which doesnt' really tell the user they can interact with the node nor its current state (in terms of selected/pressed, expanded, etc). This maybe could be a followup; deciding what roles to give each and what attributes would need to be added/documented might need a little discussion.
|
|
||
| Pipeline task nodes and groups are keyboard accessible by default. `<TaskNode>` and `<DefaultTaskGroup>` set `tabIndex` to `0`, so you can tab to these components. | ||
|
|
||
| To keep truncated labels from being announced twice, set `labelTooltipTrigger` to `mouseenter` on `<TaskNode>` or `<DefaultTaskGroup>`. This keeps the label from receiving focus during keyboard navigation. |
There was a problem hiding this comment.
We shouldn't prevent the tooltips from triggering on keyboard focus. Instead (assuming the PF Tooltip is being used) you could pass aria="none" and aria-live="off" on the Tooltip component to help prevent duplicate announcement.
There was a problem hiding this comment.
I cannot get this to work. It is still getting to a "group" and announcing.
There was a problem hiding this comment.
For now can we enable focus trigger the tooltip, and have looking into the repetitive announcement as a followwup? Between both less-than-ideal behaviors, I think exposing the full node name via keyboard might be less egregious than duplicate announcment via SR.
There was a problem hiding this comment.
Yeah, it's opt-in to use the hover trigger, by default it is focus. We can try to improve the default behavior as a follow up.
The full node name is still announced when the node itself gets focus (along with it's status).
There was a problem hiding this comment.
Gotcha, yeah a followup to potentially tweak this would be good, for keyboard without a screen reader
|
|
||
| To keep truncated labels from being announced twice, set `labelTooltipTrigger` to `mouseenter` on `<TaskNode>` or `<DefaultTaskGroup>`. This keeps the label from receiving focus during keyboard navigation. | ||
|
|
||
| Tab order follows grouping and the order nodes are added to the model. Groups come first, followed by nodes in the order they were added. To control tab order, set `tabIndex` on `<TaskNode>` or `<DefaultTaskGroup>` when you can determine the presentation order programmatically. Explicit `tabIndex` values also keep selection from changing tab order by moving the selected item to the end. |
There was a problem hiding this comment.
Could we maybe note that manually setting tab order will require the consumer to ensure tab order on the entire page doesnt break and that reading/focus order from a page level still makes sense?
| ## Known issues | ||
|
|
||
| The pipelines layout has the following known accessibility issues: | ||
|
|
||
| - Selecting a node reorders it to the last item in its layer, which changes the node's place in the tab order. Further selections move that node after the previously selected node, and so on. | ||
| - Setting `tabIndex` on nodes and groups avoids the selection issue. It can also change how focus enters the graph, so focus may move to browser controls. |
There was a problem hiding this comment.
Not sure if wew really need to include this section. We could instead mention the issue of selection causing a reorder when mentioning the manual tab order control above.
If the only way to prevent selection causing a tab reorder on a node is via manual control of that tab order, we may also want to strongly recommend consumers handle that themselves (taking into account that they would also need to ensure general page tab order doesn't break or anything). Otherwise the gain of being able to tab through and select nodes is offset by a new bug/issue of "well now I lost my place within these nodes and have to go through the entire page again/reorient myself somehow".
There was a problem hiding this comment.
I will remove the section. I'm going to remove the Set tab indicies demo as well
There was a problem hiding this comment.
I realize I hadn't pushed my changes to this doc. Please re-review.
| --- | ||
| id: Accessibility | ||
| section: extensions | ||
| subsection: topology | ||
| sortValue: 999 | ||
| --- |
There was a problem hiding this comment.
This can be a followup if it isn't as straight forward to implement for an extension, but if this file is meant to be strictly accessibility for the "Pipelines" section of topology, would be nice to include it as a tab on the Pipelines page (similar to how each PF component has the "HTML", "React", ..., "Accessibility" tabs)
There was a problem hiding this comment.
I thought about that but I'm not sure where we would document the accessibility features for non-pipeline layouts.
Once we have it for both, the information for both will likely not need to be split between layout types. We can have it all here in one section. But for now, we only support it for pipelines.
|
|
||
| ## Pipelines layout | ||
|
|
||
| Pipeline task nodes and groups are keyboard accessible by default. `<TaskNode>` and `<DefaultTaskGroup>` set `tabIndex` to `0`, so you can tab to these components. |
There was a problem hiding this comment.
| Pipeline task nodes and groups are keyboard accessible by default. `<TaskNode>` and `<DefaultTaskGroup>` set `tabIndex` to `0`, so you can tab to these components. | |
| `<TaskNode>` and `<DefaultTaskGroup>` set `tabIndex` to `0`, so you can tab to these components and select them via both keyboard and mouse. |
I think just due to the caveat mentioned about the tab reordering issue, maybe just avoiding saying these are keyboard accessible by default.
Added PF-4571 |
33e7bf0 to
a189990
Compare
|
I have updated the demo to remove the I have updated the @nicolethoen @thatblindgeye Please take another look. I have updated the surge at https://pipelines-a11y.surge.sh/ |
thatblindgeye
left a comment
There was a problem hiding this comment.
One reply above regarding the focus/tooltip comment I left before. Also, could we remove the "Known issues" section (still seeing it in the PR) and update the "keyboard accessible" verbiage per this comment https://github.com/patternfly/react-topology/pull/322/changes#r3853945278
…s to pipeline nodes and groups
a189990 to
fb581eb
Compare
|
🎉 This PR is included in version 6.6.0-prerelease.3 🎉 The release is available on: Your semantic-release bot 📦🚀 |
What
Closes #319
Description
Addresses big ticket accessibility issues with pipelines layout.
aria-labelprops onTaskNode,DefaultTaskGroup, andLabelActionIcon, with auto-generated labels that include the node's run status (e.g. "Build (succeeded)")tabIndex={-1}to layer<g>elements so focus does not get trapped when tabbing through the graph:focus-visibleoutlines on pill backgrounds, status icon circles, and group backgrounds using PatternFly focus ring tokenslabelTooltipTriggerprop toTaskNode/TaskPillto allow controlling tooltip trigger behavior (e.g.mouseentervsfocus). This is useful to prevent focus on the pill label when trucated and announcing the label a second time.actionIconAriaLabelthroughNodeLabel→LabelActionIconand addcollapseAriaLabel/expandAriaLabelprops toDefaultTaskGroupfor accessible expand/collapse buttonsType of change
Screen shots / Gifs for design review
See https://pipelines-a11y.surge.sh/