Skip to content

Commit ed0b611

Browse files
authored
[Accessibility] [Screen Reader] Enable the screen reader to announce when nodes are expanded and collapsed in the JSON tree view (#2299)
* Added screen reader announcements when nodes are expanded and collapsed. * Added a new line at the end of the file * Added a comment
1 parent 15c552c commit ed0b611

File tree

3 files changed

+57
-40
lines changed

3 files changed

+57
-40
lines changed

packages/sdk/ui-react/src/widget/collapsibleJsonViewer/collapsibleJsonViewer.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,9 @@
2323
width: calc(100% - 10px);
2424
}
2525
}
26+
27+
.aria-region {
28+
position: absolute;
29+
top: -9999px;
30+
overflow: hidden;
31+
}

packages/sdk/ui-react/src/widget/collapsibleJsonViewer/collapsibleJsonViewer.spec.tsx

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -67,48 +67,51 @@ const mockData = {
6767
};
6868

6969
const mockTreeHTMLText = `
70-
<ul id="rootGroup">
71-
<li>
72-
<div>
73-
<div>▶</div>
74-
</div>
75-
<label><span>root:</span></label>
76-
<span>
77-
<span>
78-
<span>{}</span> 2 keys
79-
</span></span>
80-
<ul id="group1">
81-
<li>
82-
<div>
83-
<div>▶</div>
84-
</div>
85-
<label><span>membersAdded:</span></label>
86-
<span><span><span>[]</span> 1 item</span></span>
87-
<ul id="group2">
88-
<li>
89-
<div role="button" id="actuator">
90-
<div>▶</div>
91-
</div>
92-
<label><span>0:</span></label>
93-
<span>
70+
<div>
71+
<ul id="rootGroup">
72+
<li>
73+
<div>
74+
<div>▶</div>
75+
</div>
76+
<label><span>root:</span></label>
77+
<span>
78+
<span>
79+
<span>{}</span> 2 keys
80+
</span></span>
81+
<ul id="group1">
82+
<li>
83+
<div>
84+
<div>▶</div>
85+
</div>
86+
<label><span>membersAdded:</span></label>
87+
<span><span><span>[]</span> 1 item</span></span>
88+
<ul id="group2">
89+
<li>
90+
<div role="button" id="actuator">
91+
<div>▶</div>
92+
</div>
93+
<label><span>0:</span></label>
9494
<span>
95-
<span>{}</span>
96-
2 keys
95+
<span>
96+
<span>{}</span>
97+
2 keys
98+
</span>
9799
</span>
98-
</span>
99-
<ul id="group3">
100-
<li><label><span>id:</span></label><span>"1"</span></li>
101-
<li><label><span>name:</span></label><span>"Bot"</span>
102-
</li>
103-
</ul>
104-
</li>
105-
</ul>
106-
</li>
107-
<li><label><span>type:</span></label><span>"conversationUpdate"</span>
108-
</li>
109-
</ul>
110-
</li>
111-
</ul>`;
100+
<ul id="group3">
101+
<li><label><span>id:</span></label><span>"1"</span></li>
102+
<li><label><span>name:</span></label><span>"Bot"</span>
103+
</li>
104+
</ul>
105+
</li>
106+
</ul>
107+
</li>
108+
<li><label><span>type:</span></label><span>"conversationUpdate"</span>
109+
</li>
110+
</ul>
111+
</li>
112+
</ul>
113+
<div id="ariaRegion" role="region" aria-live="polite" className={styles.ariaRegion}>text content</div>
114+
</div>`;
112115

113116
let jsonViewerWrapper;
114117
let jsonViewer;
@@ -117,6 +120,7 @@ describe('The JsonViewer', () => {
117120
beforeAll(() => {
118121
jsonViewerWrapper = mount(<CollapsibleJsonViewer data={mockData} themeName={'high-contrast'} />);
119122
jsonViewer = jsonViewerWrapper.find(CollapsibleJsonViewer).instance();
123+
document.body.innerHTML = mockTreeHTMLText;
120124
});
121125

122126
it('should render with data and a theme', () => {

packages/sdk/ui-react/src/widget/collapsibleJsonViewer/collapsibleJsonViewer.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export class CollapsibleJsonViewer extends Component<CollapsibleJsonViewerProps,
115115
return (
116116
<div ref={this.jsonTreeContainerRef} className={styles.collapsibleJsonViewer}>
117117
<JSONTree data={data} theme={themeNameToViewerThemeName[themeName]} invertTheme={false} {...jsonTreeProps} />
118+
<div id="ariaRegion" role="region" aria-live="polite" className={styles.ariaRegion} />
118119
</div>
119120
);
120121
}
@@ -186,6 +187,12 @@ export class CollapsibleJsonViewer extends Component<CollapsibleJsonViewerProps,
186187
const proposedAriaExpandedValue = !(ul.getAttribute('aria-expanded') === 'true');
187188
ul.setAttribute('aria-expanded', proposedAriaExpandedValue.toString());
188189
target.setAttribute('aria-expanded', proposedAriaExpandedValue.toString());
190+
// Announce the expanded/collapsed state
191+
const ariaRegion = document.getElementById('ariaRegion');
192+
const newState = proposedAriaExpandedValue ? 'Node expanded' : 'Node collapsed';
193+
// Concatenate the '.' in case it's not present in the textContent property
194+
// to announce that the node was expanded or collapsed
195+
ariaRegion.textContent = ariaRegion.textContent.indexOf('.') > -1 ? newState : newState.concat('.');
189196
};
190197

191198
private focusNext(event: KeyboardEvent): void {

0 commit comments

Comments
 (0)