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

HTMLPopupElement - <popup> #599

Closed
1 task done
mfreed7 opened this issue Jan 22, 2021 · 10 comments
Closed
1 task done

HTMLPopupElement - <popup> #599

mfreed7 opened this issue Jan 22, 2021 · 10 comments
Assignees
Labels
Resolution: too early Possibly too early for review or not enough info provided Review type: CG early review An early review of general direction from a Community Group Topic: HTML

Comments

@mfreed7
Copy link

mfreed7 commented Jan 22, 2021

HIQaH! QaH! TAG!

I'm requesting a TAG review of the <popup> element.

A new HTML element, <popup>, which can be used to build transient user interface (UI) elements that are displayed on top of all other web app UI. These include user-interactive elements like action menus, form element suggestions, content pickers, and teaching UI. This new element is similar to <dialog>, but has several important differences, including light-dismiss behavior, anchoring, and the lack of a "modal" mode.

Does this specification allow an origin some measure of control over a user agent’s native UI?
--> The <popup> element allows author-provided popup dialogs to be shown to the user. These popups are fully-contained within the owning frame, and do not overlap either parent frames or the browser UI. So there shouldn't be any issue here. But I'm bringing it up for completeness.

  • GitHub repo (if you prefer feedback filed there): I'd prefer feedback here on this issue.
  • Primary contacts (and their relationship to the specification):
  • Organization/project driving the design: Google DOM Team, Microsoft DOM/Editing Team
  • External status/issue trackers for this feature: https://chromestatus.com/guide/edit/5463833265045504

Further details:

  • I have reviewed the TAG's API Design Principles
  • The group where the incubation/design work on this is being done (or is intended to be done in the future): WICG
  • The group where standardization of this work is intended to be done ("unknown" if not known): WHATWG
  • Existing major pieces of multi-stakeholder review or discussion of this design: {coming soon}
  • Major unresolved issues with or opposition to this design: "Major" is a strong word, but there is a section of the explainer that discusses open issues and questions. Thoughts on those issues would definitely be appreciated from TAG.
  • This work is being funded by: Google and Microsoft

You should also know that...

I like the TAG.

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 @mfreed7 and @melanierichards

@mfreed7 mfreed7 added Progress: untriaged Review type: CG early review An early review of general direction from a Community Group labels Jan 22, 2021
@kenchris kenchris self-assigned this Jan 22, 2021
@LeaVerou LeaVerou self-assigned this Jan 22, 2021
@LeaVerou
Copy link
Member

LeaVerou commented Feb 3, 2021

Firstly, this is addressing a very real gap in the Web Platform and I'm happy to see work in that direction.

If my understanding is correct, this proposal introduces a <popup> element with the following features:

  • An anchor attribute anchors this to another element, both in terms of styling, as well as other behaviors.
  • Can "spill out of" containers, ignoring overflow: hidden
  • It comes with some light behavior baked in, such as light dismiss
  • It includes show() and hide() methods
  • autofocus is handled specially when the popup is shown
  • There is a delegatefocus attribute to focus the first focusable descendant when the popup is focused

Here are some thoughts.

Positioning

It seems to me that the primary problems this is trying to solve are styling problems:

  • positioning a positioned element based on another element.
  • allowing an element to "spill out" of overflow: hidden ancestors.

I think these are problems we should solve in CSS, rather than by introducing new "magic" that cannot be described fully in the UA stylesheet. Not only for separation of concerns, but also because this is more broadly useful and we wouldn't want people to have to wrap everything in a <popup> every time they need to position an element based on another element. The <popup> element can then just use that CSS as part of its UA stylesheet rules.

There are a few CSSWG threads on this, though there's definitely room for new proposals in this space:
w3c/csswg-drafts#5304
w3c/csswg-drafts#5699

Anchoring

I would suggest re-using the for attribute instead of introducing a new anchor attribute. This seems consistent with <label for> and <output for> usage.

It would be useful to have a default anchor, just like <label> elements default to form descendants when they do not have a for attribute. For example, the previous sibling and/or the parent element might be a good default. It also means that there is a more useful default than just displaying the popup at the top left corner, which is almost never desirable.

It is unclear to me if anchor affects tabbing order, but I think it should. There are many cases where the popup cannot be placed inside or next to the element it's anchored to, due to content model limitations or CSS inheritance. Authors should be able to continue the current practice of placing the popup as a child of <body>, without the current accessibility problems wrt tabbing order.

The hierarchy affects the event propagation path.

This could either be very useful, or very confusing, and I'm not sure which one it is.
I suppose there is precedent, with form elements receiving input events when their associated label receives these events.

Focus

On autofocus:

To move focus to the popup itself when show is called—without the need to explicitly call popupElement.focus()—place the attribute directly on the popup:

Are there use cases of showing the popup but not focusing it?

On delegatefocus:

Some authors may need to automatically focus the popup's first focusable descendent, and may not wish to write script to determine at runtime which element that is.

I wonder if that is the actual gap here: it should be easier to determine what the first focusable descendant is. But I definitely see the point about exposing this via HTML so that authors don't have to write script. But is this something specific to <popup> or a more generally useful behavior? I have definitely needed this before with arbitrary focusable elements (e.g. collection items).

Show and hide

I would recommend adding an open attribute, just like <dialog> so that authors can a) open the popup declaratively and b) target opened popups with an attribute selector.

Layering

Are rendered on top of all other content in the host web application

Even over <dialog>?

@mfreed7
Copy link
Author

mfreed7 commented Feb 18, 2021

Firstly, this is addressing a very real gap in the Web Platform and I'm happy to see work in that direction.

@LeaVerou thanks for the great set of initial feedback here. I'm glad you think this is a useful addition. Responses below...

If my understanding is correct, this proposal introduces a <popup> element with the following features:

  • An anchor attribute anchors this to another element, both in terms of styling, as well as other behaviors.
  • Can "spill out of" containers, ignoring overflow: hidden
  • It comes with some light behavior baked in, such as light dismiss
  • It includes show() and hide() methods
  • autofocus is handled specially when the popup is shown
  • There is a delegatefocus attribute to focus the first focusable descendant when the popup is focused

The only thing I want to clarify here, which ties to the comments below, is that the positioning of the popup has been delegated to a separate platform proposal, for "anchored positioning". This has not been put forth yet, but the current <popup> proposal should be read in the context of a forthcoming proposal on positioning. I do understand the confusion here.

Positioning

It seems to me that the primary problems this is trying to solve are styling problems:

  • positioning a positioned element based on another element.
  • allowing an element to "spill out" of overflow: hidden ancestors.

I think these are problems we should solve in CSS, rather than by introducing new "magic" that cannot be described fully in the UA stylesheet. Not only for separation of concerns, but also because this is more broadly useful and we wouldn't want people to have to wrap everything in a <popup> every time they need to position an element based on another element. The <popup> element can then just use that CSS as part of its UA stylesheet rules.

