S
SolidJS17mo ago
urish

SVG A elements not created correctly

When using an <a> element with <Show> or <For> inside an inline SVG element, we get the namespace wrong. Example:
<svg height="100" width="100" style={{ background: "#000" }}>
<Show when={true}>
<a href="https://example.org">
<rect fill="red" x="25" y="25" height="50" width="50" />
</a>
</Show>
</svg>
<svg height="100" width="100" style={{ background: "#000" }}>
<Show when={true}>
<a href="https://example.org">
<rect fill="red" x="25" y="25" height="50" width="50" />
</a>
</Show>
</svg>
The namespaceUri of the "a" element is "http://www.w3.org/1999/xhtml", so it breaks the rendering of the SVG. The desired namespaceUri would be "http://www.w3.org/2000/svg". Here's a code sandbox showing this issue in action: https://codesandbox.io/s/flamboyant-euclid-qy5hq4?file=/index.js:402-651 There are two copies of the same <svg> element, the first one does not use <Show> and renders correctly. The second one uses <Show>, and does not render the content of the <a> element, as the namespace of the <a> element is incorrect. I'd appreciate any pointers on how to fix this!
urish
CodeSandbox
flamboyant-euclid-qy5hq4 - CodeSandbox
flamboyant-euclid-qy5hq4 by urish using babel-preset-solid, solid-js
9 Replies
mdynnl
mdynnl17mo ago
as a could be both html and svg element, we can't really statically analyze what namespace it'll be in and defaults to html. you could workaround this by wrapping with <svg>
mattasia
mattasia17mo ago
Tangently, does typescript provide any JSX typing that you could say when a sibling of <svg> this tag applies, I ask, because I've seen tags behave differently in terms of required props in different circumstances, for example <Field> of modular forms is smart enough (TS typing i guess) to make the 'of' prop optional if a child of <Form>
mdynnl
mdynnl17mo ago
i think that's only possible if you somehow inferred it from somewhere, which you can't for global/module types i just took a glance of modular forms docs
import { createForm } from '@modular-forms/solid';

type LoginForm = {
email: string;
password: string;
};

export default function App() {
const [loginForm, { Form, Field, FieldArray }] = createForm<LoginForm>();
}
import { createForm } from '@modular-forms/solid';

type LoginForm = {
email: string;
password: string;
};

export default function App() {
const [loginForm, { Form, Field, FieldArray }] = createForm<LoginForm>();
}
REEEEE
REEEEE17mo ago
Wrap the a in a foreignObject tag
mdynnl
mdynnl17mo ago
Form, Field, etc's types are inferred from createForm<LoginForm>() but these can't be inferred
import { createFormStore, Form, FormStore, Field } from '@modular-forms/solid';
import { createFormStore, Form, FormStore, Field } from '@modular-forms/solid';
mattasia
mattasia17mo ago
ah I see, it's a different Field return from createForm than imported, ah that makes sense
urish
urishOP17mo ago
Thanks for the suggestion! The <svg> workaround works - but it does create an extra <svg> in DOM, around the <a> tag. I'm not yet sure if that would be a problem - it's definitely better than nothing, though, I wish there was a way to somehow tell what namespace the tag would be in. I tried adding a xmlns="http://www.w3.org/2000/svg" to the <a> element, but unfortunately, this didn't do the trick.
REEEEE
REEEEE17mo ago
Try this maybe?
urish
urishOP17mo ago
Tried that too, but unfortunately, it didn't work
Want results from more Discord servers?
Add your server