preactjs / preact-custom-element

Wrap your component up as a custom element
MIT License
366 stars 53 forks source link

"Children" not replaced on mount when shadow DOM is disabled #41

Open mbohgard opened 4 years ago

mbohgard commented 4 years ago

We have a design system with components written in React. I was thinking of rendering those with preact compat and then wrapping those in preact-custom-element to be able to use the components in a Vue/Angular or vanilla js app. I get a few issues tho.

  1. Children of the custom element in html is not replaced when the Preact component mounts. I tried the "solution" to this by @donpark in this issue thread but I can't just switch out {children} for <slot /> if I want to keep compatibility with React and also it didn't work when I tried it. Using a shadow DOM here, passing shadow: true to the register function of preact-custom-element works but since I'm using Emotion as a CSS-in-JS I need the global styling support. There are ways of controlling where Emotion inserts styles and use shadow DOM here but that would probably mess with other teams implementation as of now. I would like it to be able to use this lib without enabling shadow DOM.

2. I can't get property bindings to work at all as demonstrated in this PR. Attributes work fine, but properties doesn't end up as props on the Preact component (whether shadow DOM is used or not).

All the issues is demonstrated in this sandbox.

mbohgard commented 4 years ago

@marvinhagemeister Do you have any ideas perhaps?

marvinhagemeister commented 4 years ago

Woa, it's the prettiest bug repro we've received in any Preact repositories by a long shot! Love the animation effect 👍

Sounds like preact-custom-element needs the mentioned features to satisfy the described use case. Wrapping children automatically with a slot is one of those and the other is getting slot wrapping to work without shadow DOM.

I can't get property bindings to work at all as demonstrated in this PR. Attributes work fine, but properties doesn't end up as props on the Preact component (whether shadow DOM is used or not).

How does it show up in the linked sandbox? Whenever I click any of the buttons the number increases and the animation looks correct to me. - nvm, I see the issue now :+1:

wbern commented 4 years ago

@mbohgard given our current org developments, what do you think of this issue now?

mbohgard commented 4 years ago

@marvinhagemeister Hah, thanks for the design compliments. This was used internally for a demonstration for higher ups. Had to be somewhat pretty to sell the idea ;) Also thanks for the super fast work of getting property bindings to work! 👏

@wbern Yes the second part of this issue(s) is solved. There is still the issue that remains when having shadow DOM disabled (issue title updated). Personally, we can work around this, but maybe it should be mentioned in the docs what limitations there are while having shadow DOM disabled if there is no solution coming.

paull39 commented 4 years ago

@mbohgard

Hey!

Do you mind to share a snippet of your workaround?

const foo: FunctionalComponent<any> = (props) => {
    return (
        <h1>My Heading</h1>
        <div class="SomeSpecialContaienrWithAriaStuff">{props.children}</div>
    )
}

// register as CustomElement
register(foo, "my-foo");

Serverside Rendered HTML:

<my-foo>
    <some-special-custom-element>
        Lorem doFoo
    </some-special-custom-element>
</my-foo>

The Result with those snippets is for me:

<my-foo>
        <h1>My Heading</h1>
        <div class="SomeSpecialContaienrWithAriaStuff"></div>
        <some-special-custom-element>
            Lorem doFoo
        </some-special-custom-element>
</my-foo>

Preferred Solution:

<my-foo>
        <h1>My Heading</h1>
        <div class="SomeSpecialContaienrWithAriaStuff">
             <some-special-custom-element>
                Lorem doFoo
             </some-special-custom-element>
         </div>
</my-foo>

If this is the atomic problem, please tell me i really would like to dig into this nice project!

Nicolab commented 3 years ago

I have the same issue. @paull39 (and other) do you have found a solution?

Nicolab commented 3 years ago

I found a solution, this package works well: https://github.com/jhukdev/preactement

finalclass commented 2 years ago

For me this still does not work. If you change shadow to false in this example: https://codesandbox.io/s/preact-custom-element-rendering-content-issue-forked-38xpc?file=/src/index.js it stops working as expected.

mufaddalmw commented 1 year ago

I found a solution, this package works well: https://github.com/jhukdev/preactement

there is issue in this library, please check https://github.com/jahilldev/component-elements/issues/26 it doesn't support nested custom-elements on DOM