See above. Really, I think the primary low-level problem that <popup> solves is access to the "top layer". I.e. the ability to position a popup over the top of everything else, regardless of position in the DOM tree or how many 9's you use in z-index:999999. The "magic" that isn't specified in this proposal is a way to anchor-position one element (the <popup> in this case) relative to the position of another element (e.g. the <popup>'s "anchor" element). As I mentioned, I believe a proposal is forthcoming. @melanierichards, @ipopescu93

Anchoring

I would suggest re-using the for attribute instead of introducing a new anchor attribute. This seems consistent with <label for> and <output for> usage.

Thanks for the feedback here. Consistency is important, but so is clarity. There is a discussion see this comment about naming, anchor positioning, and automatic (declarative) invokation. Those might require two separate attributes (e.g. "anchor" and "invokedby") that might need more verbose attribute names than just "for". Let's discuss further on the issue.

It would be useful to have a default anchor, just like <label> elements default to form descendants when they do not have a for attribute. For example, the previous sibling and/or the parent element might be a good default. It also means that there is a more useful default than just displaying the popup at the top left corner, which is almost never desirable.

I definitely agree with this point. We need to figure out the mechanics of this, since theoretically any element could be an anchor. The <label> spec is easier to implement because there's only one type of element to look for. Here, we might need to "stop" on an attribute or something, e.g.

<button im-the-anchor>
  <div id=not-the-anchor>
    <popup></popup>
  </div>
</button>

Suggestions appreciated here.

It is unclear to me if anchor affects tabbing order, but I think it should. There are many cases where the popup cannot be placed inside or next to the element it's anchored to, due to content model limitations or CSS inheritance. Authors should be able to continue the current practice of placing the popup as a child of <body>, without the current accessibility problems wrt tabbing order.

Hmm that's a very good point, which I don't think we've considered in the explainer. I would agree that since the <popup> can be placed anywhere, but will (usually) be visually next to the anchor element, it might make sense to modify tab order to account for this. @melanierichards thoughts?

The hierarchy affects the event propagation path.

This could either be very useful, or very confusing, and I'm not sure which one it is.
I suppose there is precedent, with form elements receiving input events when their associated label receives these events.

I agree that it might be confusing. As I've been implementing the prototype in Chromium, wrapping my head around this part has been tricky at times. Again, suggestions appreciated for ways to make it less confusing in practice.

Focus

On autofocus:

To move focus to the popup itself when show is called—without the need to explicitly call popupElement.focus()—place the attribute directly on the popup:

Are there use cases of showing the popup but not focusing it?

@melanierichards for better examples here. But I think one is likely a "teaching bubble" that pops up on hover of some other control, but you wouldn't want focus to move to the bubble in that case.

On delegatefocus:

Some authors may need to automatically focus the popup's first focusable descendent, and may not wish to write script to determine at runtime which element that is.

I wonder if that is the actual gap here: it should be easier to determine what the first focusable descendant is. But I definitely see the point about exposing this via HTML so that authors don't have to write script. But is this something specific to <popup> or a more generally useful behavior? I have definitely needed this before with arbitrary focusable elements (e.g. collection items).

One quick first comment is that I think we should call it delegatesfocus (with plural 's') to match the similar concept for ShadowRoot. Perhaps that's also the more generally useful behavior you're looking for?

Show and hide

I would recommend adding an open attribute, just like <dialog> so that authors can a) open the popup declaratively and b) target opened popups with an attribute selector.

See this related comment from @domenic. It does seem like we should make sure <popup> and <dialog> are as parallel as they can be here.

One (potentially big?) issue with opening the popup declaratively is that only one popup can be open at a time (excepting "nested" popups) so the behavior might be a bit odd if more than one <popup> has an open attribute. That can be fixed, of course, but I'm wondering if it might be better to just remove "open" from <dialog> instead. Also, the use case for <popup> seems to be in "response" to something on the page, which should preclude popups that open themselves immediately on page load. But maybe I'm missing a use case for that.

Layering

Are rendered on top of all other content in the host web application

Even over <dialog>?

<popup>s are rendered on the "top layer", in the order they were added. So if a <dialog> was already open, and a <popup> is shown, it will be rendered on top of the <dialog>. Further, a <dialog> being shown will trigger "light dismiss" behavior on any already-showing <popup>s.

@LeaVerou
Copy link
Member

LeaVerou commented Feb 18, 2021

I definitely agree with this point. We need to figure out the mechanics of this, since theoretically any element could be an anchor. The <label> spec is easier to implement because there's only one type of element to look for. Here, we might need to "stop" on an attribute or something, e.g.

<button im-the-anchor>
  <div id=not-the-anchor>
    <popup></popup>
  </div>
</button>

Suggestions appreciated here.

I think the previous sibling or the parent are both reasonable defaults.
Slight preference for previous sibling, as it's less constrained and can work with empty elements as implicit anchors. A downside is that there might not be a previous sibling, but I suppose that is analogous to having a <label> with no for attribute and no form control descendants.

