-
-
Notifications
You must be signed in to change notification settings - Fork 28
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
Add info about supported tags to props/attrs #96
Comments
Before you go down this road, keep in mind that an attribute's applicability is not just based on the element type, it can require all kinds of complex conditions that are very hard to express in types, e.g. see the example here: https://github.com/raquo/scala-dom-types#reasonably-precise-types Also, I'm not sure how knowing which element types an attribute applies to will help you de-conflict two
It has the same name and expects the same value type (string), they serve approximately the same purpose, that's about as "same" as it gets in the soup that is DOM. The native JS call to set the label attribute is the same in both cases. If this is just for web components, then you can define special attribute types specific to that web component, without complicating the types of regular HTML attributes. In Laminar the canonical approach is to scope the web component's attributes to the web component itself, and access them as properties, e.g. like so: Button(
_.id := "myButton",
_.label <-- actionVar.signal,
...
) Which is just syntax sugar for: Button(
Button.id := "myButton",
Button.label <-- actionVar.signal,
...
) (from https://laminar.dev/examples/web-components, but Antoine's Laminar SAP UI5 Bindings takes the same approach) This syntax allows using both specific webcomponent attrs as shown above, as well as regular html properties (e.g. |
Thanks!
Sure :) I did re-read that "reasonably precise" bit before opening this issue. FWIW I'm not on any particular mission to make the API more typed, I think what we have is good. It just happens that the way Calico is currently working, we can do this "for free". And also, the web component thing put this issues of clashes onto my mind.
Yep, I studied the approach in the UI5 bindings. I'm not sure if this technique will work with how we are currently handling "modifiers" in Calico. And/or I didn't like it for other reasons 😂 |
Also just for the record an older issue about this is #13 but that was waaay before we had generators. Now that we have generators, different UI libraries can pick and choose how much of the available data they want to use, so in principle I don't mind if someone added this data to SDT. |
Ah, my bad, I couldn't tell from the title :)
Good question. Here's a prototype of how I plan to do this in Calico. In particular, check out the //> using lib "org.typelevel::shapeless3-deriving:3.3.0"
//> using option "-Ykind-projector:underscores"
import shapeless3.deriving.K0
trait Modifier[E, M]
trait SetAttribute[A, V]
class Tag[E]:
def apply[M <: Tuple](modifiers: M)(using
K0.ProductInstances[Modifier[E, _], M]
): E = ???
class Attribute[A]:
def :=[V](value: V): SetAttribute[A, V] = ???
// common to both
def sharedAttr: Attribute["shared"] = ???
// only on foo
def fooAttr: Attribute["foo"] = ???
// only on bar
def barAttr: Attribute["bar"] = ???
// on foo and bar, but with different types
def fizzBuzzAttr: Attribute["fizzbuzz"] = ???
trait Element
given sharedForElement[E <: Element]: Modifier[E, SetAttribute["shared", String]] = ???
trait FooElement extends Element
given fooForFooElement[E <: FooElement]: Modifier[E, SetAttribute["foo", String]] = ???
given fizzBuzzForFooElement[E <: FooElement]: Modifier[E, SetAttribute["fizzbuzz", Boolean]] = ???
trait BarElement extends Element
given barForBarElement[E <: BarElement]: Modifier[E, SetAttribute["bar", String]] = ???
given fizzBuzzForBarlement[E <: BarElement]: Modifier[E, SetAttribute["fizzbuzz", Int]] = ???
def fooTag: Tag[FooElement] = ???
def barTag: Tag[BarElement] = ???
def demo =
fooTag(
sharedAttr := "hello",
fooAttr := "foo",
fizzBuzzAttr := true
)
barTag(
sharedAttr := "hello",
barAttr := "bar",
fizzBuzzAttr := 42
) |
Ah, I see. I figured it'd be something with implicits. Interesting pattern. Note: I don't think that there's ever a case in the DOM where the same attribute / property has a different type based the element type. Like, the |
Part of my motivation for this pattern was to avoid relying on implicit conversions, which seem to be discouraged in Scala 3.
That may be true, but IIUC that seems down to luck or "good practice" rather than a hard rule.
Exactly, and web components creates new potential for such incompatibilities. As you point out, attributes for web components could be handled differently. But one of the big ideas of web components in HTML is that they can be used like vanilla elements, so I'm interested to see if we can preserve that experience. |
For example, the current data for the
label
attribute is:scala-dom-types/shared/src/main/scala/com/raquo/domtypes/defs/reflectedAttrs/ReflectedHtmlAttrDefs.scala
Lines 609 to 622 in 6900584
At least according to this page, it is supported only for
<track>
,<option>
,<optgroup>
,<menu>
, and<menuitem>
tags.https://www.geeksforgeeks.org/html-label-attribute/
In fact, I'm confused—is the
label
for<track>
and<option>
really the same?In any case, Calico would be able to take advantage of this information.
The reason I'm thinking about this now, is because I am looking at web components, and they often seem to be defining their own custom attributes that may be "clashing" with other HTML attributes.
For example, I'm stuck on
label
specifically because of its use in MaterialButton
.https://github.com/material-components/material-web/blob/e15c4b86d584cfda5dc850cb697bc9b9552e9536/docs/quick-start.md#usage
Basically we seem to have a "namespacing" issue, where "attributes" should be "namespaced" within their element, because they may have different implementations and types across elements (or not even be available).
The text was updated successfully, but these errors were encountered: