diff --git a/.changeset/great-pumas-rush.md b/.changeset/great-pumas-rush.md new file mode 100644 index 000000000..033efd1ae --- /dev/null +++ b/.changeset/great-pumas-rush.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +[core] rerender direct host child with right slot attr when root is switched diff --git a/packages/ui/components/core/src/SlotMixin.js b/packages/ui/components/core/src/SlotMixin.js index 0acafb5e9..d56d936c5 100644 --- a/packages/ui/components/core/src/SlotMixin.js +++ b/packages/ui/components/core/src/SlotMixin.js @@ -182,6 +182,21 @@ const SlotMixinImplementation = superclass => // Providing all options breaks Safari: we keep host and creationScope const { creationScope, host } = this.renderOptions; render(template, rerenderTarget, { creationScope, host, renderBefore }); + + // Assume we had this config: + // `'my-slot': () => ({ template: myBool ? html`
` : html``, renderAsDirectHostChild: true })` + // If myBool started as true, would be rendered in first render above, a slot would be applied, + // resulting in + // However, when myBool changes to false, the would be rendered as root instead... + // We need to make sure that this "replaced root" gets the slot applied as well => + const isRerenderingRootOfTemplate = + renderAsDirectHostChild && + renderBefore.previousElementSibling && + !renderBefore.previousElementSibling.slot; + + if (isRerenderingRootOfTemplate) { + renderBefore.previousElementSibling.slot = slotName; + } } /** diff --git a/packages/ui/components/core/test/SlotMixin.test.js b/packages/ui/components/core/test/SlotMixin.test.js index c6bb70779..2f664ae05 100644 --- a/packages/ui/components/core/test/SlotMixin.test.js +++ b/packages/ui/components/core/test/SlotMixin.test.js @@ -345,6 +345,56 @@ describe('SlotMixin', () => { expect(isActiveElement(el._focusableNode._buttonNode, { deep: true })).to.be.true; }); + it('allows for switching template root in slot as a direct child', async () => { + const tagName = defineCE( + // @ts-expect-error + class extends SlotMixin(LitElement) { + static properties = { isSwitched: Boolean }; + + constructor() { + super(); + this.isSwitched = false; + } + + get slots() { + return { + ...super.slots, + 'my-root-switcher-node': () => ({ + template: this.isSwitched + ? html`` + : html` `, + renderAsDirectHostChild: true, + }), + }; + } + + render() { + return html`