|
1 | 1 | const HTMLElement = globalThis.HTMLElement || (null as unknown as (typeof window)['HTMLElement']) |
| 2 | +const manualSlotsSupported = 'assign' in HTMLSlotElement.prototype |
2 | 3 |
|
3 | 4 | export class TabContainerChangeEvent extends Event { |
4 | 5 | constructor(type: string, {tab, panel, ...init}: EventInit & {tab?: Element; panel?: Element}) { |
@@ -133,16 +134,21 @@ export class TabContainerElement extends HTMLElement { |
133 | 134 | tabListContainer.setAttribute('part', 'tablist-wrapper') |
134 | 135 | const tabListSlot = document.createElement('slot') |
135 | 136 | tabListSlot.setAttribute('part', 'tablist') |
| 137 | + tabListSlot.setAttribute('name', 'tablist') |
136 | 138 | const panelSlot = document.createElement('slot') |
137 | 139 | panelSlot.setAttribute('part', 'panel') |
| 140 | + panelSlot.setAttribute('name', 'panel') |
138 | 141 | panelSlot.setAttribute('role', 'presentation') |
139 | 142 | const beforeTabSlot = document.createElement('slot') |
140 | 143 | beforeTabSlot.setAttribute('part', 'before-tabs') |
| 144 | + beforeTabSlot.setAttribute('name', 'before-tabs') |
141 | 145 | const afterTabSlot = document.createElement('slot') |
142 | 146 | afterTabSlot.setAttribute('part', 'after-tabs') |
| 147 | + afterTabSlot.setAttribute('name', 'after-tabs') |
143 | 148 | tabListContainer.append(beforeTabSlot, tabListSlot, afterTabSlot) |
144 | 149 | const afterSlot = document.createElement('slot') |
145 | 150 | afterSlot.setAttribute('part', 'after-panels') |
| 151 | + afterSlot.setAttribute('name', 'after-panels') |
146 | 152 | shadowRoot.replaceChildren(tabListContainer, panelSlot, afterSlot) |
147 | 153 |
|
148 | 154 | if (this.#internals && 'role' in this.#internals) { |
@@ -218,9 +224,19 @@ export class TabContainerElement extends HTMLElement { |
218 | 224 | const tabListSlot = this.#tabListSlot |
219 | 225 | const customTabList = this.querySelector('[role=tablist]') |
220 | 226 | if (customTabList && customTabList.closest(this.tagName) === this) { |
221 | | - tabListSlot.assign(customTabList) |
| 227 | + if (manualSlotsSupported) { |
| 228 | + tabListSlot.assign(customTabList) |
| 229 | + } else { |
| 230 | + customTabList.setAttribute('slot', 'tablist') |
| 231 | + } |
222 | 232 | } else { |
223 | | - tabListSlot.assign(...[...this.children].filter(e => e.matches('[role=tab]'))) |
| 233 | + if (manualSlotsSupported) { |
| 234 | + tabListSlot.assign(...[...this.children].filter(e => e.matches('[role=tab]'))) |
| 235 | + } else { |
| 236 | + for (const e of this.children) { |
| 237 | + if (e.matches('[role=tab]')) e.setAttribute('slot', 'tablist') |
| 238 | + } |
| 239 | + } |
224 | 240 | tabListSlot.role = 'tablist' |
225 | 241 | tabListSlot.style.display = 'block' |
226 | 242 | } |
@@ -251,9 +267,15 @@ export class TabContainerElement extends HTMLElement { |
251 | 267 | autoSlotted.push(child) |
252 | 268 | } |
253 | 269 | } |
254 | | - this.#beforeTabsSlot.assign(...beforeSlotted) |
255 | | - this.#afterTabsSlot.assign(...afterTabSlotted) |
256 | | - this.#afterPanelsSlot.assign(...afterSlotted) |
| 270 | + if (manualSlotsSupported) { |
| 271 | + this.#beforeTabsSlot.assign(...beforeSlotted) |
| 272 | + this.#afterTabsSlot.assign(...afterTabSlotted) |
| 273 | + this.#afterPanelsSlot.assign(...afterSlotted) |
| 274 | + } else { |
| 275 | + for (const el of beforeSlotted) el.setAttribute('slot', 'before-tabs') |
| 276 | + for (const el of afterTabSlotted) el.setAttribute('slot', 'after-tabs') |
| 277 | + for (const el of afterSlotted) el.setAttribute('slot', 'after-panels') |
| 278 | + } |
257 | 279 | const defaultTab = Number(this.getAttribute('default-tab') || -1) |
258 | 280 | const defaultIndex = defaultTab >= 0 ? defaultTab : this.#tabs.findIndex(el => el.matches('[aria-selected=true]')) |
259 | 281 | index = index >= 0 ? index : Math.max(0, defaultIndex) |
@@ -294,11 +316,18 @@ export class TabContainerElement extends HTMLElement { |
294 | 316 | if (!panel.hasAttribute('tabindex') && !panel.hasAttribute('data-tab-container-no-tabstop')) { |
295 | 317 | panel.setAttribute('tabindex', '0') |
296 | 318 | } |
| 319 | + if (!manualSlotsSupported && panel.hasAttribute('slot')) { |
| 320 | + panel.removeAttribute('slot') |
| 321 | + } |
297 | 322 | } |
298 | 323 |
|
299 | 324 | selectedTab.setAttribute('aria-selected', 'true') |
300 | 325 | selectedTab.setAttribute('tabindex', '0') |
301 | | - this.#panelSlot.assign(selectedPanel) |
| 326 | + if (manualSlotsSupported) { |
| 327 | + this.#panelSlot.assign(selectedPanel) |
| 328 | + } else { |
| 329 | + selectedPanel.setAttribute('slot', 'panel') |
| 330 | + } |
302 | 331 | selectedPanel.hidden = false |
303 | 332 |
|
304 | 333 | if (this.#setupComplete) { |
|
0 commit comments