Skip to content

Commit e45f5eb

Browse files
nikkimkbennypowers
andauthored
fix(core): resolves #2408 for roving-tabindex-controller (#2410)
* fix(core): resolves #2408 for roving-tabindex-controller * fix(roving-tabindex-controller): added changeset * Update .changeset/fresh-pumas-wave.md Co-authored-by: Benny Powers <[email protected]> * fix(core): fixed roving-tabindex-controller eventListener * fix(core): this binding in roving-tabindex-controller.ts .bind() creates a new object on each call, so we can't use it to removeEventListener. Also makes the itemsContainer default to the host at each initItems call --------- Co-authored-by: Benny Powers <[email protected]>
1 parent abf2a7c commit e45f5eb

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

.changeset/fresh-pumas-wave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@patternfly/pfe-core": minor
3+
---
4+
5+
`roving-tabindex-controller`: enabled controller to be used by aria-expanded elements

core/pfe-core/controllers/roving-tabindex-controller.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export class RovingTabindexController implements ReactiveController {
1515
/** active focusable element */
1616
#activeItem?: HTMLElement;
1717

18+
/** closest ancestor containing items */
19+
#itemsContainer?: HTMLElement;
20+
1821
/** array of all focusable elements */
1922
#items: HTMLElement[] = [];
2023

@@ -87,7 +90,7 @@ export class RovingTabindexController implements ReactiveController {
8790
/**
8891
* handles keyboard navigation
8992
*/
90-
#onKeydown(event: KeyboardEvent):void {
93+
#onKeydown = (event: KeyboardEvent) => {
9194
if (event.ctrlKey || event.altKey || event.metaKey || this.#focusableItems.length < 1) {
9295
return;
9396
}
@@ -97,9 +100,9 @@ export class RovingTabindexController implements ReactiveController {
97100
const horizontalOnly =
98101
!item ? false
99102
: item.tagName === 'SELECT' ||
100-
item.getAttribute('aria-expanded') === 'true' ||
101103
item.getAttribute('role') === 'spinbutton';
102104

105+
103106
switch (event.key) {
104107
case 'ArrowLeft':
105108
this.focusOnItem(this.prevItem);
@@ -153,7 +156,7 @@ export class RovingTabindexController implements ReactiveController {
153156
event.stopPropagation();
154157
event.preventDefault();
155158
}
156-
}
159+
};
157160

158161
/**
159162
* sets tabindex of item based on whether or not it is active
@@ -188,17 +191,35 @@ export class RovingTabindexController implements ReactiveController {
188191
/**
189192
* from array of HTML items, and sets active items
190193
*/
191-
initItems(items: HTMLElement[]) {
194+
initItems(items: HTMLElement[], itemsContainer: HTMLElement = this.host) {
192195
this.#items = items ?? [];
193196
const focusableItems = this.#focusableItems;
194197
const [focusableItem] = focusableItems;
195198
this.#activeItem = focusableItem;
196199
for (const item of focusableItems) {
197200
item.tabIndex = this.#activeItem === item ? 0 : -1;
198201
}
202+
/**
203+
* removes listener on previous contained and applies it to new container
204+
*/
205+
if (!this.#itemsContainer || itemsContainer !== this.#itemsContainer) {
206+
this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);
207+
this.#itemsContainer = itemsContainer;
208+
this.hostConnected();
209+
}
199210
}
200211

212+
/**
213+
* adds event listners to items container
214+
*/
201215
hostConnected() {
202-
this.host.addEventListener('keydown', this.#onKeydown.bind(this));
216+
this.#itemsContainer?.addEventListener('keydown', this.#onKeydown);
217+
}
218+
219+
/**
220+
* removes event listners from items container
221+
*/
222+
hostDisconnected() {
223+
this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);
203224
}
204225
}

0 commit comments

Comments
 (0)