Re: [w3c/webcomponents] Make custom elements w/ shadowRoot { display: contents } by default (#723)

> finding it a little bit annoying to apply that to a lot of my components

We can make it re-usable as a class factory mixin, f.e.

```js
function DisplayContents(BaseClass) {
  BaseClass = BaseClass || HTMLElement
  
  return class DisplayContents extends BaseClass {
    constructor () {
      super()
      // apply the style somehow
      this.style.display = 'contents'
    }
  }
}
```

Then, if there's an existing custom element class,

```js
class CubeLayout extends HTMLElement { ... }
```

it can be applied to the class:

```js
class CubeLayout extends DisplayContents(HTMLElement) { ... }
```

The styling might be applied in a different way, but at least we can abstract it into a single place.

> an alternative, like React's Fragments (see trusktr's comment), is worth exploring in the future.

Hmmm. The thing that makes Fragments possible in React is that in React there is a whole separate tree from the DOM, and React's internal tree holds a reference to an actual fragment in this internal render tree. Then based on this internal tree it knows how to create a new tree (the DOM) where the new tree does not contain the Fragment in the structure.

But Custom Elements, on the other hand, operate on a single tree (the DOM), so there isn't this opportunity to map one tree structure to another tree structure (that we've thought of yet at least). 

So far at least, `display:contents` with the current single-tree mechanic of the DOM seems like the best way to get elements out of the way in terms of how the DOM renders and functions. Still though, the container elements will still be in the DOM as actual references in the tree.

There's the "composed tree" concept that the HTML engine maps to from the regular DOM, based on the composition of shadow roots, but outside of the HTML engine we don't really have access to that tree, we can only infer it from looking at open shadow roots (or if they are closed, monkey patching `attachShadow` to keep track of all shadow roots created in the application).

I'm sort of going off on a tangent now, but elements that are `display:contents` are essentially gone from the composed tree, if we factor this styling in. However these elements are still observed in `parent` and `children` properties of the elements that are next to the `display:contents` elements in the tree. We could traverse the composed tree factoring in shadow roots and elements that are `contents`, then come up with out own tree, and from this, we could perhaps do cool things like render to WebGL (think of something like A-Frame which renders to WebGL, but A-Frame is currently not considering the ShadowDOM composed tree, and therefore it completely breaks if you try to use ShadowDOM with A-Frame).

I've been thinking about this for a while, and have done some initial work over at [infamous](https://github.com/trusktr/infamous/) which can render to WebGL as well (not trying to advertise here, just like to share what I've been thinking around web components). I've put in place some features that allow it to track the composed tree, and soon this will map to the Three.js rendering so that making ShadowDOM-based Custom Elements will compose well together. It will give component authors the ability to compose and nest elements inside of each other to make these components highly-reusable. Imagine, for example, layouts designed for 3D space, that work based on distributing their content into slots. This is currently not possible with A-Frame (though you can just use React/Angular/Vue for that, but then you're sacrificing portability of you components by limiting them to a single framework).

-- 
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/723#issuecomment-358822000

Received on Thursday, 18 January 2018 23:57:58 UTC