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

HTMLInputElement showPicker() #688

Closed
1 task done
domenic opened this issue Nov 8, 2021 · 17 comments
Closed
1 task done

HTMLInputElement showPicker() #688

domenic opened this issue Nov 8, 2021 · 17 comments
Assignees
Labels
Resolution: unsatisfied The TAG does not feel the design meets required quality standards Topic: HTML Venue: WHATWG

Comments

@domenic
Copy link
Member

domenic commented Nov 8, 2021

Braw mornin' TAG!

I'm requesting a TAG review of the showPicker() method for HTMLInputElement.

The showPicker() element is a new addition to HTMLInputElement which addresses a very common request from web developers: programmatically showing a picker for controls like date etc.

Further details:

  • I have reviewed the TAG's Web Platform Design Principles
  • Relevant time constraints or deadlines: The next WHATWG HTML triage call is 2021-12-02 and it'd be great to have any feedback by then
  • The group where the work on this specification is currently being done: WHATWG
  • The group where standardization of this work is intended to be done (if current group is a community group or other incubation venue): N/A
  • Major unresolved issues with or opposition to this specification: None known
  • This work is being funded by: Google

We'd prefer the TAG provide feedback as (please delete all but the desired option):

💬 leave review feedback as a comment in this issue and @-notify @domenic, @beaufortfrancois, and @annevk

@kenchris
Copy link

kenchris commented Nov 8, 2021

I think this is a good addition, and solves real user needs

@kenchris
Copy link

kenchris commented Nov 8, 2021

I believe that with user activation delegation, you need to add something (like feature identifier name) to make this work for iframes etc

Like here: https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md

https://wicg.github.io/capability-delegation/spec.html

@LeaVerou LeaVerou self-assigned this Nov 9, 2021
@LeaVerou
Copy link
Member

LeaVerou commented Nov 9, 2021

I'm definitely familiar with the user needs this addresses (in fact, I believe I've even been on the author end of said use cases!), so it's exciting to see work in that direction. Some questions:

  • Since programmatic clicks already trigger the picker on color and file inputs, why not just specify that programmatic clicks trigger the picker on all inputs and avoid the additional API surface?
  • I'm a little concerned that the name showPicker may be overly constraining. Can all UIs we may want this to trigger be described as pickers, not just now but also in the future?

showPicker() is specified with a few restrictions to improve security:

  • It can only be called with transient user activation. If called without, it will throw a "NotAllowedError" DOMException. (This is similar to how click() behaviors, except click() silently does nothing.)

Doesn't this leak information about whether the user has interacted with the page, that silently doing nothing does not?

@domenic
Copy link
Member Author

domenic commented Nov 9, 2021

Since programmatic clicks already trigger the picker on color and file inputs, why not just specify that programmatic clicks trigger the picker on all inputs and avoid the additional API surface?

That's one direction we could go in, but I worry that it's a bit unexpected. click() rarely has these sorts of side effects, and the fact that it does so on file and color feels like a legacy quirk instead of something we want to extend. There's also a minor compat risk that people are calling click() and expecting no-op behavior today... although I doubt it'd be that risky.

I think the main argument is one I allude to in whatwg/html#3232, which is that by not tying pickers to clicks, we allow a broader possible range of browser UIs for form controls, both now and in the future. Which has always felt important to me, given how we've seen things evolve with smartphones and watches and so on.

I'm a little concerned that the name showPicker may be overly constraining. Can all UIs we may want this to trigger be described as pickers, not just now but also in the future?

I think we're kind of defining "all UIs we may this to trigger" to be pickers. That is, showPicker() implies you want to show a picker... if we had some other sort of UI for entering values (e.g.... a virtual keyboard??) then probably the developer doesn't want that to happen when they call el.showPicker().

Perhaps another way of phrasing this is, are there other non-picker UIs that developers might want to show, in the same situations they want to show pickers? And would it be better for developers to not have to know the difference, but instead just trigger any such UIs? It's hard to say without examples, but I lean toward "picker" being a well-understood paradigm, and believing that it'll extend in the future to other non-pickers might be hard for developers to reason about...

Doesn't this leak information about whether the user has interacted with the page, that silently doing nothing does not?

No; this information is already available in plenty of ways, e.g. by using explicit event listeners for the activation triggering input events.

@domenic
Copy link
Member Author

domenic commented Nov 9, 2021

