solid icon indicating copy to clipboard operation
solid copied to clipboard

SVG fragments do not render when using html tagged template literals

Open daron81 opened this issue 2 years ago • 3 comments

Describe the bug

When using solid-js with tagged template literals (using the html tag from solid-js/html), components that contains SVG fragments do not render when added in the context of an SVG.

This behavior is different when using JSX, which works as expected. Here are the examples:

JSX: https://playground.solidjs.com/anonymous/f5e959de-1f30-4f7e-b6b5-277dd57e711d HTTL: https://playground.solidjs.com/anonymous/d388478e-c276-43a9-bf1b-e77d9110783b

Your Example Website or App

https://playground.solidjs.com/anonymous/d388478e-c276-43a9-bf1b-e77d9110783b

Steps to Reproduce the Bug or Issue

Expected behavior

Should render SVG fragments onto page.

Screenshots or Videos

No response

Platform

OS: Linux Browser: Firefox, Chrome

Additional context

No response

daron81 avatar Sep 10 '23 19:09 daron81

Yeah. I was never sure what to do about this one. We build the Dom by cloning and SVG that gets cloned needs to do so under an <svg> element. Partials won't work properly. In JSX we look ahead at compile time to hide an SVG element in templates and then remove it when inserted. Of course we could do that at runtime but it is extra processing and will increase the bundle size. But maybe thats ok as if one choises tagged template literals they've already accepted worse performance and larger bundle size.

In the past Ive seen libraries with svg tagged template literals, but maybe Lit has found a better way.

ryansolid avatar Sep 10 '23 20:09 ryansolid

In the past Ive seen libraries with svg tagged template literals, but maybe Lit has found a better way.

Thanks! Yes, I believe that's how Sinuous handles this problem. Seems like a reasonable solution.

daron81 avatar Sep 10 '23 21:09 daron81

I ran into this issue when using solidjs for a personal project. I found a hacky work around that got SVG fragments working for me. I wrote a svg tagged template literal that wraps the original template in an <svg> tag and then extracts its contents.

I'm not sure if it is a viable long-term solution, but I thought I'd share it in case anyone else runs into this issue and wants to be quickly unblocked.

Here is a working demo: https://playground.solidjs.com/anonymous/c12721fd-02c3-4518-82c7-c97f4e467630.

Implementation:


function svg(statics, ...args) {
    statics = [...statics];
    statics[0] = `<svg>${statics[0]}`;
    statics[statics.length - 1] = `${statics[statics.length - 1]}</svg>`;

    const wrapped = html(statics, ...args);

    const children = wrapped.children;
    if (children.length === 0) {
        return children[0];
    } else {
        // NOTE: IDK if the conversion to array is needed.
        return [...children];
    }
}

mmatena avatar Dec 26 '23 03:12 mmatena