Skip to content

Commit

Permalink
allow slotted content
Browse files Browse the repository at this point in the history
  • Loading branch information
keithamus committed Feb 16, 2024
1 parent c74ed91 commit 0ca96f0
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
16 changes: 6 additions & 10 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,12 @@ <h2>Vertical (custom tablist)</h2>
<h2>Panel with extra buttons</h2>

<tab-container>
<div style="display: flex">
<button>Left button, not a tab!</button>
<button>2nd Left button, not a tab!</button>
<div role="tablist" aria-label="Tabs Example with extra buttons">
<button type="button" id="tab-one" role="tab">Tab one</button>
<button type="button" id="tab-two" role="tab">Tab two</button>
<button type="button" id="tab-three" role="tab">Tab three</button>
</div>
<button>Right button, not a tab!</button>
</div>
<button>Left button, not a tab!</button>
<button type="button" id="tab-one" role="tab">Tab one</button>
<button type="button" id="tab-two" role="tab">Tab two</button>
<button type="button" id="tab-three" role="tab">Tab three</button>
<button>Right button, not a tab!</button>
<button slot="before-tabs">2nd Left button, not a tab!</button>
<div role="tabpanel" aria-labelledby="tab-one">
Panel 1
</div>
Expand Down
55 changes: 52 additions & 3 deletions src/tab-container-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ export class TabContainerElement extends HTMLElement {
}
}

get #beforeTabsSlot() {
return this.shadowRoot!.querySelector<HTMLSlotElement>('slot[part="before-tabs"]')!
}

get #afterTabsSlot() {
return this.shadowRoot!.querySelector<HTMLSlotElement>('slot[part="after-tabs"]')!
}

get #afterPanelsSlot() {
return this.shadowRoot!.querySelector<HTMLSlotElement>('slot[part="after-panels"]')!
}

get #tabListSlot() {
return this.shadowRoot!.querySelector<HTMLSlotElement>('slot[part="tablist"]')!
}
Expand All @@ -94,8 +106,12 @@ export class TabContainerElement extends HTMLElement {
)
}

get activePanel() {
return this.#panelSlot.assignedNodes()[0] as HTMLElement
}

get vertical(): boolean {
return this.#tabList.getAttribute('aria-orientation') === 'vertical'
return this.#tabList?.getAttribute('aria-orientation') === 'vertical'
}

set vertical(isVertical: boolean) {
Expand All @@ -112,12 +128,21 @@ export class TabContainerElement extends HTMLElement {
connectedCallback(): void {
this.#internals ||= this.attachInternals ? this.attachInternals() : null
const shadowRoot = this.shadowRoot || this.attachShadow({mode: 'open', slotAssignment: 'manual'})
const tabListContainer = document.createElement('div')
tabListContainer.style.display = 'flex'
const tabListSlot = document.createElement('slot')
tabListSlot.setAttribute('part', 'tablist')
const panelSlot = document.createElement('slot')
panelSlot.setAttribute('part', 'panel')
panelSlot.setAttribute('role', 'presentation')
shadowRoot.replaceChildren(tabListSlot, panelSlot)
const beforeTabSlot = document.createElement('slot')
beforeTabSlot.setAttribute('part', 'before-tabs')
const afterTabSlot = document.createElement('slot')
afterTabSlot.setAttribute('part', 'after-tabs')
tabListContainer.append(beforeTabSlot, tabListSlot, afterTabSlot)
const afterSlot = document.createElement('slot')
afterSlot.setAttribute('part', 'after-panels')
shadowRoot.replaceChildren(tabListContainer, panelSlot, afterSlot)

if (this.#internals && 'role' in this.#internals) {
this.#internals.role = 'presentation'
Expand Down Expand Up @@ -186,7 +211,7 @@ export class TabContainerElement extends HTMLElement {

selectTab(index: number): void {
if (!this.#setup) {
const tabListSlot = this.#tabListSlot;
const tabListSlot = this.#tabListSlot
const customTabList = this.querySelector('[role=tablist]')
if (customTabList && customTabList.closest(this.tagName) === this) {
tabListSlot.assign(customTabList)
Expand All @@ -207,6 +232,30 @@ export class TabContainerElement extends HTMLElement {
if (this.vertical) {
this.#tabList.setAttribute('aria-orientation', 'vertical')
}
const beforeSlotted: Element[] = []
const afterTabSlotted: Element[] = []
const afterSlotted: Element[] = []
let autoSlotted = beforeSlotted
for (const child of this.children) {
if (child.getAttribute('role') === 'tab' || child.getAttribute('role') === 'tablist') {
autoSlotted = afterTabSlotted
continue
}
if (child.getAttribute('role') === 'tabpanel') {
autoSlotted = afterSlotted
continue
}
if (child.getAttribute('slot') === 'before-tabs') {
beforeSlotted.push(child)
} else if (child.getAttribute('slot') === 'after-tabs') {
afterTabSlotted.push(child)
} else {
autoSlotted.push(child)
}
}
this.#beforeTabsSlot.assign(...beforeSlotted)
this.#afterTabsSlot.assign(...afterTabSlotted)
this.#afterPanelsSlot.assign(...afterSlotted)
}

const tabs = this.#tabs
Expand Down

0 comments on commit 0ca96f0

Please sign in to comment.