From 78c28f1c54230d9998add0f6805e02efff05b31d Mon Sep 17 00:00:00 2001 From: Yigit Yuce Date: Thu, 25 Apr 2024 15:57:25 +0300 Subject: [PATCH] fix(runtime): add root scope id to the nested child as classname sass compiler adds root scope id to the nested child elements too, therefore nested element selectors are not working from the root component since the root scope id is not adding as classname to the nested children elements #5702 --- src/declarations/stencil-private.ts | 7 +++++++ src/runtime/vdom/vdom-render.ts | 10 ++++++++++ .../cmp-level-1.scss | 7 +++++++ .../cmp-level-1.tsx | 13 +++++++++++++ .../cmp-level-2.tsx | 16 ++++++++++++++++ .../cmp-level-3.scss | 3 +++ .../cmp-level-3.tsx | 17 +++++++++++++++++ .../scoped-id-in-nested-classname/cmp.test.tsx | 14 ++++++++++++++ 8 files changed, 87 insertions(+) create mode 100644 test/wdio/scoped-id-in-nested-classname/cmp-level-1.scss create mode 100644 test/wdio/scoped-id-in-nested-classname/cmp-level-1.tsx create mode 100644 test/wdio/scoped-id-in-nested-classname/cmp-level-2.tsx create mode 100644 test/wdio/scoped-id-in-nested-classname/cmp-level-3.scss create mode 100644 test/wdio/scoped-id-in-nested-classname/cmp-level-3.tsx create mode 100644 test/wdio/scoped-id-in-nested-classname/cmp.test.tsx diff --git a/src/declarations/stencil-private.ts b/src/declarations/stencil-private.ts index 730325ce660..e8cbc84d4fc 100644 --- a/src/declarations/stencil-private.ts +++ b/src/declarations/stencil-private.ts @@ -1099,6 +1099,13 @@ export interface HostElement extends HTMLElement { */ ['s-sc']?: string; + /** + * Root Scope Id + * The scope id of the root component when using scoped css encapsulation + * or using shadow dom but the browser doesn't support it + */ + ['s-rsc']?: string; + /** * Hot Module Replacement, dev mode only * diff --git a/src/runtime/vdom/vdom-render.ts b/src/runtime/vdom/vdom-render.ts index 9fb8449e6ab..ad31bf1c501 100644 --- a/src/runtime/vdom/vdom-render.ts +++ b/src/runtime/vdom/vdom-render.ts @@ -111,6 +111,16 @@ const createElm = (oldParentVNode: d.VNode, newParentVNode: d.VNode, childIndex: elm.classList.add((elm['s-si'] = scopeId)); } + if (BUILD.shadowDom || BUILD.scoped) { + const rootScopeId = + newParentVNode.$elm$?.['s-rsc'] || newParentVNode.$elm$?.['s-si'] || newParentVNode.$elm$?.['s-sc']; + + if (rootScopeId) { + elm['s-rsc'] = rootScopeId; + !elm.classList.contains(rootScopeId) && elm.classList.add(rootScopeId); + } + } + if (newVNode.$children$) { for (i = 0; i < newVNode.$children$.length; ++i) { // create the node diff --git a/test/wdio/scoped-id-in-nested-classname/cmp-level-1.scss b/test/wdio/scoped-id-in-nested-classname/cmp-level-1.scss new file mode 100644 index 00000000000..7164e48b3cd --- /dev/null +++ b/test/wdio/scoped-id-in-nested-classname/cmp-level-1.scss @@ -0,0 +1,7 @@ +:host { + cmp-level-2 { + cmp-level-3 { + padding: 32px; + } + } +} diff --git a/test/wdio/scoped-id-in-nested-classname/cmp-level-1.tsx b/test/wdio/scoped-id-in-nested-classname/cmp-level-1.tsx new file mode 100644 index 00000000000..7455647a059 --- /dev/null +++ b/test/wdio/scoped-id-in-nested-classname/cmp-level-1.tsx @@ -0,0 +1,13 @@ +import { Component, h } from '@stencil/core'; + +@Component({ + tag: 'cmp-level-1', + styleUrl: 'cmp-level-1.scss', + shadow: false, + scoped: true, +}) +export class CmpLevel1 { + render() { + return ; + } +} diff --git a/test/wdio/scoped-id-in-nested-classname/cmp-level-2.tsx b/test/wdio/scoped-id-in-nested-classname/cmp-level-2.tsx new file mode 100644 index 00000000000..ca967ac5705 --- /dev/null +++ b/test/wdio/scoped-id-in-nested-classname/cmp-level-2.tsx @@ -0,0 +1,16 @@ +import { Component, h } from '@stencil/core'; + +@Component({ + tag: 'cmp-level-2', + shadow: false, + scoped: true, +}) +export class CmpLevel2 { + render() { + return ( + + + + ); + } +} diff --git a/test/wdio/scoped-id-in-nested-classname/cmp-level-3.scss b/test/wdio/scoped-id-in-nested-classname/cmp-level-3.scss new file mode 100644 index 00000000000..5e36a5025f9 --- /dev/null +++ b/test/wdio/scoped-id-in-nested-classname/cmp-level-3.scss @@ -0,0 +1,3 @@ +:host { + padding: 8px; +} diff --git a/test/wdio/scoped-id-in-nested-classname/cmp-level-3.tsx b/test/wdio/scoped-id-in-nested-classname/cmp-level-3.tsx new file mode 100644 index 00000000000..35429c6071f --- /dev/null +++ b/test/wdio/scoped-id-in-nested-classname/cmp-level-3.tsx @@ -0,0 +1,17 @@ +import { Component, h } from '@stencil/core'; + +@Component({ + tag: 'cmp-level-3', + styleUrl: 'cmp-level-3.scss', + shadow: false, + scoped: true, +}) +export class CmpLevel3 { + render() { + return ( +
+ DEFAULT +
+ ); + } +} diff --git a/test/wdio/scoped-id-in-nested-classname/cmp.test.tsx b/test/wdio/scoped-id-in-nested-classname/cmp.test.tsx new file mode 100644 index 00000000000..171c2c7eff4 --- /dev/null +++ b/test/wdio/scoped-id-in-nested-classname/cmp.test.tsx @@ -0,0 +1,14 @@ +import { h } from '@stencil/core'; +import { render } from '@wdio/browser-runner/stencil'; + +describe('scope-id-in-nested-classname', function () { + beforeEach(() => { + render({ + template: () => , + }); + }); + + it('should have root scope id in the nested element as classname', async () => { + await expect($('cmp-level-3')).toHaveElementClass('sc-cmp-level-1'); + }); +});