Skip to content

Commit 4ff1c4f

Browse files
committed
feat(combo): update Tab and Escape key behavior
1 parent a9ac451 commit 4ff1c4f

File tree

3 files changed

+99
-4
lines changed

3 files changed

+99
-4
lines changed

src/components/combo/combo.spec.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,85 @@ describe('Combo', () => {
714714
expect(combo.open).to.be.true;
715715
});
716716

717+
it('should close the menu by pressing the Tab key', async () => {
718+
await combo.show();
719+
await list.layoutComplete;
720+
721+
pressKey(options, 'Tab', 1, { altKey: false });
722+
await elementUpdated(combo);
723+
expect(combo.open).to.be.false;
724+
725+
await combo.show();
726+
pressKey(searchInput, 'Tab', 1, { altKey: false });
727+
await elementUpdated(combo);
728+
729+
expect(combo.open).to.be.false;
730+
731+
await combo.show();
732+
pressKey(input, 'Tab', 1, { altKey: false });
733+
await elementUpdated(combo);
734+
735+
expect(combo.open).to.be.false;
736+
});
737+
738+
it('should clear the selection by pressing the Escape key when the combo is closed', async () => {
739+
combo.autofocusList = true;
740+
combo.select(['BG01', 'BG02']);
741+
await elementUpdated(combo);
742+
743+
await combo.show();
744+
await list.layoutComplete;
745+
746+
pressKey(options, 'Escape', 1, { altKey: false });
747+
await elementUpdated(combo);
748+
749+
expect(combo.open).to.be.false;
750+
expect(combo.value.length).to.equal(2);
751+
752+
pressKey(input, 'Escape', 1, { altKey: false });
753+
await elementUpdated(combo);
754+
755+
expect(combo.open).to.be.false;
756+
expect(combo.value.length).to.equal(0);
757+
});
758+
759+
it('should close the menu by pressing the Tab key in single selection', async () => {
760+
await combo.show();
761+
await list.layoutComplete;
762+
763+
pressKey(options, 'Tab', 1, { altKey: false });
764+
await elementUpdated(combo);
765+
766+
expect(combo.open).to.be.false;
767+
768+
await combo.show();
769+
pressKey(input, 'Tab', 1, { altKey: false });
770+
await elementUpdated(combo);
771+
772+
expect(combo.open).to.be.false;
773+
});
774+
775+
it('should clear the selection by pressing the Escape key in single selection', async () => {
776+
combo.singleSelect = true;
777+
combo.select('BG01');
778+
await elementUpdated(combo);
779+
780+
await combo.show();
781+
await list.layoutComplete;
782+
783+
pressKey(options, 'Escape', 1, { altKey: false });
784+
await elementUpdated(combo);
785+
786+
expect(combo.open).to.be.false;
787+
expect(combo.value.length).to.equal(1);
788+
789+
pressKey(input, 'Escape', 1, { altKey: false });
790+
await elementUpdated(combo);
791+
792+
expect(combo.open).to.be.false;
793+
expect(combo.value.length).to.equal(0);
794+
});
795+
717796
it('should select the active item and close the menu by pressing Enter in single selection', async () => {
718797
combo.singleSelect = true;
719798
await elementUpdated(combo);

src/components/combo/combo.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ export default class IgcComboComponent<
701701
this.emitEvent('igcClosed');
702702
}
703703
this._navigation.active = -1;
704+
this._input.focus();
704705
return true;
705706
}
706707

@@ -841,6 +842,15 @@ export default class IgcComboComponent<
841842

842843
protected handleMainInputKeydown(e: KeyboardEvent) {
843844
this._setTouchedState();
845+
if (e.key === 'Escape' && !this.open) {
846+
if (this.singleSelect) {
847+
this.resetSearchTerm();
848+
this.clearSingleSelection();
849+
} else {
850+
this._selection.deselect([], true);
851+
}
852+
this.updateValue();
853+
}
844854
this._navigation.navigateMainInput(e, this._list);
845855
}
846856

src/components/combo/controllers/navigation.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class NavigationController<T extends object>
3535
Escape: this.escape,
3636
ArrowUp: this.escape,
3737
ArrowDown: this.inputArrowDown,
38-
Tab: this.inputArrowDown,
38+
Tab: this.tab,
3939
})
4040
);
4141

@@ -252,7 +252,9 @@ export class NavigationController<T extends object>
252252
event.stopPropagation();
253253

254254
if (this.mainInputHandlers.has(event.key)) {
255-
event.preventDefault();
255+
if (event.key.toLowerCase() !== 'tab') {
256+
event.preventDefault();
257+
}
256258
this.mainInputHandlers.get(event.key)!.call(this, container);
257259
}
258260
}
@@ -264,7 +266,9 @@ export class NavigationController<T extends object>
264266
event.stopPropagation();
265267

266268
if (this.searchInputHandlers.has(event.key)) {
267-
event.preventDefault();
269+
if (event.key.toLowerCase() !== 'tab') {
270+
event.preventDefault();
271+
}
268272
this.searchInputHandlers.get(event.key)!.call(this, container);
269273
}
270274
}
@@ -273,7 +277,9 @@ export class NavigationController<T extends object>
273277
event.stopPropagation();
274278

275279
if (this.listHandlers.has(event.key)) {
276-
event.preventDefault();
280+
if (event.key.toLowerCase() !== 'tab') {
281+
event.preventDefault();
282+
}
277283
this.listHandlers.get(event.key)!.call(this, container);
278284
}
279285
}

0 commit comments

Comments
 (0)