Skip to content

Commit b0c04c4

Browse files
authored
Scrollable Listbox Example: Ad default value 'None' so first item can be focusable on load (pull #3139)
Fixes issue #3138 by adding a new value of 'None' to the list of options and focusing that option by default. This makes the example consistent with the pattern guidance.
1 parent 3c8b715 commit b0c04c4

File tree

7 files changed

+34
-24
lines changed

7 files changed

+34
-24
lines changed

content/patterns/listbox/examples/js/listbox-collapsible.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ class ListboxButton {
5353
case 'ArrowDown':
5454
evt.preventDefault();
5555
this.showListbox();
56-
this.listbox.checkKeyPress(evt);
5756
break;
5857
}
5958
}

content/patterns/listbox/examples/js/listbox.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ aria.Listbox = class Listbox {
5959
if (this.activeDescendant) {
6060
const listitem = document.getElementById(this.activeDescendant);
6161
listitem.scrollIntoView({ block: 'nearest', inline: 'nearest' });
62+
} else {
63+
this.focusFirstItem();
6264
}
6365
}
6466

content/patterns/listbox/examples/listbox-collapsible.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ <h2 id="ex_label">Example</h2>
6666
<div id="exp_wrapper">
6767
<button type="button" aria-haspopup="listbox" aria-labelledby="exp_elem exp_button" id="exp_button">Neptunium</button>
6868
<ul id="exp_elem_list" tabindex="-1" role="listbox" aria-labelledby="exp_elem" class="hidden">
69+
<li id="exp_elem_None" role="option">None</li>
6970
<li id="exp_elem_Np" role="option">Neptunium</li>
7071
<li id="exp_elem_Pu" role="option">Plutonium</li>
7172
<li id="exp_elem_Am" role="option">Americium</li>

content/patterns/listbox/examples/listbox-scrollable.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ <h2 id="ex_label">Example</h2>
5353
<div>
5454
<span id="ss_elem" class="listbox-label">Transuranium elements:</span>
5555
<ul id="ss_elem_list" tabindex="0" role="listbox" aria-labelledby="ss_elem">
56+
<li id="ss_elem_None" role="option">
57+
<span class="checkmark" aria-hidden="true"></span>
58+
None
59+
</li>
5660
<li id="ss_elem_Np" role="option">
5761
<span class="checkmark" aria-hidden="true"></span>
5862
Neptunium

test/tests/listbox_collapsible.js

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const ex = {
1313
buttonSelector: '#ex button',
1414
listboxSelector: '#ex [role="listbox"]',
1515
optionSelector: '#ex [role="option"]',
16-
numOptions: 26,
16+
numOptions: 27,
1717
};
1818

