π― Goal
Enable Adapter to detect when they are slotted into a Shadow DOM β including initial projection and later re-slotting β without needing coordination from the shadow host.
This pattern is designed to be:
- β
Self-contained (no external communication)
- β
Efficient (no polling loops)
- β
Compatible with native Shadow DOM + slots
- β
Safe for large numbers of components
π§ͺ Use Case
Inside a component like <el-shadow-host>:
<el-shadow-host>
<el-bluecard></el-bluecard>
</el-shadow-host>
We want <el-bluecard> to:
- Detect when itβs slotted (projected into a shadow root)
- React to changes in the
slot attribute
- Optionally apply logic or styling depending on its slot context
β
Final Implementation Pattern
Shadow Host (simple slotting):
class ShadowHost extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' }).innerHTML = `<slot></slot>`;
}
}
Slotted Component
class Adapter extends HTMLElement {
constructor() {
super();
this._slotObserver = null;
}
connectedCallback() {
// Observe changes to the slot attribute (reslotting)
this._slotObserver = new MutationObserver(() => {
if (this.getRootNode() instanceof ShadowRoot) {
this._attachCSS();
}
});
this._slotObserver.observe(this, {
attributes: true,
attributeFilter: ['slot'],
});
// Initial check (after slot projection completes)
requestAnimationFrame(() => {
if (this.getRootNode() instanceof ShadowRoot) {
this._attachCSS();
}
});
}
disconnectedCallback() {
this._slotObserver?.disconnect();
}
_attachCSS() {
// add css to `shadowroot.adaptedStyleSheets`
}
}
π‘ Key Design Notes
| Feature |
Implementation |
| Detect first slot projection |
getRootNode() inside requestAnimationFrame() |
| Detect slot attribute change |
MutationObserver on slot attribute |
| Avoid polling or loops |
One-time check only |
| Cleanup |
Disconnect observer in disconnectedCallback() |
π― Goal
Enable Adapter to detect when they are slotted into a Shadow DOM β including initial projection and later re-slotting β without needing coordination from the shadow host.
This pattern is designed to be:
π§ͺ Use Case
Inside a component like
<el-shadow-host>:We want
<el-bluecard>to:slotattributeβ Final Implementation Pattern
Shadow Host (simple slotting):
Slotted Component
π‘ Key Design Notes
getRootNode()insiderequestAnimationFrame()MutationObserveronslotattributedisconnectedCallback()