diff --git a/src/tab-container-element.ts b/src/tab-container-element.ts index 431b63c..563e0df 100644 --- a/src/tab-container-element.ts +++ b/src/tab-container-element.ts @@ -111,6 +111,10 @@ export class TabContainerElement extends HTMLElement { ) } + get activeTab() { + return this.#tabs[this.selectedTabIndex] + } + get activePanel() { return this.#panelSlot.assignedNodes()[0] as HTMLElement } @@ -189,7 +193,7 @@ export class TabContainerElement extends HTMLElement { const tabs = this.#tabs if (!tabs.includes(tab as HTMLElement)) return - const currentIndex = tabs.indexOf(tabs.find(e => e.matches('[aria-selected="true"]'))!) + const currentIndex = this.selectedTabIndex const vertical = tab.closest('[role="tablist"]')?.getAttribute('aria-orientation') === 'vertical' const prevTab = event.code === 'ArrowLeft' || (vertical && event.code === 'ArrowUp') const nextTab = event.code === 'ArrowRight' || (vertical && event.code === 'ArrowDown') @@ -226,6 +230,14 @@ export class TabContainerElement extends HTMLElement { } } + get selectedTabIndex(): number { + return this.#tabs.findIndex(el => el.matches('[aria-selected=true]')) + } + + set selectedTabIndex(i: number) { + this.selectTab(i) + } + selectTab(index: number): void { if (!this.#setupComplete) { const tabListSlot = this.#tabListSlot @@ -283,7 +295,7 @@ export class TabContainerElement extends HTMLElement { for (const el of afterSlotted) el.setAttribute('slot', 'after-panels') } const defaultTab = Number(this.getAttribute('default-tab') || -1) - const defaultIndex = defaultTab >= 0 ? defaultTab : this.#tabs.findIndex(el => el.matches('[aria-selected=true]')) + const defaultIndex = defaultTab >= 0 ? defaultTab : this.selectedTabIndex index = index >= 0 ? index : Math.max(0, defaultIndex) } diff --git a/test/test.js b/test/test.js index 17fb96c..f8a6a9e 100644 --- a/test/test.js +++ b/test/test.js @@ -183,6 +183,8 @@ describe('tab-container', function () { 'change events point to second panel', ) assert.equal(document.activeElement, tabs[1]) + assert.equal(tabContainer.activeTab, tabs[1]) + assert.equal(tabContainer.selectedTabIndex, 1) }) it('keyboard shortcuts work and `tab-container-changed` events are dispatched', function () { @@ -208,6 +210,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [true, false, false], 'First tab is selected') assert.deepStrictEqual(panels.map(isHidden), [false, true, true], 'First panel is visible') assert.equal(document.activeElement, tabs[0]) + assert.equal(tabContainer.activeTab, tabs[0]) + assert.equal(tabContainer.selectedTabIndex, 0) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -301,6 +305,8 @@ describe('tab-container', function () { 'change events point to second panel', ) assert.equal(document.activeElement, tabs[1]) + assert.equal(tabContainer.activeTab, tabs[1]) + assert.equal(tabContainer.selectedTabIndex, 1) }) it('result in noop, when selectTab receives out of bounds index', function () { @@ -445,6 +451,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [false, false, true], 'Third tab is selected') assert.deepStrictEqual(panels.map(isHidden), [true, true, false], 'Third panel is visible') assert.equal(document.activeElement, tabs[2]) + assert.equal(tabContainer.activeTab, tabs[2]) + assert.equal(tabContainer.selectedTabIndex, 2) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -467,6 +475,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [true, false, false], 'First tab is selected') assert.deepStrictEqual(panels.map(isHidden), [false, true, true], 'First panel is visible') assert.equal(document.activeElement, tabs[0]) + assert.equal(tabContainer.activeTab, tabs[0]) + assert.equal(tabContainer.selectedTabIndex, 0) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -489,6 +499,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [false, true, false], 'Second tab is selected') assert.deepStrictEqual(panels.map(isHidden), [true, false, true], 'Second panel is visible') assert.equal(document.activeElement, tabs[1]) + assert.equal(tabContainer.activeTab, tabs[1]) + assert.equal(tabContainer.selectedTabIndex, 1) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -511,6 +523,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [false, false, true], 'Third tab is selected') assert.deepStrictEqual(panels.map(isHidden), [true, true, false], 'Third panel is visible') assert.equal(document.activeElement, tabs[2]) + assert.equal(tabContainer.activeTab, tabs[2]) + assert.equal(tabContainer.selectedTabIndex, 2) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -534,6 +548,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [false, false, true], 'Third tab is selected') assert.deepStrictEqual(panels.map(isHidden), [true, true, false], 'Third panel is visible') assert.equal(document.activeElement, tabs[2]) + assert.equal(tabContainer.activeTab, tabs[2]) + assert.equal(tabContainer.selectedTabIndex, 2) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -556,6 +572,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [true, false, false], 'First tab is selected') assert.deepStrictEqual(panels.map(isHidden), [false, true, true], 'First panel is visible') assert.equal(document.activeElement, tabs[0]) + assert.equal(tabContainer.activeTab, tabs[0]) + assert.equal(tabContainer.selectedTabIndex, 0) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -578,6 +596,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [false, true, false], 'Second tab is selected') assert.deepStrictEqual(panels.map(isHidden), [true, false, true], 'Second panel is visible') assert.equal(document.activeElement, tabs[1]) + assert.equal(tabContainer.activeTab, tabs[1]) + assert.equal(tabContainer.selectedTabIndex, 1) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type), @@ -600,6 +620,8 @@ describe('tab-container', function () { assert.deepStrictEqual(tabs.map(isSelected), [false, false, true], 'Third tab is selected') assert.deepStrictEqual(panels.map(isHidden), [true, true, false], 'Third panel is visible') assert.equal(document.activeElement, tabs[2]) + assert.equal(tabContainer.activeTab, tabs[2]) + assert.equal(tabContainer.selectedTabIndex, 2) assert.equal(events.length, 2, 'tab-container-change(d) called') assert.deepStrictEqual( events.map(e => e.type),