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

Opt-in for <select> customizability #5791

Closed
gregwhitworth opened this issue Aug 5, 2020 · 15 comments
Closed

Opt-in for <select> customizability #5791

gregwhitworth opened this issue Aug 5, 2020 · 15 comments

Comments

@gregwhitworth
Copy link

gregwhitworth commented Aug 5, 2020

@dandclark opened this issue on the repo that contains the explainer for this. For context, we released an explainer that attempts to explain a web platform control definition for defining components going forward. This requires HTML modifications across the WHATWG but to keep this one scoped. Here is the outline from Dan in the initial issue:

It's necessary that control customizability be opt-in rather than on by default in order to not break compatibility with older > sites and to avoid issues where capabilities of the customizable controls be limited, e.g. the customizable <select> must > not escape the bounds of windows due to security concerns.

Opt-in for custom control behavior for type like will be done by introducing new elements, > e.g. <range>, for the customizable version, while will remain the same.

For <select>, since unlike <input> the parser does not prevent it from being parsed with child DOM nodes, we've
proposed that it's not necessary to create a new element for it and we could instead do opt-in through an attribute like <select custom="">.

There are downsides to relying on an attribute though:

@mfreed7 pointed out that we'd need to deal with the fact that the custom attribute could be added/removed dynamically, which adds complexity. Parsing is particularly concerning here, since the attribute would change the parsing rules for the subtree of the <select>. Is there any scenario where a <select> could have script change it to custom when we're in the middle of parsing its subtree?

@travisleithead raised this specific concern about the dynamic case: consider a dynamically-created <select> (via document.createElement()), when the custom attribute must be set using setAttribute(). When should the transition to the custom behavior be applied? Applying it at the point of setAttribute() would be inconsistent with how other elements like <input type="range"> work when created dynamically; typically the transformation would occur when the element was appended to the DOM. But, this means that for a dynamically created <select>, the developer would have to wait until the <select> is appended to the DOM before calling attachShadow(), since attachShadow() throws for a non-custom <select>.

If we're minting new elements for all the customizable <input> types then it seems odd to do something different just for <select>.

On the other hand there are downsides to adding a new element for : What would we name it? @mfreed7 suggested <selectmenu>, I don't have any other ideas at the moment. @gregwhitworth pointed out that some might be opposed to a new element that is almost 1:1 with the current one but had more capabilities. Overall, introducing a new element and thereby sidestepping the problems of dynamic opt-in seems better to me.

@gregwhitworth
Copy link
Author

Bringing in my comment from the MSEdgeExplainer repo:

From the beginning I've been in favor of having new elements for the new controls as it also allows us to keep some native ones and specific needs for certain capabilities (window escape, etc). As we discussed in our explainer I'm also a fan of the built-in parts, while maybe leveraging WC parts under the hood being elements themselves as well so it is 100% apparent what is standard/ships with the UA and what is user land code.

@Yay295
Copy link
Contributor

Yay295 commented Aug 6, 2020

What type of customizability are you trying to add to <select>?

@gregwhitworth
Copy link
Author

@Yay295 thanks for the question. While it's a bit long the explainer delves into the overall goal for every control that is currently shipping natively in browsers and exploration of new components/controls. TLDR; enable styling and extensibility of the built in controls by defining the antomy, states and behaviors within one specification within Open UI.

