Skip to content

Commit 6dcaebe

Browse files
committed
feat!: move vaadin-tabs to light dom
1 parent bf2a978 commit 6dcaebe

File tree

3 files changed

+61
-39
lines changed

3 files changed

+61
-39
lines changed

demo/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
--anchor-nav-inner-max-width: 1000px;
4343
}
4444

45-
vcf-anchor-nav.main::part(tabs) {
45+
vcf-anchor-nav.main .tabs {
4646
box-shadow: inset 0 -1px 0 0 var(--lumo-contrast-20pct);
4747
z-index: 2;
4848
}

src/vcf-anchor-nav-section.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ class AnchorNavSectionElement extends ElementMixin(ThemableMixin(PolymerElement)
137137
}
138138

139139
get navTab() {
140-
return this.nav && this.nav.$ && this.nav.$.tabs && this.nav.$.tabs.querySelector(`#${this.tabId || this.defaultTabId}`);
140+
const tabs = this.nav.querySelector('vaadin-tabs');
141+
return this.nav && tabs && tabs.querySelector(`#${this.tabId || this.defaultTabId}`);
141142
}
142143

143144
get url() {
@@ -175,10 +176,13 @@ class AnchorNavSectionElement extends ElementMixin(ThemableMixin(PolymerElement)
175176

176177
_onTabSlotChange() {
177178
const tab = this.tab;
179+
178180
if (this.nav && this.nav.$ && tab) {
179181
tab.removeAttribute('slot');
180182
this.tabId = tab.id;
181-
this.nav.$.tabs.appendChild(tab);
183+
184+
this.nav.querySelector('vaadin-tabs').appendChild(tab);
185+
182186
this.nav._initTab(tab, this);
183187
this.nav._sortTabs();
184188
}

src/vcf-anchor-nav.js

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,19 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
9191
background: var(--anchor-nav-inner-background);
9292
}
9393
94-
[part='tabs'],
95-
::slotted([part='tabs']) {
94+
::slotted(.tabs) {
9695
position: -webkit-sticky;
9796
position: sticky;
9897
top: 0 !important;
9998
background: var(--lumo-base-color);
10099
z-index: 2;
101100
}
102101
103-
:host([has-header]) [part='tabs'],
104-
:host([has-header]) ::slotted([part='tabs']) {
102+
:host([has-header]) ::slotted(.tabs) {
105103
top: -1px !important;
106104
}
107105
108-
[part='tabs'][stuck]::after,
109-
::slotted([part='tabs'][stuck])::after {
106+
::slotted(.tabs[stuck])::after {
110107
content: ' ';
111108
position: absolute;
112109
width: 100%;
@@ -131,9 +128,7 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
131128
<div id="header" part="header">
132129
<slot id="headerSlot" name="header"></slot>
133130
</div>
134-
<slot id="tabsSlot" name="tabs">
135-
<vaadin-tabs id="tabs" part="tabs"></vaadin-tabs>
136-
</slot>
131+
<slot id="tabsSlot" name="tabs"></slot>
137132
<slot id="slot"></slot>
138133
</div>
139134
`;
@@ -230,7 +225,8 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
230225
}
231226

232227
get _tabHeight() {
233-
return this._verticalTabs ? 0 : this.$.tabs.clientHeight;
228+
const tabs = this.querySelector('vaadin-tabs');
229+
return this._verticalTabs ? 0 : tabs.clientHeight;
234230
}
235231

236232
get _expandLastHeight() {
@@ -241,16 +237,28 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
241237
return !this.disablePreserveOnRefresh;
242238
}
243239

240+
_createVaadinTabs() {
241+
const vaadinTabs = document.createElement('vaadin-tabs');
242+
vaadinTabs.setAttribute('id', 'tabs');
243+
vaadinTabs.setAttribute('slot', 'tabs');
244+
vaadinTabs.classList.add('tabs');
245+
this.appendChild(vaadinTabs);
246+
}
247+
244248
ready() {
245249
super.ready();
250+
this._createVaadinTabs();
251+
246252
this._verticalTabs = false;
247253
// Add polyfills
248254
smoothScrollPolyfill();
249-
stickyPolyfill.add(this.$.tabs);
255+
stickyPolyfill.add(this.querySelector('vaadin-tabs'));
256+
250257
// Init observers
251258
this._initTabsStuckAttribute();
252259
this._initWindowResizeListener();
253260
this._initContainerResizeObserver();
261+
254262
// Add slotchange listeners
255263
this.$.slot.addEventListener('slotchange', () => this._onSlotChange());
256264
this.$.tabsSlot.addEventListener('slotchange', e => this._onTabsSlotChange(e));
@@ -351,7 +359,9 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
351359
let tab = section.tab;
352360
if (!tab) {
353361
tab = document.createElement('vaadin-tab');
354-
this.$.tabs.appendChild(tab);
362+
Array.from(this.querySelectorAll('vaadin-tabs'))
363+
.filter(el => el.parentElement == this)[0]
364+
.appendChild(tab);
355365
this._initTab(tab, section);
356366
}
357367
section.removeEventListener('section-focus', this.onSectionFocus);
@@ -378,14 +388,17 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
378388
}
379389

380390
_onTabsSlotChange(e) {
381-
const slottedTabsElement = e.target.assignedElements().filter(el => el.tagName.toUpperCase() === 'VAADIN-TABS')[0];
391+
const slottedTabsElement = e.target
392+
.assignedElements()
393+
.filter(el => el.tagName.toUpperCase() === 'VAADIN-TABS' && !el.classList.contains('tabs'))[0];
394+
382395
if (slottedTabsElement) {
383-
const defaultTabs = Array.from(this.$.tabs.querySelectorAll('vaadin-tab'));
384-
defaultTabs.forEach(tab => slottedTabsElement.appendChild(tab));
385-
slottedTabsElement.setAttribute('part', 'tabs');
386-
this.$.tabs.remove();
387-
this.$.tabs = slottedTabsElement;
388-
Array.from(slottedTabsElement.querySelectorAll('vaadin-tab')).forEach(tab => {
396+
const defaultTabsElement = this.querySelector('#tabs');
397+
const slottedTabs = Array.from(slottedTabsElement.querySelectorAll('vaadin-tab'));
398+
slottedTabs.forEach(tab => defaultTabsElement.appendChild(tab));
399+
slottedTabsElement.remove();
400+
401+
Array.from(defaultTabsElement.querySelectorAll('vaadin-tab')).forEach(tab => {
389402
const section = this.querySelector(`[tab-id="${tab.id}"]`);
390403
if (section) this._initTab(tab, section);
391404
});
@@ -418,7 +431,7 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
418431

419432
_sortTabs() {
420433
this.sections.forEach(section => {
421-
if (section.navTab) this.$.tabs.appendChild(section.navTab);
434+
if (section.navTab) this.querySelector('vaadin-tabs').appendChild(section.navTab);
422435
});
423436
}
424437

@@ -513,7 +526,7 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
513526
threshold: 1
514527
}
515528
);
516-
observer.observe(this.$.tabs);
529+
observer.observe(this.querySelector('vaadin-tabs'));
517530
});
518531
}
519532

@@ -540,22 +553,27 @@ export class AnchorNavElement extends ElementMixin(ThemableMixin(PolymerElement)
540553
}
541554

542555
_selectTab(section) {
543-
this.$.tabs.querySelectorAll('vaadin-tab').forEach(tab => (tab.selected = false));
544-
const tab = section.tab;
545-
if (tab) tab.selected = true;
546-
// Horizontally scroll tabs when selected changes
547-
if (this.$.tabs.hasAttribute('overflow') && this.sections.length) {
548-
const leftOffset = this.$.tabs.root.querySelector('[part="back-button"]').clientWidth * 2;
549-
const topOffset = this.sections[0].offsetTop;
550-
const scrollRatio = (this.sections[this.selectedIndex].offsetTop - topOffset) / (this.scrollHeight - topOffset);
551-
const left = this.$.tabs.$.scroll.scrollWidth * scrollRatio;
552-
this.$.tabs.$.scroll.scrollTo({
553-
left: left && left - leftOffset,
554-
behavior: this._firstTabSelect ? 'auto' : 'smooth'
555-
});
556-
this._firstTabSelect = false;
556+
const tabs = this.querySelector('vaadin-tabs');
557+
558+
if (tabs) {
559+
tabs.querySelectorAll('vaadin-tab').forEach(tab => (tab.selected = false));
560+
561+
const tab = section.tab;
562+
if (tab) tab.selected = true;
563+
// Horizontally scroll tabs when selected changes
564+
if (tabs.hasAttribute('overflow') && this.sections.length) {
565+
const leftOffset = tabs.root.querySelector('[part="back-button"]').clientWidth * 2;
566+
const topOffset = this.sections[0].offsetTop;
567+
const scrollRatio = (this.sections[this.selectedIndex].offsetTop - topOffset) / (this.scrollHeight - topOffset);
568+
const left = tabs.$.scroll.scrollWidth * scrollRatio;
569+
tabs.$.scroll.scrollTo({
570+
left: left && left - leftOffset,
571+
behavior: this._firstTabSelect ? 'auto' : 'smooth'
572+
});
573+
this._firstTabSelect = false;
574+
}
575+
this.dispatchEvent(new CustomEvent('selected-changed', { detail: { index: this.selectedIndex, id: this.selectedId } }));
557576
}
558-
this.dispatchEvent(new CustomEvent('selected-changed', { detail: { index: this.selectedIndex, id: this.selectedId } }));
559577
}
560578

561579
_getSectionIndex(sectionId) {

0 commit comments

Comments
 (0)