emberjs / emberjs/ember.js

[Bug] declarative ShadowDOM is unable to have content rendered in to it

Open
#20,642 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
22.6k
Forks
4.2k
Avg merge
3d 12h
Merged PRs (30d)
15

Description

### 🐞 Describe the Bug

Reading and trying to apply https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#declaratively_with_html

Element is empty when I expect yielded content to be within it.

Related:
- https://github.com/emberjs/ember.js/issues/20641

### 🔬 Minimal Reproduction

An attempt at creating a shadow-dom-using component:
```glimmer-ts
import { setComponentTemplate } from '@ember/component';
import templateOnly from '@ember/component/template-only';
import { precompileTemplate } from '@ember/template-compilation';

import type { TOC } from '@ember/component/template-only';
import type { ComponentLike } from '@glint/template';

// index.html has the production-fingerprinted references to these links
// Ideally, we'd have some pre-processor scan everything for references to
// assets in public, but idk how to set that up
const getStyles = () => [...document.head.querySelectorAll('link')].map((link) => link.href);

const Shadow = setComponentTemplate(precompileTemplate(`

{{yield}}

`, { strictMode: true }), templateOnly('shadow', 'Shadow')) as ComponentLike<{
Element: null;
Args: {};
Blocks: { default: [] }
}>;

export const Shadowed: TOC<{
Element: HTMLDivElement;
Args: {
omitStyles?: boolean;
};
Blocks: { default: [] };
}> =



{{#unless @omitStyles}}
{{#each (getStyles) as |styleHref|}}

{{/each}}
{{/unless}}

{{yield}}


;

export default Shadowed;
```

Note that I'm manually using low-level APIs for the component, due to:
https://github.com/embroider-build/content-tag/pull/66/files

This is the test I'm using to debug:
```glimmer-ts
import { find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';

import { Shadowed } from 'limber/components/shadowed';

module('Rendering | ', function (hooks) {
setupRenderingTest(hooks);

test('it works', async function (assert) {
await render(

out of shadow


in shadow


);

await this.pauseTest();
assert.dom().hasText('out of shadow');
assert.dom().doesNotContainText('in shadow');
// assort.dom forgot that ShadowDom is a thing
// assert.dom(find('[data-shadow]')?.shadowRoot).hasText('in shadow');
assert.ok(find('template')?.shadowRoot?.textContent?.includes('in shadow'));
});
});
```

### 😕 Actual Behavior

![image](https://github.com/emberjs/ember.js/assets/199018/9835278e-73bd-4d8b-beae-16146744199f)

![image](https://github.com/emberjs/ember.js/assets/199018/7e1562bc-2354-4175-86dd-06cc5d857d62)

### 🤔 Expected Behavior

`in shadow` is rendered in to the ``

### 🌍 Environment

- Ember: - ember-source 5.5 and 5.6

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.