Skip to content

Commit

Permalink
Make sure selected option is focused when listbox is opened
Browse files Browse the repository at this point in the history
  • Loading branch information
acelaya committed Nov 5, 2024
1 parent 986c9d5 commit 207342d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 26 deletions.
5 changes: 3 additions & 2 deletions src/components/input/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,9 @@ function SelectOption<T>({
role="option"
aria-disabled={disabled}
aria-selected={selected}
// This is intended to be focused with arrow keys
tabIndex={-1}
// Set tabIndex to 0 for selected option, so that useArrowKeyNavigation
// initially focuses it
tabIndex={selected ? 0 : -1}
ref={downcastRef(optionRef)}
title={title}
>
Expand Down
47 changes: 23 additions & 24 deletions src/components/input/test/Select-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,18 @@ describe('Select', () => {
return listboxTop < buttonTop;
};

const getOption = (wrapper, id) =>
wrapper.find(`[data-testid="option-${id}"]`).closest('[role="option"]');

const clickOption = (wrapper, id) => {
openListbox(wrapper);
wrapper.find(`[data-testid="option-${id}"]`).simulate('click');
getOption(wrapper, id).simulate('click');
};

function clickOptionCheckbox(wrapper, id) {
openListbox(wrapper);

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

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

wrapper
.find(`[data-testid="option-${id}"]`)
.closest('[role="option"]')
getOption(wrapper, id)
.getDOMNode()
.dispatchEvent(new KeyboardEvent('keydown', { key }));
};

function pressKeyInOptionCheckbox(wrapper, id, key) {
openListbox(wrapper);

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

if (!checkbox.exists()) {
throw new Error(
Expand Down Expand Up @@ -320,11 +315,7 @@ describe('Select', () => {
toggleListbox(wrapper);

// Focus listbox option before closing listbox
wrapper
.find('[data-testid="option-3"]')
.getDOMNode()
.closest('[role="option"]')
.focus();
getOption(wrapper, '3').getDOMNode().focus();

toggleListbox(wrapper);
wrapper.update();
Expand Down Expand Up @@ -391,6 +382,19 @@ describe('Select', () => {
});
});

it('sets tabIndex=0 for the selected option', () => {
const wrapper = createComponent({ value: defaultItems[2] });
const getTabIndex = id => getOption(wrapper, id).prop('tabIndex');

openListbox(wrapper);

assert.equal(getTabIndex(1), -1);
assert.equal(getTabIndex(2), -1);
assert.equal(getTabIndex(3), 0);
assert.equal(getTabIndex(4), -1);
assert.equal(getTabIndex(5), -1);
});

context('when Option is rendered outside of Select', () => {
it('throws an error', () => {
assert.throws(
Expand Down Expand Up @@ -698,9 +702,7 @@ describe('Select', () => {
openListbox(wrapper);

// Spy on checkbox focus
const checkbox = wrapper
.find(`[data-testid="option-${optionId}"]`)
.closest('[role="option"]')
const checkbox = getOption(wrapper, optionId)
.find('input[type="checkbox"]')
.getDOMNode();
const focusStub = sinon.stub(checkbox, 'focus');
Expand All @@ -717,10 +719,7 @@ describe('Select', () => {
);
openListbox(wrapper);

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

pressKeyInOptionCheckbox(wrapper, optionId, 'ArrowLeft');
Expand Down

0 comments on commit 207342d

Please sign in to comment.