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

Editorial review: Document popover="hint" #37990

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion files/en-us/web/api/htmlelement/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ _Also inherits properties from its parent, {{DOMxRef("Element")}}._
As a getter, it is the same as {{DOMxRef("HTMLElement.innerText")}} (it represents the rendered text content of an element and its descendants).
As a setter, it replaces the selected node and its contents with the given value, converting any line breaks into {{HTMLElement("br")}} elements.
- {{domxref("HTMLElement.popover")}}
- : Gets and sets an element's popover state via JavaScript (`"auto"` or `"manual"`), and can be used for feature detection. Reflects the value of the [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover) global HTML attribute.
- : Gets and sets an element's popover state via JavaScript (`"auto"`, `"hint"`, or `"manual"`), and can be used for feature detection. Reflects the value of the [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover) global HTML attribute.
- {{DOMxRef("HTMLElement.spellcheck")}}
- : A boolean value that controls the [spell-checking](/en-US/docs/Web/HTML/Global_attributes/spellcheck) hint. It is available on all HTML elements, though it doesn't affect all of them.
- {{DOMxRef("HTMLElement.style")}}
Expand Down
23 changes: 16 additions & 7 deletions files/en-us/web/api/htmlelement/popover/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,29 @@ browser-compat: api.HTMLElement.popover

{{APIRef("Popover API")}}

The **`popover`** property of the {{domxref("HTMLElement")}} interface gets and sets an element's popover state via JavaScript (`"auto"` or `"manual"`), and can be used for feature detection.
The **`popover`** property of the {{domxref("HTMLElement")}} interface gets and sets an element's popover state via JavaScript (`"auto"`, `"hint"`, or `"manual"`), and can be used for feature detection.

It reflects the value of the [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover) global HTML attribute.

## Value

An enumerated value; possible values are:

