Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(runtime): add root scope id to the nested child as classname #5704

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/declarations/stencil-private.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
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');
yigityuce marked this conversation as resolved.
Show resolved Hide resolved

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