Some additional reading on the topic of the problem space and why this is worth investing in (I have some other concrete examples that I provide in my Open UI talk but haven't put in blog form yet):

Open UI will define the necessary anatomy which may result in new elements or psuedo elements, states, and other gaps. So to scope this one, the specific request as @dandclark has noted is that in order to unlock these new capabilities as some authors may desire the current <select> and there may be web compat concerns. As such we can go a few different ways in order to unlock access to the new code. This methodology may itself need to be denoted on a case by case basis. Currently there are two possible options:

  1. Introduce a new element for customizable controls
  2. Introduce an attribute that unlocks the customizable controls

As outlined in the explainer it makes sense to introduce new elements for the various input types since their models and controller code are so different and this will allow this fork in the code. Let me know if that clarifies it for ya @Yay295

@annevk
Copy link
Member

annevk commented Aug 6, 2020

If the main goal is styling I don't see why we need a new attribute or element. It seems that appearance:none or some such could allow for that.

@gregwhitworth
Copy link
Author

@annevk out of curiosity did you read the explainer? Currently the parts of a select (and many other controls) are not exposed in order to enable the necessary styling and extensibility. As I outlined to the CSSWG we continue to do this but in an ad-hoc fashion due to inteop (see the file input psuedo element request by Mozilla). Open UI is a place where we're doing a holistic review and creating functional specifications that defines a control/component for web plat, component libs, etc as everyone is duplicating these (a single standardized functional specification currently does not exist).

If the main goal is styling I don't see why we need a new attribute or element. It seems that appearance:none or some such could allow for that.

There will be a need for appearance: none but it will not be sufficient since the parts can't be accessed. The current <select> has different implementations across UAs and also has additional capabilities that we can't keep due to security reasons (eg: escaping the bounds of the viewport) while enabling full style that is necessary. This also doesn't address the need for extensibility.

@domenic
Copy link
Member

domenic commented Aug 6, 2020

A new element makes a lot more sense to me.

If you go that route, I would suggest trying to unify <select> with the current <input type="text"> + <datalist> combination. E.g. work on a <combobox> element. Developers are consistently tripped up by the fact that these similar controls have very different interfaces.

@annevk
Copy link
Member

annevk commented Aug 6, 2020

@gregwhitworth well yes, you would also need pseudo-elements to get at the various bits. It would not give you the ability to add new bits necessarily, but it would address a large swath of the use cases. (And yes, part of disabling the native theming would be disabling the dialog drawing its own window.)

@gregwhitworth
Copy link
Author

gregwhitworth commented Aug 6, 2020

It would not give you the ability to add new bits necessarily, but it would address a large swath of the use cases.

And this is why psuedo elements are insufficient to cover the use cases. The explainer outlines that we'll leverage web component definitions leveraging slots and updating the definition of part to not solely be a hoist for CSS but to denote (even though it's implied) that the part has "controller" code attached to it by the component author. This will allow the UA (or component lib that builds according to Open UI) to wire up the necessary events & ARIA. This enables general extensibility without needing to completely recreate every interaction that a control has which can be very complex and is often not done with the same rigor across all implementations.

A new element makes a lot more sense to me.

Agreed

If you go that route, I would suggest trying to unify with the current + combination. E.g. work on a element. Developers are consistently tripped up by the fact that these similar controls have very different interfaces.

I am open to this and am worth discussing it, I'd like to resolve on the differences/naming as a combobox and select as the majority of component libs, etc leverage the name select even if they appear as a combobox. Which is why we were initially leaning towards a select derivative.

@domenic
Copy link
Member

domenic commented Aug 6, 2020

The naming will be a hard problem regardless, as you've mentioned; I don't have any strong opinions there.

But I do feel somewhat firmly that there needs to be unification of "select where you can type" and "select where you cannot type". And ideally that would be at the web-developer-facing level. For example, one element with an optional attribute.

Stated in terms of use cases, I think developers transitioning from a fixed set of inputs to a fixed set of inputs + optional free-form text (e.g., modernizing a gender form field) should be able to do so easily. Currently, to transition from <select> to <input> + <datalist>, they have to re-do all of their markup, change their CSS selectors, and probably update their JavaScript code if they use things like selectedIndex or options. It would be great if in the future they could just add an HTML attribute, or similar, without those extra changes.

@gregwhitworth
Copy link
Author

gregwhitworth commented Aug 6, 2020