- `"auto"`: In [auto state](/en-US/docs/Web/API/Popover_API/Using#auto_state_and_light_dismiss):
- The popover can be "light dismissed" — this means that you can hide the popover by clicking outside it or pressing the <kbd>Esc</kbd> key.
- Usually, only one popover can be shown at a time — showing a second popover when one is already shown will hide the first one. The exception to this rule is when you have nested auto popovers. See [Nested popovers](/en-US/docs/Web/API/Popover_API/Using#nested_popovers) for more details.
- `"manual"`: In [manual state](/en-US/docs/Web/API/Popover_API/Using#using_manual_popover_state):
- The popover cannot be "light dismissed", although declarative show/hide/toggle buttons will still work.
- Multiple independent popovers can be shown at a time.
- `"auto"`

- : In [auto state](/en-US/docs/Web/API/Popover_API/Using#auto_state_and_light_dismiss):
- Popovers can be "light dismissed" — this means that you can hide the popover by clicking outside it or pressing the <kbd>Esc</kbd> key.
- Usually, only one popover can be shown at a time — showing a second popover when one is already shown will hide the first one. The exception to this rule is when you have nested auto popovers. See [Nested popovers](/en-US/docs/Web/API/Popover_API/Using#nested_popovers) for more details.
hamishwillee marked this conversation as resolved.
Show resolved Hide resolved

- `"hint"`

- : [`hint`](/en-US/docs/Web/API/Popover_API/Using#using_hint_popover_state) popovers are similar to `auto` popovers, but with a significant difference. They can be light-dismissed, but they do not light-dismiss `auto` popovers when shown, only `hint` popovers. `hint` popovers tend to be shown and hidden in response to non-click JavaScript events such as [`mouseover`](/en-US/docs/Web/API/Element/mouseover_event)/[`mouseout`](/en-US/docs/Web/API/Element/mouseout_event) and [`focus`](/en-US/docs/Web/API/Element/focus_event)/[`blur`](/en-US/docs/Web/API/Element/blur_event). When clicking on a button, the click itself would cause an open `auto` popover to light-dismiss.
hamishwillee marked this conversation as resolved.
Show resolved Hide resolved

- `"manual"`

- : In [manual state](/en-US/docs/Web/API/Popover_API/Using#using_manual_popover_state):
hamishwillee marked this conversation as resolved.
Show resolved Hide resolved
- Popovers cannot be "light dismissed", although declarative show/hide/toggle buttons will still work.
- Multiple independent popovers can be shown at a time.
hamishwillee marked this conversation as resolved.
Show resolved Hide resolved

## Examples

Expand Down
4 changes: 2 additions & 2 deletions files/en-us/web/api/popover_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ See [Using the popover API](/en-US/docs/Web/API/Popover_API/Using) for a detaile
## HTML attributes

- [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover)
- : A global attribute that turns an element into a popover element; takes a popover state (`"auto"` or `"manual"`) as its value.
- : A global attribute that turns an element into a popover element; takes a popover state (`"auto"`, `"hint"`, or `"manual"`) as its value.
- [`popovertarget`](/en-US/docs/Web/HTML/Element/button#popovertarget)
- : Turns a {{htmlelement("button")}} or {{htmlelement("input")}} element into a popover control button; takes the ID of the popover element to control as its value.
- [`popovertargetaction`](/en-US/docs/Web/HTML/Element/button#popovertargetaction)
Expand All @@ -64,7 +64,7 @@ See [Using the popover API](/en-US/docs/Web/API/Popover_API/Using) for a detaile
### Instance properties

- {{domxref("HTMLElement.popover")}}
- : Gets and sets an element's popover state via JavaScript (`"auto"` or `"manual"`), and can be used for feature detection. Reflects the value of the [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover) global HTML attribute.
- : Gets and sets an element's popover state via JavaScript (`"auto"`, `"hint"`, or `"manual"`), and can be used for feature detection. Reflects the value of the [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover) global HTML attribute.
- {{domxref("HTMLButtonElement.popoverTargetElement")}} and {{domxref("HTMLInputElement.popoverTargetElement")}}
- : Gets and sets the popover element being controlled by the control button. The JavaScript equivalent of the [`popovertarget`](/en-US/docs/Web/HTML/Element/button#popovertarget) HTML attribute.
- {{domxref("HTMLButtonElement.popoverTargetAction")}} and {{domxref("HTMLInputElement.popoverTargetAction")}}
Expand Down
97 changes: 96 additions & 1 deletion files/en-us/web/api/popover_api/using/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ You can see the behavior described above in action in our [Multiple auto popover

## Using manual popover state

The alternative to auto state is **manual state**, achieved by setting `popover="manual"` on your popover element:
One alternative to auto state is **manual state**, achieved by setting `popover="manual"` on your popover element:

```html
<div id="mypopover" popover="manual">Popover content</div>
Expand Down Expand Up @@ -190,6 +190,101 @@ There are three different ways to create nested popovers:

See our [Nested popover menu example](https://mdn.github.io/dom-examples/popover-api/nested-popovers/) ([source](https://github.com/mdn/dom-examples/tree/main/popover-api/nested-popovers)) for an example. You'll notice that quite a few event handlers have been used to display and hide the subpopover appropriately during mouse and keyboard access, and also to hide both menus when an option is selected from either. Depending on how you handle loading of new content, either in an SPA or multi-page website, some of all of these may not be necessary, but they have been included in this demo for illustrative purposes.

## Using "hint" popover state
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the policy is on documenting stuff that only applies in the middle stage where some browsers support hint but others don't. But it might be worth pointing out that popover="hint" will fallback to a manual popover in unsupporting browsers rather than auto.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a quick note in my next commit. I think it's worth including, and we can always remove it when all modern browsers catch up.


There is a third type of popover you can create — **hint popovers**, designated by setting `popover="hint"` on your popover element. `hint` popovers are similar to `auto` popovers, but with a significant difference. They can be light-dismissed, but they do not light-dismiss `auto` popovers when shown, only `hint` popovers.

This is useful for situations where, for example, you have toolbar buttons that can be pressed to show UI popovers, but you also want to reveal tooltips when the buttons are hovered, without dismissing the UI popovers.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

`hint` popovers tend to be shown and hidden in response to non-click JavaScript events such as [`mouseover`](/en-US/docs/Web/API/Element/mouseover_event)/[`mouseout`](/en-US/docs/Web/API/Element/mouseout_event) and [`focus`](/en-US/docs/Web/API/Element/focus_event)/[`blur`](/en-US/docs/Web/API/Element/blur_event). When clicking on a button, the click itself would cause an open `auto` popover to light-dismiss.

See our [popover hint demo](https://mdn.github.io/dom-examples/popover-api/popover-hint/) ([source](https://github.com/mdn/dom-examples/tree/main/popover-api/popover-hint)) for an example that behaves exactly as described above. The demo features a button bar; when pressed, the buttons show popup sub-menus inside which further options can be selected. However, when hovered over or focused, the buttons also show tooltips to give the user an idea of what each button does.

In the below sections, we'll walk through all the important parts of the code.

### Creating the sub-menus with `popover="auto"`

The popup sub-menus are created declaratively, using `auto` popovers. First, the control buttons:

```html
<section id="button-bar">
<button popovertarget="submenu-1" popovertargetaction="toggle" id="menu-1">
Menu A
</button>

<button popovertarget="submenu-2" popovertargetaction="toggle" id="menu-2">
Menu B
</button>

<button popovertarget="submenu-3" popovertargetaction="toggle" id="menu-3">
Menu C
</button>
</section>
```

Now, the popovers themselves:

```html
<div id="submenu-1" popover="auto">
<button>Option A</button><br /><button>Option B</button>
</div>
<div id="submenu-2" popover="auto">
<button>Option A</button><br /><button>Option B</button>
</div>
<div id="submenu-3" popover="auto">
<button>Option A</button><br /><button>Option B</button>
</div>
```

### Creating the tooltips with `popover="hint"`

The sub-menu popovers work fine as they are, opening when the toolbar buttons are clicked, but how do we also show tooltips on button hover/focus? First, we create the tooltips in HTML, using `hint` popovers:

```html
<div id="tooltip-1" class="tooltip" popover="hint">Tooltip A</div>
<div id="tooltip-2" class="tooltip" popover="hint">Tooltip B</div>
<div id="tooltip-3" class="tooltip" popover="hint">Tooltip C</div>
```

To control the showing/hiding, we need to use JavaScript. First of all, we grab references to the `hint` popovers and the control buttons in two separate {{domxref("NodeList")}}s using {{domxref("Document.querySelectorAll()")}}:

```js
const tooltips = document.querySelectorAll(".tooltip");
const btns = document.querySelectorAll("#button-bar button");
```

Next, we create a function, `addEventListeners()`, which sets four event listeners (via {{domxref("EventTarget.addEventListener()")}}) on a given {{htmlelement("button")}}, chosen by grabbing the `<button>` at a specific index value of the `btns` `NodeList`. The functions act on the `hint` popover at the same index value of the `tooltips` `NodeList`, allowing us to keep the buttons and the tooltips in sync — showing/hiding the correct tooltip when a button is interacted with.

The event listeners [show](/en-US/docs/Web/API/HTMLElement/showPopover) the popover on [`mouseover`](/en-US/docs/Web/API/Element/mouseover_event) and [`focus`](/en-US/docs/Web/API/Element/focus_event), and [hide](/en-US/docs/Web/API/HTMLElement/hidePopover) the popover on [`mouseout`](/en-US/docs/Web/API/Element/mouseout_event) and [`blur`](/en-US/docs/Web/API/Element/blur_event), meaning that the tooltips can be accessed via mouse and keyboard.

```js
function addEventListeners(i) {
btns[i].addEventListener("mouseover", () => {
tooltips[i].showPopover();
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
});

btns[i].addEventListener("mouseout", () => {
tooltips[i].hidePopover();
});

btns[i].addEventListener("focus", () => {
tooltips[i].showPopover();
});

btns[i].addEventListener("blur", () => {
tooltips[i].hidePopover();
});
}
```

Finally, we use a [`for`](/en-US/docs/Web/JavaScript/Reference/Statements/for) loop to iterate through the `<buttons>` in the `btns` `NodeList`, calling the `addEventListeners()` function for each one so that all of them have the desired event listeners set.

```js
for (let i = 0; i < btns.length; i++) {
addEventListeners(i);
}
```

## Styling popovers

The popover API has some related CSS features available that are worth looking at.
Expand Down
20 changes: 17 additions & 3 deletions files/en-us/web/html/global_attributes/popover/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,27 @@ browser-compat: html.global_attributes.popover

The **`popover`** [global attribute](/en-US/docs/Web/HTML/Global_attributes) is used to designate an element as a popover element.

## Value

The `popover` attribute can take one of the following values:

- `auto` (setting `popover` is equivalent to setting `popover="auto"`)
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
- `hint`
- `manual`

## Description

Popover elements are hidden via `display: none` until opened via an invoking/control element (i.e. a `<button>` or `<input type="button">` with a [`popovertarget`](/en-US/docs/Web/HTML/Element/button#popovertarget) attribute) or a {{domxref("HTMLElement.showPopover()")}} call.

When open, popover elements will appear above all other elements in the {{glossary("top layer")}}, and won't be influenced by parent elements' {{cssxref('position')}} or {{cssxref('overflow')}} styling.

A popover attribute can have values [`"auto"`](/en-US/docs/Web/API/Popover_API/Using#auto_state_and_light_dismiss) (default) or [`"manual"`](/en-US/docs/Web/API/Popover_API/Using#using_manual_popover_state).
Popovers that have the `auto` state can be "light dismissed" by selecting outside the popover area, and generally only allow one popover to be displayed on-screen at a time.
By contrast, `manual` popovers must always be explicitly hidden, but allow for use cases such as nested popovers in menus.
Popovers that have the [`auto`](/en-US/docs/Web/API/Popover_API/Using#auto_state_and_light_dismiss) state can be shown and hidden using associated controls (designated by the [`popovertarget`](/en-US/docs/Web/HTML/Element/button#popovertarget) attribute, ) and "light dismissed" by clicking outside the popover area, opening another popover, or pressing browser-specific mechanisms such as the <kbd>Esc</kbd> key. Generally only one `auto` popover can be displayed on-screen at a time — showing a second popover when one is already shown will hide the first one. They can also be controlled using JavaScript, for example the {{domxref("HTMLElement.togglePopover()")}} method can be used to toggle a popover between shown and hidden.

By contrast, [`manual`](/en-US/docs/Web/API/Popover_API/Using#using_manual_popover_state) popovers can't be light dismissed — they must be manually shown and hidden. This allows for use cases where you want to show multiple popovers at the same time.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

[`hint`](/en-US/docs/Web/API/Popover_API/Using#using_hint_popover_state) popovers are similar to `auto` popovers, but with a significant difference. They can be light-dismissed, but they do not light-dismiss `auto` popovers when shown, only `hint` popovers. This is useful for situations where, for example, you have toolbar buttons that can be pressed to show UI popovers, but you also want to reveal tooltips when the buttons are hovered, without dismissing the UI popovers.

`hint` popovers tend to be shown and hidden in response to non-click JavaScript events such as [`mouseover`](/en-US/docs/Web/API/Element/mouseover_event)/[`mouseout`](/en-US/docs/Web/API/Element/mouseout_event) and [`focus`](/en-US/docs/Web/API/Element/focus_event)/[`blur`](/en-US/docs/Web/API/Element/blur_event). When clicking on a button, the click itself would cause an open `auto` popover to light-dismiss.

For detailed information on usage, see the {{domxref("Popover API", "Popover API", "", "nocode")}} landing page.

Expand Down