Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow CSS style setters for SVG root elements #171

Open
raquo opened this issue Sep 14, 2024 · 0 comments
Open

Allow CSS style setters for SVG root elements #171

raquo opened this issue Sep 14, 2024 · 0 comments

Comments

@raquo
Copy link
Owner

raquo commented Sep 14, 2024

Suppose you have an svg element like this in your HTML:

<svg viewBox="0 0 300 100" xmlns="http://www.w3.org/2000/svg" stroke="red" fill="grey">
  <circle cx="50" cy="50" r="40"></circle>
  <circle cx="150" cy="50" r="4"></circle>
  <svg viewBox="0 0 10 10" x="200" width="100">
    <circle cx="5" cy="5" r="4"></circle>
  </svg>
</svg>

In raw JS, you can mostly treat the outer element as an HTML element – you can set CSS properties like el.style.background, el.style.border, and el.style.position, and they will work. However, setting these properties does not work for any other SVG elements in this example – neither nor the inner element.

Technically, all svg elements, including both and , are instances of SVGElement in JS. Both the inner and outer elements are specifically instances of SVGSVGElement.

Currently Laminar only supports setting CSS properties on HTML elements. Ideally, we would support that for both HTML elements, and root (outer) elements, however the types for that are not possible, since JS does not differentiate between outer and inner elements. This would be an acceptable tradeoff for me, as it is similar to how we don't enforce the availability rules for html attributes, e.g. Laminar lets you set value attribute on a div element, even though it does not make sense – the full HTML rules are just too complex to effectively encode in Scala types.

The next best thing is to support CSS props for Html elements and any element, meaning, any SVGSVGElement – then only inner elements would be incorrectly typed (allowing setting CSS props that do nothing).

The least best thing is to support CSS properties for all JS elements, including all HTML elements and all SVG elements (and all MathML and XUL elements, but let's ignore those for now). This would be simpler, but it would let users try to set CSS properties on SVG elements like , which would have no effect.

TODO

Figure out how to add CSS support specifically to SVGSVGElement without introducing implicits / typeclasses. I just don't want Laminar's primary API to be complicated by such things, nor do I want the compile time penalty for many implicit search calls.

Perhaps we should offer a noop implicit conversion from StyleSetter (KeySetter[StyleProp[_], String, ReactiveHtmlElement.Base]) to KeySetter[StyleProp[_], String, ReactiveSvgElement[dom.SVGSVGElement]]. the conversion can be noop, even though the source assumes HtmlElement, because the style setting JS API of HTML and SVG elements is source compatible (even if it does not have a common nominal type... oh the pleasures of JS structural typing).

To keep user-facing types simple, we would rename StyleSetter to HtmlStyleSetter, and the new type would be SvgStyleSetter.

This approach will let us keep a common Key-setting API in Laminar between CSS style props, JS props, HTML attributes, etc. It is getting increasingly hard to wrangle CSS style setters into this API, but we will keep doing that while we can, to keep the source simple for end users. We already do somewhat similar shenanigans with derivedStyleIntToDouble, styleEncoderIntToDouble implicits, for similar purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant