solidjs / solid

A declarative, efficient, and flexible JavaScript library for building user interfaces.
https://solidjs.com
MIT License
31.74k stars 898 forks source link

SVG fragments do not render when using html tagged template literals #1879

Open offsounder opened 10 months ago

offsounder commented 10 months ago

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

ryansolid commented 10 months ago

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.

offsounder commented 10 months ago

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.

mmatena commented 6 months ago

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];
    }
}