Show and hide

I would recommend adding an open attribute, just like <dialog> so that authors can a) open the popup declaratively and b) target opened popups with an attribute selector.

See this related comment from @domenic. It does seem like we should make sure <popup> and <dialog> are as parallel as they can be here.

One (potentially big?) issue with opening the popup declaratively is that only one popup can be open at a time (excepting "nested" popups) so the behavior might be a bit odd if more than one <popup> has an open attribute. That can be fixed, of course, but I'm wondering if it might be better to just remove "open" from <dialog> instead. Also, the use case for <popup> seems to be in "response" to something on the page, which should preclude popups that open themselves immediately on page load. But maybe I'm missing a use case for that.

Providing declarative HTML-based ways to interact with UI controls has several benefits. Off the top of my head:

  • It facilitates experimentation and iteration (much quicker to type open when iterating than to write script)
  • It makes it more learnable: there is a baseline uniform API (DOM) that novices can use to interact with the UI control via script, even before learning the more specialized API that might come with each individual control
  • It means behaviors can be expressed reactively in libraries supporting such syntax (e.g. open={{expression}}) and be handled by any library handling HTML generically.
  • It means UI states can be addressed via established and widely understood attribute selectors, instead of new pseudo-classes
  • It makes state inspectable via dev tools which facilitates debugging

Therefore, I think removing open from <dialog> would be a step in the wrong direction. It would be far better to instead of fix its issues so it can be adopted in <popup> as well.

The fact that only one popup can be open at a time is not a blocker; there is already precedent with radio buttons and their checked attribute or <option> elements and their selected attribute. But are you sure there are no use cases of showing multiple popups at once? Nested popups is one use case that is expressly listed as an exception. Could there be more?

@torgo torgo added the Progress: pending external feedback The TAG is waiting on response to comments/questions asked by the TAG during the review label Feb 24, 2021
@melanierichards
Copy link

Hi folks, apologies that I am so woefully behind in responding to this issue, and many thanks to @LeaVerou for reviewing the proposal!

Substantive changes to the proposal

  • delegatefocus was renamed to delegatesfocus (this was a typo, not intentional).
  • The open attribute is now part of the popup proposal. We're omitting the hidden attribute now given HTML editor/contributor interest in addressing some of the quirky behavior with dialog and removing the open attribute.
  • A popup attribute has been added to the proposal. This is applicable to a subset of interactive elements and can be used to invoke the popup without script. We considered using the for attribute for this (applied to the invoker element), but we felt this might be confusing for authors ("isn't my popup for this combobox input?"). Happy to bikeshed on this though.
    • We still consider invocation/controller relationships to be separate from anchoring, as your invoker may not always be your anchor. And you may have an anchor but no invoker element.
    • The popup attribute now also negates the need for aria-haspopup and aria-controls. Equivalent accessibility semantics will be mapped as a result of this attribute.
  • We weren't sure that the change to event bubbling was providing the right value in exchange for the added platform complexity, so we've moved this to the appendix and will track any author feedback on this.

Anchoring

  • The anchor attribute is meant only to be a hook for a CSS-based scheme that we have not yet published (working out how to deal with a couple specific use cases). I'll publish on the CSS issue thread with where our thinking is at right now.
  • We did chat about anchoring reordering trees, as the accessibility tree order matters in addition to the right tab cycle. While we hope that due to the top-layer positioning of popup it would become less of a common practice to insert the popup somewhere separate in the DOM, I think we need to anticipate having to heal distant anchors and popups. We weren't quite sure whether this reordering capability should be tied to the popup attribute, anchor attribute, or some fallback scenario between the two, so this was added as an open question.