I believe that with user activation delegation, you need to add something (like feature identifier name) to make this work for iframes etc

Yeah, I noted that under "possible future work" in the mini-explainer:

  • We could add a permissions policy which allows cross-origin iframes to show pickers, when their parent chain allows them to do so.

@LeaVerou
Copy link
Member

LeaVerou commented Nov 22, 2021

Since programmatic clicks already trigger the picker on color and file inputs, why not just specify that programmatic clicks trigger the picker on all inputs and avoid the additional API surface?

That's one direction we could go in, but I worry that it's a bit unexpected. click() rarely has these sorts of side effects, and the fact that it does so on file and color feels like a legacy quirk instead of something we want to extend.

.click() has major side effects already, e.g. calling it on an <a> element can navigate to another page! Doesn't get any more side effect-y than that! 😁

There's also a minor compat risk that people are calling click() and expecting no-op behavior today... although I doubt it'd be that risky.

Yeah, I agree I wouldn't expect that to be common.

The way I see it, the advantages of .click() triggering the picker instead of a separate method are:

  • It's usually the first thing authors try, even before they research the API surface, so it's good for discoverability
  • If there are any event listeners attached to clicks with the assumption that they will be triggered every time the picker is opened, this will trigger them too

One downside is that it couples synthetic clicks with opening the picker: is there any case where authors may want to do one without the other?

I think the main argument is one I allude to in whatwg/html#3232, which is that by not tying pickers to clicks, we allow a broader possible range of browser UIs for form controls, both now and in the future. Which has always felt important to me, given how we've seen things evolve with smartphones and watches and so on.

If I understand your point correctly (?), you are saying that browsers in the future may want to provide more granular UIs which display different pickers depending on the location of the click, and thus a general .click() cannot really describe these kinds of interactions, whereas .showPicker() can be extended to support granularity via arguments.

I see that in theory, though why not add a separate API call then, if that happens? They're not mutually exclusive. Then .click() can do the same thing as .showPicker() if called with no arguments.

I could be wrong, but it seems inconsistent to me to have .click() trigger only some pickers, and add a separate method to trigger the rest. 🤷🏽‍♀️

It's also a bit unclear what a "picker" is. E.g. in an <input type=color> .showPicker() would open the OS color picker. However, in an <input type=color list="paletteid"> .showPicker() would not open the OS color picker, but a popup displaying the datalist options. I wonder if this would confuse authors that may expect .showPicker() to display a consistent type of UI for a given input type. Whereas .click() is easier to have a mental model about.

@plinss plinss modified the milestones: 2021-11-22-week, 2021-12-06-F2F-Madripoor Nov 22, 2021
@annevk
Copy link
Member

annevk commented Nov 22, 2021

Such UI already exists, e.g., try <input type=date> in Chrome. Clicking the calendar icon shows the picker, clicking the control merely focuses it.

Similar situation with <input type=password> in Safari, although the icon doesn't show until the control is focused.

@torgo torgo modified the milestones: 2021-12-06-F2F-Madripoor, 2021-12-13 Dec 9, 2021
@plinss
Copy link
Member

plinss commented Dec 13, 2021

One concern here is feature detection, which is already difficult and fragile for various input types. I want to be sure that developers can detect if the browser can display a picker so they have the option to adjust their UI and/or display a custom picker when needed.

Otherwise we're generally happy with this and are glad to see it moving forward.

@beaufortfrancois
Copy link

Rejecting the showPicker() promise with NotSupportedError may help with whether picker was shown or not. What do you think @domenic?

if ("showPicker" in HTMLInputElement.prototype) {
  try {
    await document.querySelector("input").showPicker();
  }
  catch (error) {
    if (error == "NotSupportedError") {
      /* Show custom picker */
    }
  }
} else {
  /* Show custom picker */
}

@domenic
Copy link
Member Author

domenic commented Dec 14, 2021

Thanks for bringing this up; it's quite a worthwhile discussion.

I think this is a tradeoff. By changing the behavior to make whether a picker was shown or not detectable, we introduce compat issues that constrain browsers from changing their UI in the future. I.e., adding or removing pickers from controls could now become a breaking change for websites. This is an area browsers have been hesitant to be constrained on, in the past.

It also introduces potential interop issues. Right now, if you call showPicker(), it will never throw. But with that proposal, it might work fine in some browsers, and throw in others. This could lead to scenarios where, in the browsers you test with, there's no need for a catch block, and so the developer doesn't add one. But then other browsers can't access your site. The same is true for other APIs that expose support, e.g. a boolean return value or a separate canShowPicker() function.

So adding any sort of feature-detection which exposes whether a browser supports a given picker, or not, creates new interop and compat risks that the current proposal doesn't have. But, it makes the proposal more useful for the specific case where a developer definitely wants to show a picker, even if a browser doesn't support it, and thus plans to perform good feature testing and add good fallbacks for such non-supporting browsers.

My instinct is to wait to gather more data on in-the-wild usage to see whether the majority of use cases are:

  • It'd be nice to show a picker here, if the browser supports it; otherwise the user can just type; vs.
  • I definitely need to show a picker here, and need to know if that won't work, so that I can display my own fallback.

The current API is designed more for the former. If we find out that in the wild people are actually more interested in the latter, then we can consider adding feature detection abilities to serve that use case, and having a cross-browser discussion about whether that's worth the compat and interop risks.

@plinss
Copy link
Member

plinss commented Dec 14, 2021

It's anecdata (and real-world data wins ofc), but I can assure you that the 'I really want a picker here (because users typing dates is extremely error-prone), and would prefer the native one, but will roll my own if I have to' situation has happened to me. There are also a lot of UI widgets out there implementing date pickers, and I expect most of them fail somewhere on a11y, i18n, and l10n, so user experience would be well served if they can use a native picker that gets it right when available.

Provided that showPicker() fails predictably when a given picker isn't available from day one I think the potential risk of interop problems is fairly low. Especially as not all UAs are likely to implement all the possible pickers at the same time, authors will have plenty of incentive to detect failure. Historically some UAs didn't even support date pickers on all platforms (not sure about current reality there).

If showPicker() sometimes throwing exception is problematic, there are other approaches like simply returning null that would be less disruptive. Note also it's important to be able to tell the difference between a UA failing to display a picker vs the user dismissing the picker with no selection. (Maybe if a user dismiss also throws an exception then everyone has to deal with exceptions...)

Which brings up another thought, what about accepting an AbortSignal in showPicker()?

@domenic
Copy link
Member Author

domenic commented Dec 14, 2021

Which brings up another thought, what about accepting an AbortSignal in showPicker()?

To allow the web developer to dismiss a picker even if the user is interacting with it? Yeah, we mentioned

It's possible closePicker() might be useful, and we could consider adding that if developers ask for it.

as a possible future extension in the explainer.

@plinss
Copy link
Member

plinss commented Dec 14, 2021

A closePicker() method could be useful, but it's not quite the same as accepting an AbortSignal. The latter has the advantage of closing the picker when something somewhat unrelated (and isolated from the code handling the picker) happens without having to add a bunch of glue code. Seems useful to me, but just a suggestion.

@domenic
Copy link
Member Author

domenic commented Dec 14, 2021

Yeah, I agree that's probably a better API than closePicker() in particular, if we do hear requests of that sort.

@atanassov atanassov added Progress: propose closing we think it should be closed but are waiting on some feedback or consensus and removed Progress: in progress labels Feb 15, 2022
@atanassov
Copy link

@domenic, we had another round of discussions with TAG today and our consensus is still wanting to see detectability of the proposed feature. We want to close the review with this last issue addressed.

(assuming detectability is provided) Another question I have is whether you considered exposing finer granularity of UI detectability? In the case a picker is supported, that picker can be UI implemented by the browser vs the OS native picker. This type of distinction will be just as important when component implementers are making the decision to show native vs theirs.

@domenic
Copy link
Member Author

domenic commented Apr 4, 2022

Thanks for the feedback! My current position is that it's not a worthwhile tradeoff, to constrain and expose browser UI specifics in that way, but I understand we differ in that regard.

@atanassov
Copy link

Thank you for confirming your position @domenic. As you stated, we do differ in our opinions, and it doesn't look we can add anything else for now, thus closing the review.
Thank you for working with us and if you want us to do another round of reviews, please reopen.

@atanassov atanassov added Resolution: unsatisfied The TAG does not feel the design meets required quality standards and removed Progress: propose closing we think it should be closed but are waiting on some feedback or consensus labels Jun 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: unsatisfied The TAG does not feel the design meets required quality standards Topic: HTML Venue: WHATWG
Projects
None yet
Development

No branches or pull requests

9 participants