S
SolidJS2y 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
mdynnl2y 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
mattasia2y 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
mdynnl2y 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
REEEEE2y ago
Wrap the a in a foreignObject tag
mdynnl
mdynnl2y 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
mattasia2y ago
ah I see, it's a different Field return from createForm than imported, ah that makes sense
urish
urishOP2y 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
REEEEE2y ago
Try this maybe?
urish
urishOP2y ago
Tried that too, but unfortunately, it didn't work

Did you find this page helpful?