Skip to content

Commit 57e7e58

Browse files
johnjenkinsJohn Jenkins
and
John Jenkins
authored
fix(runtime): scoped: true slot fallback with forwarded slot (#6171)
* fix(runtime): `scoped: true` slot fallback with forwarded slot * chore: --------- Co-authored-by: John Jenkins <john.jenkins@nanoporetech.com>
1 parent 30f2a09 commit 57e7e58

File tree

5 files changed

+108
-9
lines changed

5 files changed

+108
-9
lines changed

src/runtime/slot-polyfill-utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const updateFallbackSlotVisibility = (elm: d.RenderNode) => {
2626
getHostSlotNodes(childNodes as any, (elm as HTMLElement).tagName).forEach((slotNode) => {
2727
if (slotNode.nodeType === NODE_TYPE.ElementNode && slotNode.tagName === 'SLOT-FB') {
2828
// this is a slot fallback node
29-
if (getSlotChildSiblings(slotNode, getSlotName(slotNode), false)?.length) {
29+
if (getSlotChildSiblings(slotNode, getSlotName(slotNode), false).length) {
3030
// has slotted nodes, hide fallback
3131
slotNode.hidden = true;
3232
} else {
@@ -108,7 +108,7 @@ export const getSlotChildSiblings = (slot: d.RenderNode, slotName: string, inclu
108108
let node = slot;
109109

110110
while ((node = node.nextSibling as any)) {
111-
if (getSlotName(node) === slotName) childNodes.push(node as any);
111+
if (getSlotName(node) === slotName && (includeSlot || !node['s-sr'])) childNodes.push(node as any);
112112
}
113113
return childNodes;
114114
};

src/runtime/test/hydrate-slot-fallback.spec.tsx

+7-7
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ describe('hydrate, slot fallback', () => {
443443
return (
444444
<article>
445445
<cmp-b>
446-
<slot>Fallback content parent - should not be hidden</slot>
446+
<slot>Fallback content parent - should be hidden</slot>
447447
</cmp-b>
448448
</article>
449449
);
@@ -458,7 +458,7 @@ describe('hydrate, slot fallback', () => {
458458
render() {
459459
return (
460460
<section>
461-
<slot>Fallback content child - should be hidden</slot>
461+
<slot>Fallback content child - should not be hidden</slot>
462462
</section>
463463
);
464464
}
@@ -479,13 +479,13 @@ describe('hydrate, slot fallback', () => {
479479
<!--r.2-->
480480
<!--o.1.2.-->
481481
<section c-id=\"2.0.0.0\">
482-
<slot-fb c-id=\"2.1.1.0\" hidden=\"\" s-sn=\"\">
482+
<slot-fb c-id=\"2.1.1.0\" s-sn=\"\">
483483
<!--t.2.2.2.0-->
484-
Fallback content child - should be hidden
484+
Fallback content child - should not be hidden
485485
</slot-fb>
486486
<slot-fb c-id=\"1.2.2.0\" s-sn=\"\">
487487
<!--t.1.3.3.0-->
488-
Fallback content parent - should not be hidden
488+
Fallback content parent - should be hidden
489489
</slot-fb>
490490
</section>
491491
</cmp-b>
@@ -507,12 +507,12 @@ describe('hydrate, slot fallback', () => {
507507
<mock:shadow-root>
508508
<section>
509509
<slot>
510-
Fallback content child - should be hidden
510+
Fallback content child - should not be hidden
511511
</slot>
512512
</section>
513513
</mock:shadow-root>
514514
<slot-fb class="sc-cmp-a">
515-
Fallback content parent - should not be hidden
515+
Fallback content parent - should be hidden
516516
</slot-fb>
517517
</cmp-b>
518518
</article>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Component, h, Host, Prop } from '@stencil/core';
2+
3+
@Component({
4+
tag: 'slot-forward-child-fallback',
5+
scoped: true,
6+
styles: `
7+
:host {
8+
display: block;
9+
}
10+
`,
11+
})
12+
export class ChildComponent {
13+
@Prop() label: string;
14+
15+
render() {
16+
return (
17+
<Host>
18+
<div>
19+
<slot name="label">{this.label}</slot>
20+
</div>
21+
</Host>
22+
);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { h } from '@stencil/core';
2+
import { render } from '@wdio/browser-runner/stencil';
3+
4+
describe('slot-fallback-with-forwarded-slot', () => {
5+
it('renders fallback via prop', async () => {
6+
// @ts-expect-error - wdio complaining about missing prop
7+
const { $root, root } = render({
8+
template: () => <slot-forward-root label="Slot fallback via property"></slot-forward-root>,
9+
});
10+
await $root.$('slot-fb');
11+
const fb: HTMLElement = document.querySelector('slot-fb');
12+
13+
expect(await $root.getText()).toBe('');
14+
expect(fb.textContent).toBe('Slot fallback via property');
15+
expect(fb.getAttribute('hidden')).toBe(null);
16+
expect(fb.hidden).toBe(false);
17+
18+
const p = document.createElement('p');
19+
p.textContent = 'Slot content via slot';
20+
p.slot = 'label';
21+
root.appendChild(p);
22+
23+
expect(await $root.getText()).toBe('Slot content via slot');
24+
expect(fb.getAttribute('hidden')).toBe('');
25+
expect(fb.hidden).toBe(true);
26+
});
27+
28+
it('should hide slot-fb elements when slotted content exists', async () => {
29+
// @ts-expect-error - wdio complaining about missing prop
30+
const { $root, root } = render({
31+
template: () => (
32+
<slot-forward-root label="Slot fallback via property">
33+
<div slot="label">Slot content via slot</div>
34+
</slot-forward-root>
35+
),
36+
});
37+
await $root.$('slot-fb');
38+
const fb: HTMLElement = document.querySelector('slot-fb');
39+
40+
expect(await $root.getText()).toBe('Slot content via slot');
41+
expect(fb.textContent).toBe('Slot fallback via property');
42+
expect(fb.getAttribute('hidden')).toBe('');
43+
expect(fb.hidden).toBe(true);
44+
45+
root.removeChild(root.childNodes[0]);
46+
47+
expect(await $root.getText()).toBe('');
48+
expect(fb.getAttribute('hidden')).toBe(null);
49+
expect(fb.hidden).toBe(false);
50+
});
51+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Component, h, Host, Prop } from '@stencil/core';
2+
3+
@Component({
4+
tag: 'slot-forward-root',
5+
scoped: true,
6+
styles: `
7+
:host {
8+
display: block;
9+
}
10+
`,
11+
})
12+
export class MyComponent {
13+
@Prop() label: string;
14+
15+
render() {
16+
return (
17+
<Host>
18+
<slot-forward-child-fallback label={this.label}>
19+
<slot name="label" />
20+
</slot-forward-child-fallback>
21+
</Host>
22+
);
23+
}
24+
}

0 commit comments

Comments
 (0)