@domenic yep - there is agreement here generally and we've discussed this in general here in Open UI as this is the primary request for <select> upon survey of 1400 webdevs and ~20 top web property partners in why they desire additional functionality. There are, to your point a desire to have a select solely be a button verse an actual input. I'll open a single issue on Open UI to discuss this (eg: should we bifurcate in control name solely to add an input rather than an element that behaves as button).

This is even more more odd with built in UA implementations as they allow type ahead functionality but don't show the actual user input which is just generally a bad UX. I think due to this I'd be more in favor of keeping the <select> name and updating the anatomy to contain an input by default since that is actually how it's behaving. I'll link the Open UI issue here later this evening.

@mfreed7
Copy link
Contributor

mfreed7 commented Aug 10, 2020

But I do feel somewhat firmly that there needs to be unification of "select where you can type" and "select where you cannot type". And ideally that would be at the web-developer-facing level. For example, one element with an optional attribute.

I just want to second this - the new element should unify these two use cases ("combo-box" and "drop-down") into a single control.

And I want to re-iterate my original comment: I think this should be a new element, not an attribute (which can be added and removed) on <select>. While I understand the argument that this new thing "looks" like the old <select>, there are many new behaviors that are incompatible with the old <select>:

  1. The (optional) ability to type anything, not just restricted to the set of options.
  2. Arbitrary HTML in options
  3. Customizable parts
  4. Pop-up that does not extend beyond the window bounds.

And inevitably there will be strange behaviors associated with adding or removing the opt-in attribute on <select> such as removal of selections, resetting of state, etc. And as mentioned by @travisleithead, there will be questions about the timing of when the new behavior takes effect.

Consider what would happen here, if we went the attribute-on-select route:

Sample #1:

const combobox = document.createElement('select');
document.body.appendChild(combobox);
combobox.addAttribute('newbehavior','true'); // Opt in!
combobox.innerHTML = '<option><img src="cat.jpg">Cat</option><option><img src="dog.jpg">Dog</option>';
// Here, we have a fancy, new <select> with images of cats and dogs

Sample #2:

const combobox = document.createElement('select');
document.body.appendChild(combobox);
combobox.innerHTML = '<option><img src="cat.jpg">Cat</option><option><img src="dog.jpg">Dog</option>';
combobox.addAttribute('newbehavior','true'); // Opt in, but a little late
// Boo! No images here, because we opted in after innerHTML, and the parser removed the <img> tags.

@annevk
Copy link
Member

annevk commented Aug 17, 2020

(Note that <input> + <datalist> also works for other controls (some in theory), e.g., range, color, and email.)

@LeaVerou
Copy link

I second the proposal for a new <combobox> element, or whatever it ends up being called to unify <select> and <input>+<datalist>.

A few thoughts:

  • One thing I've seen people get tripped up about is that while you can use a <datalist> to specify the autocomplete options in an <input>, you cannot use it to specify the options in a <select>, which in some cases forces them to duplicate markup. So it may be a good idea to allow both in the new element.
  • Orientation: it should be possible to orent options top to bottom (default), left to right, or as a grid, at least via CSS.
  • A select allows selecting one or more options. An input allows only one option to be entered. Does their union allow more than one custom options?
  • I maintain Awesomplete, a popular autocomplete library. One of the most common issues people have is that they want a list of key-value pairs, where the key is what gets sent to the server but the value is what is shown (like a <select>), a behavior that is not possible with an <input>, where selecting an item from the <datalist> enters that option's value in the input. A new element can also address this issue.
  • For large lists of values, it may be a good idea to be able to set them programmatically, without the overhead of thousands of DOM elements.

@zcorpan
Copy link
Member

zcorpan commented Jun 11, 2021

Related issue: #6733

@annevk
Copy link
Member

annevk commented Nov 8, 2024

Let's duplicate this into #9799.

@annevk annevk closed this as not planned Won't fix, can't repro, duplicate, stale Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

7 participants