Skip to content

Commit 669b1ea

Browse files
gavinbarronsebastienlevertmusale
authored
fix: editor tabs keyboard navigation (#2371)
makes visual tabs in editor behave like aria tabs Co-authored-by: Sébastien Levert <[email protected]> Co-authored-by: Musale Martin <[email protected]>
1 parent 70bef48 commit 669b1ea

File tree

1 file changed

+61
-12
lines changed

1 file changed

+61
-12
lines changed

.storybook/addons/codeEditorAddon/editor.js

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class EditorElement extends LitElement {
4141
color: #616161;
4242
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
4343
font-size: 11px;
44+
font-weight: 400;
4445
padding: 8px 18px;
4546
display: inline-block;
4647
cursor: pointer;
@@ -49,11 +50,12 @@ export class EditorElement extends LitElement {
4950
border: 1px solid transparent;
5051
}
5152
52-
.tab.selected {
53+
.tab[aria-selected='true'] {
5354
background-color: white;
5455
color: rgb(51, 51, 51);
55-
font-weight: 400;
56+
font-weight: 600;
5657
border: 2px solid transparent;
58+
text-decoration: underline;
5759
}
5860
`;
5961
}
@@ -90,6 +92,7 @@ export class EditorElement extends LitElement {
9092
this.editorRoot = document.createElement('div');
9193
this.editorRoot.setAttribute('slot', 'editor');
9294
this.editorRoot.style.height = '100%';
95+
this.tabFocus = 0;
9396

9497
this.updateCurrentFile = debounce(() => {
9598
this.files[this.currentType] = this.editor.getValue();
@@ -181,9 +184,8 @@ export class EditorElement extends LitElement {
181184
window.removeEventListener('resize', this.handleResize);
182185
}
183186

184-
showTab(type, event) {
187+
showTab(type) {
185188
this.editor.updateOptions({ readOnly: false });
186-
if (event && event.keyCode != 13) return;
187189

188190
this.currentType = type;
189191
if (this.files && typeof this.files[type] !== 'undefined') {
@@ -199,26 +201,73 @@ export class EditorElement extends LitElement {
199201
}
200202
}
201203

204+
tabKeyDown = e => {
205+
const tabs = this.renderRoot.querySelectorAll('.tab');
206+
// Move right
207+
if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
208+
tabs[this.tabFocus].setAttribute('tabindex', -1);
209+
if (e.key === 'ArrowRight') {
210+
this.tabFocus++;
211+
// If we're at the end, go to the start
212+
if (this.tabFocus >= tabs.length) {
213+
this.tabFocus = 0;
214+
}
215+
// Move left
216+
} else if (e.key === 'ArrowLeft') {
217+
this.tabFocus--;
218+
// If we're at the start, move to the end
219+
if (this.tabFocus < 0) {
220+
this.tabFocus = tabs.length - 1;
221+
}
222+
}
223+
224+
tabs[this.tabFocus].setAttribute('tabindex', 0);
225+
tabs[this.tabFocus].focus();
226+
}
227+
};
228+
202229
render() {
203230
return html`
204-
<div class="root" tabindex=0>
205-
<div class="tab-root" tabindex=0">
231+
<div class="root">
232+
<div class="tab-root" role="tablist" tabindex="0" @keydown="${this.tabKeyDown}" >
206233
${this.fileTypes.map(
207234
type => html`
208-
<div
209-
@keydown=${e => this.showTab(type, e)}
210-
tabindex=0
235+
<button
236+
tabindex="${type === this.currentType ? 0 : -1}"
211237
@click="${_ => this.showTab(type)}"
212238
id="${type}"
213-
class="tab ${type === this.currentType ? 'selected' : ''}">
239+
role="tab"
240+
class="tab"
241+
aria-selected="${type === this.currentType}"
242+
aria-controls="${`tab-${type}`}"
243+
>
214244
${type}
215-
</div>
245+
</button>
216246
`
217247
)}
218248
</div>
219-
<div class="editor-root">
249+
<div
250+
class="editor-root"
251+
role="tabpanel"
252+
id="${`tab-${this.currentType}`}"
253+
aria-labelledby="${this.currentType}"
254+
tabindex=0
255+
>
220256
<slot name="editor"></slot>
221257
</div>
258+
${this.fileTypes.map(type =>
259+
type !== this.currentType
260+
? html`
261+
<div
262+
role="tabpanel"
263+
id="${`tab-${type}`}"
264+
aria-labelledby="${type}"
265+
tabindex=0
266+
hidden
267+
></div>
268+
`
269+
: ''
270+
)}
222271
</div>
223272
`;
224273
}

0 commit comments

Comments
 (0)