Skip to content

Commit a268e80

Browse files
authored
fix: opening drop should focus on next available option only initially (#229)
* fix: opening drop should focus on next available option only initially - opening the drop should move highlight to next available option but only on the initial opening, meaning that if we close and reopen the drop then it should keep its highlight index. Prior to this PR, closing/reopening multiple times was moving the highlight down by 1 option every time which is wrong
1 parent 33396ea commit a268e80

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"editor.defaultFormatter": "biomejs.biome",
33
"editor.formatOnSave": true,
4+
"editor.formatOnSaveMode": "file",
45
"editor.formatOnPaste": false,
56
"typescript.tsdk": "node_modules\\typescript\\lib"
6-
}
7+
}

packages/multiple-select-vanilla/src/MultipleSelectInstance.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class MultipleSelectInstance {
2929
protected fromHtml = false;
3030
protected choiceElm!: HTMLButtonElement;
3131
protected closeElm?: HTMLElement | null;
32-
protected closeSearchElm?: HTMLElement | null;
32+
protected clearSearchIconElm?: HTMLElement | null;
3333
protected filterText = '';
3434
protected updateData: any[] = [];
3535
protected data?: Array<OptionRowData | OptGroupRowData> = [];
@@ -718,7 +718,7 @@ export class MultipleSelectInstance {
718718
'option-list-scroll',
719719
]);
720720

721-
this.closeSearchElm = this.filterParentElm?.querySelector('.icon-close');
721+
this.clearSearchIconElm = this.filterParentElm?.querySelector('.icon-close');
722722
this.searchInputElm = this.dropElm.querySelector<HTMLInputElement>('.ms-search input');
723723
this.selectAllElm = this.dropElm.querySelector<HTMLInputElement>(`input[data-name="${this.selectAllName}"]`);
724724
this.selectGroupElms = this.dropElm.querySelectorAll<HTMLInputElement>(
@@ -774,13 +774,16 @@ export class MultipleSelectInstance {
774774
}) as EventListener);
775775
}
776776

777-
if (this.closeSearchElm) {
778-
this._bindEventService.bind(this.closeSearchElm, 'click', ((e: MouseEvent) => {
777+
if (this.clearSearchIconElm) {
778+
this._bindEventService.bind(this.clearSearchIconElm, 'click', ((e: MouseEvent) => {
779779
e.preventDefault();
780780
if (this.searchInputElm) {
781781
this.searchInputElm.value = '';
782782
this.searchInputElm.focus();
783783
}
784+
// move highlight back to top of the list
785+
this._currentHighlightIndex = -1;
786+
this.moveFocusDown();
784787
this.filter();
785788
}) as EventListener);
786789
}
@@ -1096,7 +1099,14 @@ export class MultipleSelectInstance {
10961099
ulElm.focus();
10971100
}
10981101
}
1099-
this.moveFocusDown();
1102+
1103+
if (this._currentHighlightIndex < 0) {
1104+
// on open drop initial, we'll focus on next available option
1105+
this.moveFocusDown();
1106+
} else {
1107+
// if it was already opened earlier, we'll keep same option index focused
1108+
this.highlightCurrentOption();
1109+
}
11001110

11011111
if (this.options.autoAdjustDropWidthByTextSize) {
11021112
this.adjustDropWidthByText();

playwright/e2e/options35.spec.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,21 @@ test.describe('Options 35 - Diacritic Parser', () => {
2626
await page.locator('[data-test=select1] .ms-search .icon-close').click();
2727
await expect(page.locator('[data-test=select1] .ms-search span')).toHaveText('');
2828

29-
await page.getByRole('textbox', { name: '🔎︎' }).fill('û');
30-
await page.keyboard.press('Enter');
29+
await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('û ');
3130
await expect(page.locator('input.in-log')).toHaveValue('û');
3231
await expect(page.locator('input.out-log')).toHaveValue('u');
3332
await expect(page.locator('[data-test=select1].ms-drop li:not(.ms-no-results)')).toHaveCount(3);
3433
await page.locator('[data-test=select1] .ms-search .icon-close').click();
3534
await page.getByRole('textbox', { name: '🔎︎' }).fill('u');
36-
await page.keyboard.press('Enter');
3735
await page.locator('[data-test=select1] span').filter({ hasText: 'Juin' }).click();
3836
await page.locator('[data-test=select1] span').filter({ hasText: 'Juillet' });
3937
await page.locator('[data-test=select1] span').filter({ hasText: 'Août' }).click();
4038
const parentSpan = await page.locator('div[data-test=select1] .ms-choice span');
4139
await expect(parentSpan).toHaveText('Février, Juin, Août');
4240
await page.locator('[data-test=select1].ms-parent').click();
4341

44-
// // 2nd Select
45-
// // --------------
42+
// 2nd Select
43+
// --------------
4644
await page.locator('[data-test=select2].ms-parent').click();
4745
await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('év');
4846
await page.locator('[data-test=select2] span').filter({ hasText: 'Février' }).click();
@@ -56,22 +54,20 @@ test.describe('Options 35 - Diacritic Parser', () => {
5654
await expect(page.locator('[data-test=select2] .ms-search span')).toHaveText('');
5755
await expect(page.locator('[data-test=select2].ms-drop li:not(.ms-no-results)')).toHaveCount(12);
5856

59-
await page.getByRole('textbox', { name: '🔎︎' }).fill('e');
60-
await page.keyboard.press('Enter');
57+
await page.getByRole('textbox', { name: '🔎︎' }).press('e');
6158
await expect(page.locator('[data-test=select2].ms-drop li:not(.ms-no-results)')).toHaveCount(7);
6259
await page.locator('[data-test=select2] .ms-search .icon-close').click();
6360
await expect(page.locator('[data-test=select2] .ms-search span')).toHaveText('');
6461

65-
await page.getByRole('textbox', { name: '🔎︎' }).fill('û');
66-
await page.keyboard.press('Enter');
62+
await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('û ');
6763
await expect(page.locator('[data-test=select2].ms-drop li:not(.ms-no-results)')).toHaveCount(3);
6864
await page.locator('[data-test=select2] .ms-search .icon-close').click();
69-
await page.getByRole('textbox', { name: '🔎︎' }).pressSequentially('u');
65+
await page.getByRole('textbox', { name: '🔎︎' }).press('u');
7066
await page.locator('[data-test=select2] span').filter({ hasText: 'Juin' }).click();
7167
await page.locator('[data-test=select2] span').filter({ hasText: 'Juillet' });
7268
await page.locator('[data-test=select2] span').filter({ hasText: 'Août' }).click();
7369
const parentSpan2 = await page.locator('div[data-test=select2] .ms-choice span');
74-
await expect(parentSpan2).toHaveText('Juin, Août');
70+
await expect(parentSpan2).toHaveText('Février, Juin, Août');
7571
await page.locator('[data-test=select2].ms-parent').click();
7672
});
7773
});

0 commit comments

Comments
 (0)