Skip to content

Commit 5e45050

Browse files
committed
Make sure selected option is focused when listbox is opened
1 parent 986c9d5 commit 5e45050

File tree

2 files changed

+26
-26
lines changed

2 files changed

+26
-26
lines changed

src/components/input/Select.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,9 @@ function SelectOption<T>({
187187
role="option"
188188
aria-disabled={disabled}
189189
aria-selected={selected}
190-
// This is intended to be focused with arrow keys
191-
tabIndex={-1}
190+
// Set tabIndex to 0 for selected option, so that useArrowKeyNavigation
191+
// initially focuses it
192+
tabIndex={selected ? 0 : -1}
192193
ref={downcastRef(optionRef)}
193194
title={title}
194195
>

src/components/input/test/Select-test.js

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,18 @@ describe('Select', () => {
118118
return listboxTop < buttonTop;
119119
};
120120

121+
const getOption = (wrapper, id) =>
122+
wrapper.find(`[data-testid="option-${id}"]`).closest('[role="option"]');
123+
121124
const clickOption = (wrapper, id) => {
122125
openListbox(wrapper);
123-
wrapper.find(`[data-testid="option-${id}"]`).simulate('click');
126+
getOption(wrapper, id).simulate('click');
124127
};
125128

126129
function clickOptionCheckbox(wrapper, id) {
127130
openListbox(wrapper);
128131

129-
const checkbox = wrapper
130-
.find(`[data-testid="option-${id}"]`)
131-
.closest('[role="option"]')
132-
.find('input[type="checkbox"]');
132+
const checkbox = getOption(wrapper, id).find('input[type="checkbox"]');
133133

134134
if (!checkbox.exists()) {
135135
throw new Error(
@@ -143,20 +143,15 @@ describe('Select', () => {
143143
const pressKeyInOption = (wrapper, id, key) => {
144144
openListbox(wrapper);
145145

146-
wrapper
147-
.find(`[data-testid="option-${id}"]`)
148-
.closest('[role="option"]')
146+
getOption(wrapper, id)
149147
.getDOMNode()
150148
.dispatchEvent(new KeyboardEvent('keydown', { key }));
151149
};
152150

153151
function pressKeyInOptionCheckbox(wrapper, id, key) {
154152
openListbox(wrapper);
155153

156-
const checkbox = wrapper
157-
.find(`[data-testid="option-${id}"]`)
158-
.closest('[role="option"]')
159-
.find('input[type="checkbox"]');
154+
const checkbox = getOption(wrapper, id).find('input[type="checkbox"]');
160155

161156
if (!checkbox.exists()) {
162157
throw new Error(
@@ -320,11 +315,7 @@ describe('Select', () => {
320315
toggleListbox(wrapper);
321316

322317
// Focus listbox option before closing listbox
323-
wrapper
324-
.find('[data-testid="option-3"]')
325-
.getDOMNode()
326-
.closest('[role="option"]')
327-
.focus();
318+
getOption(wrapper, '3').getDOMNode().focus();
328319

329320
toggleListbox(wrapper);
330321
wrapper.update();
@@ -391,6 +382,19 @@ describe('Select', () => {
391382
});
392383
});
393384

385+
it('sets tabIndex=0 for the selected option', () => {
386+
const wrapper = createComponent({ value: defaultItems[2] });
387+
const getTabIndex = id => getOption(wrapper, id).prop('tabIndex');
388+
389+
openListbox(wrapper);
390+
391+
assert.equal(getTabIndex(1), -1);
392+
assert.equal(getTabIndex(2), -1);
393+
assert.equal(getTabIndex(3), 0);
394+
assert.equal(getTabIndex(4), -1);
395+
assert.equal(getTabIndex(5), -1);
396+
});
397+
394398
context('when Option is rendered outside of Select', () => {
395399
it('throws an error', () => {
396400
assert.throws(
@@ -698,9 +702,7 @@ describe('Select', () => {
698702
openListbox(wrapper);
699703

700704
// Spy on checkbox focus
701-
const checkbox = wrapper
702-
.find(`[data-testid="option-${optionId}"]`)
703-
.closest('[role="option"]')
705+
const checkbox = getOption(wrapper, optionId)
704706
.find('input[type="checkbox"]')
705707
.getDOMNode();
706708
const focusStub = sinon.stub(checkbox, 'focus');
@@ -717,10 +719,7 @@ describe('Select', () => {
717719
);
718720
openListbox(wrapper);
719721

720-
const option = wrapper
721-
.find(`[data-testid="option-${optionId}"]`)
722-
.closest('[role="option"]')
723-
.getDOMNode();
722+
const option = getOption(wrapper, optionId).getDOMNode();
724723
const focusStub = sinon.stub(option, 'focus');
725724

726725
pressKeyInOptionCheckbox(wrapper, optionId, 'ArrowLeft');

0 commit comments

Comments
 (0)