Skip to content

Commit

Permalink
fix(runtime): add root scope id to the nested child as classname (#5704)
Browse files Browse the repository at this point in the history
* 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

* test: add additional test for css and add code documentation

* test: fix failing unit test due to the additional class

* chore: remove shadowDom condition regarding review
  • Loading branch information
yigityuce committed May 3, 2024
1 parent 44fcba1 commit b40ebb9
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/declarations/stencil-private.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,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
*
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/test/scoped.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe('scoped', () => {
<cmp-a class="hydrated sc-cmp-a-h sc-cmp-a-s">
<cmp-b class="hydrated sc-cmp-a sc-cmp-b-h sc-cmp-b-s">
<!---->
<div class="sc-cmp-b sc-cmp-b-s">
<div class="sc-cmp-a sc-cmp-b sc-cmp-b-s">
<span class="sc-cmp-a">
Hola
</span>
Expand Down
13 changes: 13 additions & 0 deletions src/runtime/vdom/vdom-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ const createElm = (oldParentVNode: d.VNode, newParentVNode: d.VNode, childIndex:
elm.classList.add((elm['s-si'] = scopeId));
}

if (BUILD.scoped) {
// to be able to style the deep nested scoped component from the root component,
// root component's scope id needs to be added to the child nodes since sass compiler
// adds scope id to the nested selectors during compilation phase
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
Expand Down
7 changes: 7 additions & 0 deletions test/wdio/scoped-id-in-nested-classname/cmp-level-1.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:host {
cmp-level-2 {
cmp-level-3 {
padding: 32px;
}
}
}
13 changes: 13 additions & 0 deletions test/wdio/scoped-id-in-nested-classname/cmp-level-1.tsx
Original file line number Diff line number Diff line change
@@ -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 <cmp-level-2></cmp-level-2>;
}
}
16 changes: 16 additions & 0 deletions test/wdio/scoped-id-in-nested-classname/cmp-level-2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, h } from '@stencil/core';

@Component({
tag: 'cmp-level-2',
shadow: false,
scoped: true,
})
export class CmpLevel2 {
render() {
return (
<cmp-level-3>
<slot />
</cmp-level-3>
);
}
}
3 changes: 3 additions & 0 deletions test/wdio/scoped-id-in-nested-classname/cmp-level-3.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
padding: 8px;
}
17 changes: 17 additions & 0 deletions test/wdio/scoped-id-in-nested-classname/cmp-level-3.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<slot>DEFAULT</slot>
</div>
);
}
}
17 changes: 17 additions & 0 deletions test/wdio/scoped-id-in-nested-classname/cmp.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { h } from '@stencil/core';
import { render } from '@wdio/browser-runner/stencil';

describe('scope-id-in-nested-classname', function () {
beforeEach(() => {
render({
template: () => <cmp-level-1></cmp-level-1>,
});
});

it('should have root scope id in the nested element as classname', async () => {
await expect($('cmp-level-3')).toHaveElementClass('sc-cmp-level-1');

const appliedCss = await (await $('cmp-level-3')).getCSSProperty('padding');
await expect(appliedCss.parsed.value).toBe(32);
});
});

0 comments on commit b40ebb9

Please sign in to comment.