diff --git a/site/src/pages/components/popover-hint.research.explainer.mdx b/site/src/pages/components/popover-hint.research.explainer.mdx new file mode 100644 index 000000000..6c1272b40 --- /dev/null +++ b/site/src/pages/components/popover-hint.research.explainer.mdx @@ -0,0 +1,197 @@ +--- +menu: Proposals +name: Popover Hint and Hover (Explainer) +path: /components/popover-hint.research.explainer +pathToResearch: /components/popup.research +layout: ../../layouts/ComponentLayout.astro +--- + +- [@mfreed7](https://github.com/mfreed7), [@scottaohara](https://github.com/scottaohara), [@aleventhal](https://github.com/aleventhal) +- Last updated: July 10, 2023 + +A followup proposal to the [original Popover proposal](https://open-ui.org/components/popover.research.explainer/), which adds several features related to building hints/tooltips. + +{/* */} +{/* */} +## Table of Contents + +- [Background](#background) +- ["Hover" triggering](#hover-triggering) + - [Add the `hover` value](#add-the-hover-value) + - [CSS values to control delay](#css-values-to-control-delay) + - [Example buttons](#example-buttons) + - [Popover types](#popover-types) + - [Example menu](#example-menu) +- [`popover=hint` Behavior](#popoverhint-behavior) +- [Accessibility](#accessibility) + - [Why differentiate between rich and plain hints?](#why-differentiate-between-rich-and-plain-hints) + - [A11y API support](#a11y-api-support) +- [::tooltip pseudo element](#tooltip-pseudo-element) +- [Monkeypatch spec](#monkeypatch-spec) +- [Articles and References](#articles-and-references) + +{/* */} + + +# Background + +The [Popover API](https://html.spec.whatwg.org/multipage/C#the-popover-attribute) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API), [OpenUI Explainer](https://open-ui.org/components/popover.research.explainer/)) is now part of the HTML standard. It allows developers to create popovers of varying types and also easily trigger them from buttons, without using Javascript. + +This explainer discusses two important extensions of the Popover API: + +1. The ability to trigger popovers via a "hover" type interaction. +2. The ability to show a new type of popover for "hints". + +These two capabilities are orthogonal but closely related, and this explainer therefore discusses them both. + +The motivating use case, but certainly not the only use case, for these two capabilities is in the construction of "tooltips". Typically, tooltips are transient bits of additional information related to a bit of content. This additional information is *not required* and is supplementary in nature. Usually the user accesses this tooltip by hovering, keyboard-focusing, or long-pressing a control. + +# "Hover" triggering + +The existing popover API includes the concept of "invoking elements": + +```html + +
I'm a popover
+``` + +The `popovertarget` attribute can be used on buttons (and ``), and it points to the idref of an element with the `popover` attribute. In this configuration, clicking the button automatically shows the popover, without requiring Javascript. In addition, this linkage ensures that the accessibility tree is properly updated to represent the connection. The `popovertargetaction` attribute determines what action to take when the button is activated: `show`, `hide`, or `toggle`. + +## Add the `hover` value + +To support hover triggering, a new value is added: `popovertargetaction=hover`. When set to the `hover` value, the popover will be **shown** when the invoking element is **a)** hovered with the mouse, **b)** focused, or **c)** long-pressed (mobile). + +## CSS values to control delay + +The majority of hover-triggered UI has a set of delays associated with it. It tends to be jarring to the user if UI elements show up *immediately* upon hovering an element. For example, that causes elements to show and hide rapidly as the user moves their mouse across the screen. To allow the user to be more intentional, there is an expectation that the element of interest must be hovered for a short period of time before any popovers are triggered. Additionally, it is common for such hover-triggered popovers to also be hidden automatically when they are no longer hovered, again after a sufficient delay. This "hide delay" is particularly important in the case that there is a physical gap between the invoking element and the hint popover: the user must move the mouse from the invoker to the popover and cross that gap, and it is frustrating if the popover closes while that traversal is taking place. + +To facilitate these delays, two new CSS properties are added: + +- `popover-show-delay` - applied to the invoking element. The invoking element must be hovered, focused, or long-pressed for this long before the popover is shown. The default value for this property is `0.5s`. +- `popover-hide-delay` - applied to the popover. The invoking element *or* the popover must be **not** hovered, focused, or long-pressed for this long before the popover is hidden. The default value for this property is `infinity`. + +It is important to "debounce" these delays. Said another way, the delays are interpreted as *the time an element must be continuously hovered or de-hovered*. The naive Javascript implementation of this behavior is to just call `setTimeout(() => show/hidePopover(), delayValue)`. I.e. after the invoking element is hovered, wait `delayValue`, and then show the popover. But that does not properly handle the situation where the user hovers the element, and then de-hovers it, all within the delay time. In that case, no popover should be shown. Similarly, once the popover is shown and the user de-hovers the popover briefly but re-hoveres it again quickly, the popover should not close. + +## Example buttons + +Let's examine a small example: + +```html + +
Hint 1
+ + + +``` + +In this example, because of the `popover-show-delay: 0.3s`, hovering (with the mouse) or keyboard-focusing "Button 1", *and then waiting for 0.3 seconds* will cause "Hint 1" to be shown. It will stay showing as long as the button *or* the popover are hovered with the mouse or keyboard-focused. + +Because of the `popover-hide-delay: 0.6s`, the hint will be automatically hidden after 0.6 seconds, once "interest has left" the popover. That depends on how the popover was triggered: + +- If the invoker was **hovered** to trigger "Hint 1", then it will stay open as long as the invoker or the hint are still hovered. If the mouse if moved off of *both* the invoker and the hint for 0.6 seconds, the hint will be closed. +- If the invoker was **keyboard focused** to trigger "Hint 1", then it will stay open as long as focus is contained within either the invoker or the hint. If keyboard focus leaves both invoker and hint for 0.6 seconds, the hint will be closed. + +## Popover types + +The new hover-triggering functionality should work for all `popover` types. There are use cases, e.g. for `popover=auto`; for example, a nested menu structure where sub-menus are shown when items in the primary menu are hovered or focused. + +## Example menu + +```html + + +