|
1 | 1 | const HTMLElement = globalThis.HTMLElement || (null as unknown as (typeof window)['HTMLElement']) |
2 | 2 |
|
3 | | -type IncrementKeyCode = 'ArrowRight' | 'ArrowDown' |
4 | | -type DecrementKeyCode = 'ArrowUp' | 'ArrowLeft' |
5 | | - |
6 | 3 | function getTabs(el: TabContainerElement): HTMLElement[] { |
7 | 4 | return Array.from(el.querySelectorAll<HTMLElement>('[role="tablist"] [role="tab"]')).filter( |
8 | 5 | tab => tab instanceof HTMLElement && tab.closest(el.tagName) === el, |
@@ -33,17 +30,6 @@ export class TabContainerChangeEvent extends Event { |
33 | 30 | } |
34 | 31 | } |
35 | 32 |
|
36 | | -function getNavigationKeyCodes(vertical: boolean): [IncrementKeyCode[], DecrementKeyCode[]] { |
37 | | - if (vertical) { |
38 | | - return [ |
39 | | - ['ArrowDown', 'ArrowRight'], |
40 | | - ['ArrowUp', 'ArrowLeft'], |
41 | | - ] |
42 | | - } else { |
43 | | - return [['ArrowRight'], ['ArrowLeft']] |
44 | | - } |
45 | | -} |
46 | | - |
47 | 33 | export class TabContainerElement extends HTMLElement { |
48 | 34 | static define(tag = 'tab-container', registry = customElements) { |
49 | 35 | registry.define(tag, this) |
@@ -109,21 +95,21 @@ export class TabContainerElement extends HTMLElement { |
109 | 95 | } |
110 | 96 |
|
111 | 97 | #handleKeydown(event: KeyboardEvent) { |
112 | | - const target = event.target |
113 | | - if (!(target instanceof HTMLElement)) return |
114 | | - if (target.closest(this.tagName) !== this) return |
115 | | - if (target.getAttribute('role') !== 'tab' && !target.closest('[role="tablist"]')) return |
| 98 | + const tab = (event.target as HTMLElement)?.closest?.('[role="tab"]') |
| 99 | + if (!tab) return |
116 | 100 | const tabs = getTabs(this) |
117 | | - const currentIndex = tabs.indexOf(tabs.find(tab => tab.matches('[aria-selected="true"]'))!) |
118 | | - const [incrementKeys, decrementKeys] = getNavigationKeyCodes( |
119 | | - target.closest('[role="tablist"]')?.getAttribute('aria-orientation') === 'vertical', |
120 | | - ) |
| 101 | + if (!tabs.includes(tab as HTMLElement)) return |
| 102 | + |
| 103 | + const currentIndex = tabs.indexOf(tabs.find(e => e.matches('[aria-selected="true"]'))!) |
| 104 | + const vertical = tab.closest('[role="tablist"]')?.getAttribute('aria-orientation') === 'vertical' |
| 105 | + const prevTab = event.code === 'ArrowLeft' || (vertical && event.code === 'ArrowUp') |
| 106 | + const nextTab = event.code === 'ArrowRight' || (vertical && event.code === 'ArrowDown') |
121 | 107 |
|
122 | | - if (incrementKeys.some(code => event.code === code)) { |
| 108 | + if (nextTab) { |
123 | 109 | let index = currentIndex + 1 |
124 | 110 | if (index >= tabs.length) index = 0 |
125 | 111 | this.selectTab(index) |
126 | | - } else if (decrementKeys.some(code => event.code === code)) { |
| 112 | + } else if (prevTab) { |
127 | 113 | let index = currentIndex - 1 |
128 | 114 | if (index < 0) index = tabs.length - 1 |
129 | 115 | this.selectTab(index) |
|
0 commit comments