1919
const checkFocus = async function (t, selector) {
@@ -132,23 +132,27 @@ ariaTest(
132132
By.css(ex.listboxSelector)
133133
);
134134
const options = await t.context.queryElements(t, ex.optionSelector);
135-
const optionId = await options[0].getAttribute('id');
135+
const optionId0 = await options[0].getAttribute('id');
136+
const optionId1 = await options[1].getAttribute('id');
136137

137-
// no active descendant is expected until arrow keys are used
138+
// The first active descendant is selected
138139
t.is(
139140
await listbox.getAttribute('aria-activedescendant'),
140-
null,
141-
'activedescendant not set on open click'
141+
optionId0,
142+
'aria-activedescendant should be set to ' +
143+
optionId0 +
144+
' for items: ' +
145+
ex.listboxSelector
142146
);
143147

144-
// active descendant set to first item on down arrow
148+
// The active descendant moves to the second item on down arrow
145149
await listbox.sendKeys(Key.DOWN);
146150

147151
t.is(
148152
await listbox.getAttribute('aria-activedescendant'),
149-
optionId,
153+
optionId1,
150154
'aria-activedescendant should be set to ' +
151-
optionId +
155+
optionId1 +
152156
' for items: ' +
153157
ex.listboxSelector
154158
);
@@ -160,7 +164,7 @@ ariaTest(
160164
exampleFile,
161165
'option-role',
162166
async (t) => {
163-
await assertAriaRoles(t, 'ex', 'option', 26, 'li');
167+
await assertAriaRoles(t, 'ex', 'option', 27, 'li');
164168
}
165169
);
166170

@@ -444,7 +448,7 @@ ariaTest(
444448
// will automatically select the first option.
445449
await t.context.session.findElement(By.css(ex.buttonSelector)).click();
446450

447-
// The third item is 'Americium'
451+
// The fourth item is 'Americium'
448452
let listbox = await t.context.session.findElement(
449453
By.css(ex.listboxSelector)
450454
);
@@ -453,7 +457,7 @@ ariaTest(
453457
t,
454458
ex.listboxSelector,
455459
ex.optionSelector,
456-
2
460+
3
457461
);
458462

459463
// Reload page
@@ -464,14 +468,14 @@ ariaTest(
464468
await t.context.session.findElement(By.css(ex.buttonSelector)).click();
465469

466470
// Keys in rapid session will treat characters like first few characters of item
467-
// In this cae, 'Curium' at index 3 will be skipped for 'Californium' at index 5
471+
// In this cae, 'Curium' at index 4 will be skipped for 'Californium' at index 6
468472
listbox = await t.context.session.findElement(By.css(ex.listboxSelector));
469473
await listbox.sendKeys('c', 'a');
470474
await assertAriaSelectedAndActivedescendant(
471475
t,
472476
ex.listboxSelector,
473477
ex.optionSelector,
474-
5
478+
6
475479
);
476480

477481
// Reload page
@@ -483,25 +487,25 @@ ariaTest(
483487

484488
listbox = await t.context.session.findElement(By.css(ex.listboxSelector));
485489

486-
// With a break, sending on 'b' will land us on 'Berkelium' at index 4
490+
// With a break, sending on 'b' will land us on 'Berkelium' at index 5
487491
await listbox.sendKeys('b');
488492
await assertAriaSelectedAndActivedescendant(
489493
t,
490494
ex.listboxSelector,
491495
ex.optionSelector,
492-
4
496+
5
493497
);
494498

495499
// Wait for half a second before sending second 'b'
496500
await new Promise((resolve) => setTimeout(resolve, 500));
497501

498-
// A second 'b' should land us on 'Bohrium' at index 14
502+
// A second 'b' should land us on 'Bohrium' at index 15
499503
await listbox.sendKeys('b');
500504
await assertAriaSelectedAndActivedescendant(
501505
t,
502506
ex.listboxSelector,
503507
ex.optionSelector,
504-
14
508+
15
505509
);
506510
}
507511
);

test/tests/listbox_grouped.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ ariaTest(
176176
);
177177

178178
ariaTest(
179-
'DOWN ARROW sends initial focus to the first option',
179+
'DOWN ARROW moves focus to the second option',
180180
exampleFile,
181181
'key-down-arrow',
182182
async (t) => {
183-
// Sending the key down arrow will put focus on the first option if no options are focused
183+
// Sending the key down arrow will move focus to the second option.
184184
const listbox = await t.context.session.findElement(
185185
By.css(ex.listboxSelector)
186186
);
@@ -190,7 +190,7 @@ ariaTest(
190190
t,
191191
ex.listboxSelector,
192192
ex.optionSelector,
193-
0
193+
1
194194
);
195195
}
196196
);

test/tests/listbox_scrollable.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ const ex = {
1212
listboxSelector: '#ex [role="listbox"]',
1313
optionSelector: '#ex [role="option"]',
1414
spanSelector: '#ex [role="option"] span.checkmark',
15-
numOptions: 26,
16-
firstOptionSelector: '#ex #ss_elem_Np',
15+
numOptions: 27,
16+
firstOptionSelector: '#ex #ss_elem_None',
1717
};
1818

1919
// Attributes
@@ -75,7 +75,7 @@ ariaTest(
7575
exampleFile,
7676
'option-role',
7777
async (t) => {
78-
await assertAriaRoles(t, 'ex', 'option', 26, 'li');
78+
await assertAriaRoles(t, 'ex', 'option', 27, 'li');
7979
}
8080
);
8181

0 commit comments

Comments
 (0)