Focus

  • Re "Are there use cases of showing the popup but not focusing it?": teaching UI is certainly one of these. With comboboxes, you also want to keep your focus in the text input by default even as you show available options in the listbox. And there are menu button + popup patterns where invoking the button shows the popup menu, but focus does not move into the menu until the user presses the down arrow key, for example.
  • I agree that the delegatesfocus attribute could be extended to other elements. This seems like a good one to raise in Open UI and similar forums to find out what other use cases authors might be tracking.

@torgo
Copy link
Member

torgo commented Mar 10, 2021

Thanks @melanierichards for letting us know about this. I'm putting this on our agenda for next week and we hope to have feedback back to you by then.

@melanierichards
Copy link

Thanks to @torgo and the rest of TAG!

As a heads up, the Open UI CG resolved to take up this work item for incubation before we bring any formal changes to the HTML spec (we have shared the early ideas with WHATWG, however). This doesn't have any bearing on the design of the APIs as of yet, but I thought it might be useful to know where we'll first take up any TAG feedback. Thanks again!

@LeaVerou
Copy link
Member

Thank you for the updates @melanierichards! It's good to see progress on this!

We discussed this again this Monday, and concluded that since this is essentially a two-part proposal (the HTML element and the CSS positioning scheme it hooks into), we would need to see both parts to review it further. Without this essential component, it is difficult to properly evaluate things like the anchor or popup attributes.

Therefore, we are going to close this early review and will continue to monitor open issues for a future review request where we can look at the entire proposal.

There was also some discussion on lower level design decisions in the breakout that you might find useful.

@LeaVerou LeaVerou added Resolution: too early Possibly too early for review or not enough info provided and removed Progress: in progress Progress: pending external feedback The TAG is waiting on response to comments/questions asked by the TAG during the review labels Mar 18, 2021
@melanierichards
Copy link

Thank you @LeaVerou & co, will re-file once we've got all our cohesive thoughts on anchored positioning down on paper! :)

@melanierichards
Copy link

Hi @LeaVerou @hober @kenchris and @atanassov, wanted to share an update with you in case it's a good time to revisit this review. (Please let us know if a separate issue is preferable to reopening this one, thought it nice that the history was here)

<popup> itself is in active incubation in the Open UI CG: initial proposal, issues we are working through, first editor's draft PR

CSS Anchored Positioning Scheme

  • An initial proposal has been published. We have two viable proposals here for a path forward: the primary at-rules-based syntax, and an "Alternate A" syntax which uses a position-set() function within various property values. We think that actually Alternate A might be a bit better implementation-wise, as it avoids a style-on-layout dependency introduced by the at-rules syntax. However, we've invited author feedback on the ergonomics of the various options; TBD on an assessment there.
  • The initial proposal aims to give enough flexibility to cover known use cases for anchored positioning. However, some authors may prefer "magic" over control (w/r/t repositioning anchored elements) and might find the current syntax somewhat overpowered for their use case. We plan to discuss how the proposals could evolve to empower 1) the developer who wants to express a preferred position and let the UA handle fallbacks and 2) the developer who has very specific requirements as to positioning-aware styling and fallback positioning logic.
  • The proposal is limited to browser-managed, top-layer elements for now, due to perf reasons. We want to see what we can do to expand that scope, even if the use of this scheme is not completely unrestricted.
  • Open UI has agreed to incubate this proposal/discussion and get it to a more mature place before formally bringing this proposal to CSSWG for specification. CSSWG has been notified of this work. FYI, given that the reviewers are chairs/members of CSS: we plan to request a 5 minute agenda item presenting this scheme/inviting collaboration in Open UI. That will occur after yours truly is out of office next week. :)

Clearly, we're still early in co-designing a solution here for anchored positioning, but we wanted to prioritize giving the TAG a heads up. Thanks in advance!

cc / @mfreed7 @BoCupp-Microsoft

@mfreed7
Copy link
Author

mfreed7 commented Jun 18, 2021

Thanks @melanierichards!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: too early Possibly too early for review or not enough info provided Review type: CG early review An early review of general direction from a Community Group Topic: HTML
Projects
None yet
Development

No branches or pull requests

8 participants