Skip to content

Commit

Permalink
fix(runtime): merge styles within ShadowRoot into a single node (#6014)
Browse files Browse the repository at this point in the history
* fix(runtime): merge shadow root styles into into a single node

* fix build

* change order how styles are applied

* prettier
  • Loading branch information
christian-bromann authored Oct 8, 2024
1 parent 1564b7a commit 61f90b0
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 5 deletions.
17 changes: 14 additions & 3 deletions src/runtime/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,21 @@ export const addStyle = (styleContainerNode: any, cmpMeta: d.ComponentRuntimeMet
(styleContainerNode as HTMLElement).insertBefore(styleElm, referenceNode);
} else if ('host' in styleContainerNode) {
/**
* if a scoped component is used within a shadow root, we want to insert the styles
* at the beginning of the shadow root node
* If a scoped component is used within a shadow root, we want to insert the styles
* at the beginning of the shadow root node.
*
* However if there is already a style node in the ShadowRoot, we just append
* the styles to the existing node.
*
* Note: order of how styles are applied is important. The new style node
* should be inserted before the existing style node.
*/
(styleContainerNode as HTMLElement).prepend(styleElm);
const existingStyleContainer = styleContainerNode.querySelector('style');
if (existingStyleContainer) {
existingStyleContainer.innerHTML = style + existingStyleContainer.innerHTML;
} else {
(styleContainerNode as HTMLElement).prepend(styleElm);
}
} else {
styleContainerNode.append(styleElm);
}
Expand Down
13 changes: 13 additions & 0 deletions test/end-to-end/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ export namespace Components {
}
interface NestedCmpParent {
}
interface NestedScopeCmp {
}
interface PathAliasCmp {
}
interface PrerenderCmp {
Expand Down Expand Up @@ -350,6 +352,12 @@ declare global {
prototype: HTMLNestedCmpParentElement;
new (): HTMLNestedCmpParentElement;
};
interface HTMLNestedScopeCmpElement extends Components.NestedScopeCmp, HTMLStencilElement {
}
var HTMLNestedScopeCmpElement: {
prototype: HTMLNestedScopeCmpElement;
new (): HTMLNestedScopeCmpElement;
};
interface HTMLPathAliasCmpElement extends Components.PathAliasCmp, HTMLStencilElement {
}
var HTMLPathAliasCmpElement: {
Expand Down Expand Up @@ -445,6 +453,7 @@ declare global {
"method-cmp": HTMLMethodCmpElement;
"nested-cmp-child": HTMLNestedCmpChildElement;
"nested-cmp-parent": HTMLNestedCmpParentElement;
"nested-scope-cmp": HTMLNestedScopeCmpElement;
"path-alias-cmp": HTMLPathAliasCmpElement;
"prerender-cmp": HTMLPrerenderCmpElement;
"prop-cmp": HTMLPropCmpElement;
Expand Down Expand Up @@ -529,6 +538,8 @@ declare namespace LocalJSX {
}
interface NestedCmpParent {
}
interface NestedScopeCmp {
}
interface PathAliasCmp {
}
interface PrerenderCmp {
Expand Down Expand Up @@ -588,6 +599,7 @@ declare namespace LocalJSX {
"method-cmp": MethodCmp;
"nested-cmp-child": NestedCmpChild;
"nested-cmp-parent": NestedCmpParent;
"nested-scope-cmp": NestedScopeCmp;
"path-alias-cmp": PathAliasCmp;
"prerender-cmp": PrerenderCmp;
"prop-cmp": PropCmp;
Expand Down Expand Up @@ -635,6 +647,7 @@ declare module "@stencil/core" {
"method-cmp": LocalJSX.MethodCmp & JSXBase.HTMLAttributes<HTMLMethodCmpElement>;
"nested-cmp-child": LocalJSX.NestedCmpChild & JSXBase.HTMLAttributes<HTMLNestedCmpChildElement>;
"nested-cmp-parent": LocalJSX.NestedCmpParent & JSXBase.HTMLAttributes<HTMLNestedCmpParentElement>;
"nested-scope-cmp": LocalJSX.NestedScopeCmp & JSXBase.HTMLAttributes<HTMLNestedScopeCmpElement>;
"path-alias-cmp": LocalJSX.PathAliasCmp & JSXBase.HTMLAttributes<HTMLPathAliasCmpElement>;
"prerender-cmp": LocalJSX.PrerenderCmp & JSXBase.HTMLAttributes<HTMLPrerenderCmpElement>;
"prop-cmp": LocalJSX.PropCmp & JSXBase.HTMLAttributes<HTMLPropCmpElement>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
display: block;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, h } from '@stencil/core';

@Component({
tag: 'nested-cmp-child',
styleUrl: `nested-child-cmp.css`,
shadow: true,
})
export class NestedCmpChild {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
color: green;
}
16 changes: 16 additions & 0 deletions test/end-to-end/src/declarative-shadow-dom/nested-scope-cmp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, h } from '@stencil/core';

@Component({
tag: 'nested-scope-cmp',
styleUrl: 'nested-scope-cmp.css',
scoped: true,
})
export class NestedScopeCmp {
render() {
return (
<div class="some-scope-class">
<slot></slot>
</div>
);
}
}
3 changes: 3 additions & 0 deletions test/end-to-end/src/declarative-shadow-dom/parent-cmp.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
display: inline-block;
}
5 changes: 4 additions & 1 deletion test/end-to-end/src/declarative-shadow-dom/parent-cmp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { Component, h } from '@stencil/core';
@Component({
tag: 'nested-cmp-parent',
shadow: true,
styleUrl: 'parent-cmp.css',
})
export class NestedCmpParent {
render() {
return (
<div class="some-class">
<slot></slot>
<nested-scope-cmp>
<slot></slot>
</nested-scope-cmp>
</div>
);
}
Expand Down
15 changes: 14 additions & 1 deletion test/end-to-end/src/declarative-shadow-dom/test.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,26 @@ describe('renderToString', () => {
);
expect(html).toBe(`<nested-cmp-parent custom-hydrate-flag="" s-id="29">
<template shadowrootmode="open">
<style>
.sc-nested-scope-cmp-h{color:green}:host{display:inline-block}
</style>
<div c-id="29.0.0.0" class="some-class">
<slot c-id="29.1.1.0"></slot>
<nested-scope-cmp c-id="29.1.1.0" class="sc-nested-scope-cmp-h sc-nested-scope-cmp-s" custom-hydrate-flag="" s-id="31">
<!--r.31-->
<!--o.29.2.c-->
<div c-id="31.0.0.0" class="sc-nested-scope-cmp sc-nested-scope-cmp-s some-scope-class">
<!--s.31.1.1.0.-->
<slot c-id="29.2.2.0" class="sc-nested-scope-cmp"></slot>
</div>
</nested-scope-cmp>
</div>
</template>
<!--r.29-->
<nested-cmp-child custom-hydrate-flag="" s-id="30">
<template shadowrootmode="open">
<style>
:host{display:block}
</style>
<div c-id="30.0.0.0" class="some-other-class">
<slot c-id="30.1.1.0"></slot>
</div>
Expand Down

0 comments on commit 61f90b0

Please sign in to comment.