From cdbfb4687d9e96ae229f285dfa523fecd3c9a59f Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Fri, 19 Apr 2024 10:15:21 -0400 Subject: [PATCH 1/2] first attempt --- examples/index.html | 25 +++++++++++++++++++++++-- src/tab-container-element.ts | 18 ++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/examples/index.html b/examples/index.html index 4e3553e..0d7f7e2 100644 --- a/examples/index.html +++ b/examples/index.html @@ -46,6 +46,27 @@

Horizontal (custom tablist)

+

Horizontal (custom tablist and tablist-wrapper)

+ + +
+
+ + + +
+
+
+ Panel 1 +
+ + +
+

Vertical (shadow tablist)

@@ -140,7 +161,7 @@

Panel with extra buttons

- - + + diff --git a/src/tab-container-element.ts b/src/tab-container-element.ts index 831409d..382405b 100644 --- a/src/tab-container-element.ts +++ b/src/tab-container-element.ts @@ -104,7 +104,7 @@ export class TabContainerElement extends HTMLElement { } get #tabListTabWrapper() { - return this.shadowRoot!.querySelector('div[part="tablist-tab-wrapper"]')! + return this.shadowRoot!.querySelector('slot[part="tablist-tab-wrapper"]')! } get #beforeTabsSlot() { @@ -165,8 +165,9 @@ export class TabContainerElement extends HTMLElement { const tabListContainer = document.createElement('div') tabListContainer.style.display = 'flex' tabListContainer.setAttribute('part', 'tablist-wrapper') - const tabListTabWrapper = document.createElement('div') + const tabListTabWrapper = document.createElement('slot') tabListTabWrapper.setAttribute('part', 'tablist-tab-wrapper') + tabListTabWrapper.setAttribute('name', 'tablist-tab-wrapper') const tabListSlot = document.createElement('slot') tabListSlot.setAttribute('part', 'tablist') tabListSlot.setAttribute('name', 'tablist') @@ -275,13 +276,22 @@ export class TabContainerElement extends HTMLElement { if (!this.#setupComplete) { const tabListSlot = this.#tabListSlot const customTabList = this.querySelector('[role=tablist]') - if (customTabList && customTabList.closest(this.tagName) === this) { + const customTabListWrapper = this.querySelector('[slot=tablist-tab-wrapper]') + if (customTabListWrapper && customTabListWrapper.closest(this.tagName) === this) { + if (manualSlotsSupported) { + tabListSlot.assign(customTabListWrapper) + } else { + customTabListWrapper.setAttribute('slot', 'tablist') + } + } + else if (customTabList && customTabList.closest(this.tagName) === this) { if (manualSlotsSupported) { tabListSlot.assign(customTabList) } else { customTabList.setAttribute('slot', 'tablist') } - } else { + } + else { this.#tabListTabWrapper.role = 'tablist' if (manualSlotsSupported) { tabListSlot.assign(...[...this.children].filter(e => e.matches('[role=tab]'))) From 2a0e8d2a5fced1395ee55f2f18d4349b614c0fee Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Mon, 22 Apr 2024 11:21:35 -0400 Subject: [PATCH 2/2] adds the ability to have a custom tablist-tab-wrapper --- examples/index.html | 4 +-- src/tab-container-element.ts | 12 +++++---- test/test.js | 49 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/examples/index.html b/examples/index.html index 0d7f7e2..e752ef6 100644 --- a/examples/index.html +++ b/examples/index.html @@ -161,7 +161,7 @@

Panel with extra buttons

- - + + diff --git a/src/tab-container-element.ts b/src/tab-container-element.ts index 382405b..bdd9f1a 100644 --- a/src/tab-container-element.ts +++ b/src/tab-container-element.ts @@ -283,15 +283,13 @@ export class TabContainerElement extends HTMLElement { } else { customTabListWrapper.setAttribute('slot', 'tablist') } - } - else if (customTabList && customTabList.closest(this.tagName) === this) { + } else if (customTabList && customTabList.closest(this.tagName) === this) { if (manualSlotsSupported) { tabListSlot.assign(customTabList) } else { customTabList.setAttribute('slot', 'tablist') } - } - else { + } else { this.#tabListTabWrapper.role = 'tablist' if (manualSlotsSupported) { tabListSlot.assign(...[...this.children].filter(e => e.matches('[role=tab]'))) @@ -312,7 +310,11 @@ export class TabContainerElement extends HTMLElement { const afterSlotted: Element[] = [] let autoSlotted = beforeSlotted for (const child of this.children) { - if (child.getAttribute('role') === 'tab' || child.getAttribute('role') === 'tablist') { + if ( + child.getAttribute('role') === 'tab' || + child.getAttribute('role') === 'tablist' || + child.getAttribute('slot') === 'tablist-tab-wrapper' + ) { autoSlotted = afterTabSlotted continue } diff --git a/test/test.js b/test/test.js index 441aa41..28cb708 100644 --- a/test/test.js +++ b/test/test.js @@ -669,4 +669,53 @@ describe('tab-container', function () { ) }) }) + describe('with custom tablist-tab-wrapper', function () { + beforeEach(function () { + document.body.innerHTML = ` + +
+
+ + + +
+
+ +
+ Panel 2 +
+ +
+ ` + tabs = Array.from(document.querySelectorAll('button')) + panels = Array.from(document.querySelectorAll('[role="tabpanel"]')) + }) + + afterEach(function () { + // Check to make sure we still have accessible markup after the test finishes running. + expect(document.body).to.be.accessible() + + document.body.innerHTML = '' + }) + + it('has accessible markup', function () { + expect(document.body).to.be.accessible() + }) + + it('the second tab is still selected', 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') + }) + + it('selects the clicked tab', function () { + tabs[0].click() + + assert.deepStrictEqual(tabs.map(isSelected), [true, false, false], 'First tab is selected') + assert.deepStrictEqual(panels.map(isHidden), [false, true, true], 'First panel is visible') + }) + }) })