preactjs / preact

⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
https://preactjs.com
MIT License
36.35k stars 1.93k forks source link

syntax for choosing setting a property vs attribute on elements #4416

Open trusktr opened 2 weeks ago

trusktr commented 2 weeks ago

Describe the feature you'd love to see

It is not possible to guess 100% of the time whether an element user needs to set a property, or an attribute.

Does this set an attribute, or a property?

return <some-element foo={[1, 2, 3]} />

Answer: it depends, sometimes Preact sets the .foo property, sometimes Preact sets the foo attribute. The user has no control over this.

The implementation of an element can vary (and may be out of the Preact user's control):

Design choices out of the control of Preact:

It is not possible for Preact to always guess correctly which of the above cases the user will want, and the Preact user needs control.

Additional context (optional)

Users need a way to express whether they want to set an attribute, or a property, or both. We also need to be able to add/remove attributes based on booleans.

Lit, Solid.js, and others have (sometimes only partial) solutions to this. For more details on the solutions other frameworks have, see this new test proposal for custom-elements-everywhere:

Possible solution idea

Solid.js has JSX syntax such as attr:foo=... and prop:foo=... for setting an attribute vs a property, but no boolean support. Pota, a library that is built on Solid.js, has its own JSX and html syntax that adds bool:foo=... support. Etc.

Preact could choose to adopt a similar approach, which is valid JSX syntax.

An alternative html template string tag for Preact could also provide Lit-like syntax (.foo=..., foo=..., and ?foo=...).

rschristian commented 2 weeks ago

Answer: it depends, sometimes Preact sets the .foo property, sometimes Preact sets the foo attribute. The user has no control over this.

While I don't disagree with the premise/request, and have written up minor forks/patches that add this, there are quite defined rules. It's not random or a guess: if the provided label has a DOM property, and isn't from a small list of excluded labels, it gets set as a property, else, attr.

Preact (and other UI libs) aren't "guessing" at what others expect; they work with the DOM as they see fit. It's up to the individual devs to reconcile the expectations of different pieces of software. More control here would absolutely help devs reconcile those expectations, but I just want to make it clear that it isn't really a project goal to "guess correctly" as you put it.

trusktr commented 2 weeks ago

It's not random or a guess: if the provided label has a DOM property, and isn't from a small list of excluded labels, it gets set as a property, else, attr.

Perhaps "heuristic" or "rules" are better terms. To re-express with those words, no heuristic or rule can satisfy all scenarios because all scenarios can only be users picking which to use.

rschristian commented 2 weeks ago

Not quite what I meant, no. We largely set what we set, we're not looking to satisfy any scenarios beyond "works with DOM APIs correctly". Anything beyond that is a non-goal of the project really, something for users to address. It's not a concern of the project if it doesn't enable a CSS selector, for example.

Not having great tools for users to address these issues is, however, a valid issue for the project, if that makes sense.

Minor (perhaps frivolous) semantics, I know, but I want to clarify project goals.

trusktr commented 2 weeks ago

I'm not sure what's the debate. In my mind it's a valid request (and likely project goal) to be able to control DOM elements with a DOM framework like Preact (wanting to set an attribute to use for CSS selecting is but one of many reasons), but of course that's up to each framework.

I changed the issue template to feature request (accidentally chose bug first).

rejhgadellaa commented 2 weeks ago

I recently ran into the popover property not accepting boolean values, but the attribute can be a boolean (it will then default to auto). So this:

<menu popover />

Will actually try to set Element.popover = true (which is an error)

You have to write:

<menu popover="auto" />

Not a big problem, but annoying 😅

rschristian commented 2 weeks ago

@rejhgadellaa have you checked the latest version? I believe that was a bug that was corrected.

Edit: Never mind, hasn't been released yet. Fixed in #4393 though

rschristian commented 2 weeks ago

@trusktr I'm saying the comments of "It is not possible for Preact to always guess correctly which of the above cases the user will want" and "no heuristic or rule can satisfy all scenarios" aren't really relevant as it's not, nor was it ever, a project goal to do that. That was always on the user's end of things.

I just want to make that clear as the inability to "guess which cases the users will want" is not in itself a problem or a valid issue, as we never made any attempt at all to guess what a user could prefer in sone scenario. Lack of tools for the user to set things how they want, however, is absolutely a valid issue.

It's somewhat important framing, as it's confusing fundamental project goals, but I digress.

rejhgadellaa commented 2 weeks ago

@rschristian oh sweet, I actually thought this was "working as intended", and maybe even more of an issue of the spec where the property and attribute don't accept the same argument types. Thanks!