Re: [w3c/webcomponents] idea: Allow light DOM to delegate styles/behavior to shadow DOM (#883)

Ah

> Sure thing, what I'm thinking is that a light DOM author might want to give control to part of its markup to some parent. Imagine this being like a design system implementation:
> 
> ```js
> // ... elided ...
> customElements.define('x-ds', DesignSystem);
> ```
> 
> then in the HTML
> 
> ```
> <x-ds>
>     ...
>     <input id="whatever" name="whatever" control="ds-input">
> </x-ds>
> ```

Hah! Funny! That's very similar to what I wanted to do and asked about on StackOverflow yesterday: https://stackoverflow.com/questions/62842418

The example from that question is

```html
<div>
  <p><span>test</span></p>
  <p><span>test</span></p>
  <p><span>test</span></p>
  <p><span>test</span></p>
  <p><span>test</span></p>
</div>

<script>
const d = document.querySelector('div')
const r = d.attachShadow({mode: 'open'})

r.innerHTML = `
  <style>
    /* This doesn't work as I was hoping: */
    ::slotted(p) span {
      border: 1px solid deeppink;
    }
    
    /* This doesn't work (and I wouldn't expect it to), but I tried it anyways: */
    ::slotted(span) {
      border: 1px solid deeppink;
    }
    
    /* This doesn't work either: */
    :host span {
      border: 1px solid deeppink;
    }
    
    /* This works, but not what I'm trying to do. */
    ::slotted(p) {
      background: #f9f9f9
    }
  </style>
  <slot></slot>
`
</script>
```

But you can also imagine how it would work with a custom element that creates its own `ShadowRoot`.

I think I like the `::slotted(*) .foo` method that I attempted in my SO question (f.e. in your last example it may be `::slotted(*) .close-btn`) because it doesn't add a new pseudo element in CSS (though honestly I don't know that "pseudo element" is even a good description of what `slotted` is) and doesn't add a new attribute in the HTML (the `control` attribute in your example).

Here's what your example would look like if what I was asking about worked (as one would intuitively expect it to):

```js
const sheet = new CSSStyleSheet();
sheet.replace(`
  ::slotted(*) .ds-input {
    border: 2px solid tomato;
    background: gainsboro;
  }
`);
class DesignSystem extends HTMLElement {
  constructor() {
    super();
    const root = this.attachShadow({ mode: 'open' });
    root.adoptedStyleSheets = [sheet];
    root.innerHTML = `<slot></slot>`;
    // other stuff maybe
  }
}

customElements.define('x-ds', DesignSystem);
```

and the user would write

```html
<x-ds>
  <h1>Whatever</h1>

  <form>
    <label for="whatever">
    <input id="whatever" name="whatever" class="ds-input">
  </form>
</x-ds>
```

This is interesting because the user can write familiar markup using `class` attributes like they already do.


What I find unintuitive is why `::slotted(*) .ds-input` does not work. One would expect that `::slotted(.foo)` targets some set of elements with class `foo`, and therefore one would expect that `::slotted(.foo) .bar` would target any elements with class `bar` that are descendants of the elements targeted by `::slotted(.foo)`.

Your idea with `this.controls['close-btn']` would be convenient, but I believe this should also be achieved with the shadow root like follows (extending from my `::slotted` selector idea):

```js
this.shadowRoot.querySelector('::slotted(*) .close-btn').addEventListener('click', this.close.bind(this));
```

I think these things should be on `shadowRoot` for encapsulation. For example, your idea would be

```js
this.shadowRoot.controls['close-btn'].addEventListener('click', this.close.bind(this));
```

This is especially important because if the shadow root mode is `closed`, then someone could still run a querySelector or access controls on the custom element. I think it's good to just keep it on `shadowRoot`.

`ShadowRoot` instances already have the `querySelector` method, so we could allow it to query for things like `::slotted(.foo) .bar` without adding any new properties.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/883#issuecomment-657141777

Received on Saturday, 11 July 2020 22:46:04 UTC