Skip to content

πŸ“¦ Feature Proposal: Slotted Component Self-awarenessΒ #48

@nitipit

Description

@nitipit

🎯 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()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions