Skip to content

Commit f4ad361

Browse files
authored
Update a11y section and add FAQ about hot-key vs. focus (#1155)
1 parent b4c89b0 commit f4ad361

File tree

1 file changed

+97
-23
lines changed

1 file changed

+97
-23
lines changed

site/src/pages/components/interest-invokers.explainer.mdx

Lines changed: 97 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,35 @@ layout: ../../layouts/ComponentLayout.astro
1010
## Table of Contents
1111
{/* DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE */}
1212

13+
- [Table of Contents](#table-of-contents)
1314
- [The Pitch in Code](#the-pitch-in-code)
1415
- [Introduction](#introduction)
15-
- [HIDs and interest](#hids-and-interest)
16+
- [HIDs and Interest](#hids-and-interest)
1617
- [Mouse](#mouse)
1718
- [Keyboard](#keyboard)
1819
- [Touchscreen](#touchscreen)
1920
- [Other](#other)
2021
- [Mouse delays](#mouse-delays)
21-
- [Why No `interestaction` Attribute?](#why-no-interestaction-attribute)
22+
- [The `:has-interest` Pseudo Class](#the-has-interest-pseudo-class)
2223
- [Implementation Details](#implementation-details)
2324
- [Example Code](#example-code)
2425
- [Popovers](#popovers)
2526
- [Custom delays and multiple actions](#custom-delays-and-multiple-actions)
2627
- [Custom behaviour](#custom-behaviour)
28+
- [Feature detection](#feature-detection)
2729
- [Mockups](#mockups)
2830
- [Touchscreen hovercard](#touchscreen-hovercard)
2931
- [Accessibility](#accessibility)
30-
- [PAQ (Potentially Asked Questions)](#paq-potentially-asked-questions)
32+
- [Plain hints (aka tooltips)](#plain-hints-aka-tooltips)
33+
- [Rich hints (aka hovercards or other)](#rich-hints-aka-hovercards-or-other)
34+
- [FAQ (Frequently Asked Questions)](#faq-frequently-asked-questions)
35+
- [Why No `interestaction` Attribute?](#why-no-interestaction-attribute)
36+
- [Why a keyboard hot-key and not just keyboard focus?](#why-a-keyboard-hot-key-and-not-just-keyboard-focus)
3137
- [Why the name `interest`? Why not `hover` or `focus`?](#why-the-name-interest-why-not-hover-or-focus)
32-
- [Why is `interesttarget` on a lot more elements than `commandfor`?](#why-is-interesttarget-on-a-lot-more-elements-than-commandfor)
38+
- [Why is `interesttarget` supported on more elements than `commandfor`?](#why-is-interesttarget-supported-on-more-elements-than-commandfor)
3339
- [Why is `interesttarget` not unlimited, like `title` is?](#why-is-interesttarget-not-unlimited-like-title-is)
3440
- [Safe Area Triangle](#safe-area-triangle)
41+
- [What if I (the developer) don't want the touchscreen context menu](#what-if-i-the-developer-dont-want-the-touchscreen-context-menu)
3542

3643

3744
## The Pitch in Code
@@ -73,7 +80,11 @@ Mouse users will show interest in an element by mouse-hovering the element for a
7380

7481
### Keyboard
7582

76-
For keyboard users, the UA will provide a hot-key such as Alt-Down, which will "show interest" in the element. Another hot-key such as the ESC key will provide a way to trigger "loseinterest". These hot-keys must be chosen by the UA to be convenient for the user, while also not conflicting with existing UA-provided and OS-provided hot-keys.
83+
For keyboard users, the UA will provide a hot-key such as Alt-Down, which will "show interest" in the element. Another hot-key such as the ESC key will provide a way to trigger "loseinterest". These hot-keys must be chosen by the UA to be convenient for the user, while also not conflicting with existing UA-provided and OS-provided hot-keys. Other ideas include Alt-Space or Ctrl-Space for the show interest hot key.
84+
85+
Additionally, the appearance of the focus ring will be altered slightly when focus is on elements with `interesttarget`. This allows the user to discover that something is "different" about this element, and know that the keyboard activation hot-key will allow them to show interest. Since accessibility guidelines state that color alone cannot be enough to differentiate states, this focus ring change will likely need to be something like a slightly-thicker outline, or other shape change.
86+
87+
An alternative idea is to instead change the "location" hint that most browsers include in the lower-left corner when focusing a link element. This area currently shows the destination URL for the link, but it could have additional text added such as "press alt-down for additional information" when an element with `interesttarget` is focused. This could also be shown on the bottom-right side of the screen, to avoid interfering with the URL hint.
7788

7889
See https://github.com/openui/open-ui/issues/1133 for a much more detailed conversation with developers about keyboard behavior. That extended discussion led to the behaviors described in this section.
7990

@@ -114,13 +125,6 @@ There was some discussion about the need to allow UAs to modify these delays bas
114125

115126
See https://github.com/w3c/csswg-drafts/issues/9236 for a much more detailed conversation about these hover delay settings. That extended discussion led to the behaviors described in this section. Notably, the OP and initial comments started in a somewhat different place than the eventual conclusion, which is what is described here.
116127

117-
## Why No `interestaction` Attribute?
118-
119-
The `command`/`commandfor` API, as its name suggests, provides *two* attributes. One (`commandfor`) is the link to the target element, and the other (`command`) describes what action to take on the target element. That is appropriate, because when activating a button, many different types of actions could be desired, even for the same target element. A button might want to open, open-modal, close, **or** request-close a dialog, for example. Or it might want to play, pause, **or** mute a video.
120-
121-
The same is not true for `interesttarget`. When the target is a popover, the only set of actions that makes sense is to *show* the popover when interest is shown, and *hide* the popover when interest is lost. There are no identified use cases that invert those actions. Alternatively, defining show and lose interest actions to both *toggle* the popover can lead to serious out-of-sync problems that would be major footguns. So for popovers, there is no need for a separate attribute controlling the behavior, because there is only one rational set of behaviors. And as described above, popovers are the only kind of target element that comes with default actions. Other actions might use the `"interest"` and `"loseinterest"` events to add additional behavior, but in that case, they can provide their own definitions of actions to take. And again because of the above points, there isn't a future-compat problem like there might be for the `commandfor` attribute.
122-
123-
See https://github.com/openui/open-ui/issues/1064#issuecomment-2581511411 (particularly [this comment](https://github.com/openui/open-ui/issues/1064#issuecomment-2581511411)) for more discussion of this section.
124128

125129
## The `:has-interest` Pseudo Class
126130

@@ -233,6 +237,14 @@ The `InterestEvent` interface allows for custom JavaScript to be triggered when
233237
</script>
234238
```
235239
240+
### Feature detection
241+
242+
To feature-detect this overall API, the following code does the trick:
243+
244+
```javascript
245+
const supported = HTMLButtonElement.prototype.hasOwnProperty("interestTargetElement");
246+
```
247+
236248
## Mockups
237249
238250
### Touchscreen hovercard
@@ -247,16 +259,76 @@ Using those insets, a developer could implement a long-press activated hovercard
247259
248260
## Accessibility
249261
250-
> Warning: This section is TBD. PRs and discussions welcome.
262+
Since `popover=hint` is a common target for `interesttarget`, for the purpose of building "tooltips" and "hovercards", there are a few additional definitions and considerations:
263+
264+
- When the target is a `popover=hint` element, and that hint popover contains only elements with a computed role of generic, text or image, we will call that a **"plain hint"**.
265+
- When the target is a `popover=auto` or `popover=manual`, or it is a `popover=hint` with contents beyond those allowed by "plain hint", then we will call that a **"rich hint"**.
266+
267+
### Plain hints (aka tooltips)
268+
269+
For a screen reader user, there already exist simple settings and commands to read accessible descriptions, which are just an additional piece of text associated with an object, such as used by a `title` or `aria-description` attribute. When a plain hint is just used for a prettier tooltip, a screen reader can reuse this simple mechanism and act like a title was present. There is no need for the user to navigate to the hint popover itself, since there's nothing to explore.
270+
271+
For the above reason, the browser will simply expose the the contents of a plain hint on the interest invoker element. The actual popover element and its descendants can be invisible/ignored in the AX tree. In particular:
272+
273+
1. If no other accessible name is available, use the `popover=hint`’s inner text for the accessible name.
274+
2. If it's used as the name, then use it to compute the description, setting the `describedby` relation to point from the interest invoker to the hint element
275+
3. There is no need to make `aria-details` connections or set `aria-expanded` on the interest invoker for plain hints.
251276
252-
See the [`popover=hint` explainer's accessibility section](../popover-hint.research.explainer/#a11y-api-support) for additional comments. In particular, many of the relationships that are provided for "regular" invokers such as `popovertarget` apply to interest-based invokers also. For example, an `aria-details` relationship should be established between an interest invoker and its target, and `aria-expanded` should be set when the target is open.
277+
### Rich hints (aka hovercards or other)
253278
254-
One nuance of hovercards is that for "simple" hovercards that only contain non-interactive content, it's possible that rather than establishing the above ARIA relationships, it might be better to simply use the content of the hovercard as the accessible description for the triggering element.
279+
Since rich hints have additional content that might want to be explored directly, additional connections need to be made here:
255280
256-
In particular, for interest-based triggering of popovers, there is a problem with hidden objects. In general, the details relation does not work for hidden objects, and we can’t necessarily expect the popover to be complete before it becomes visible, as that may happen on-demand. So what happens if the user navigates to a popover’s trigger, and it’s not open? If they are using a keyboard, then we can make sure the popover is shown when the hot-key is pressed. But, if they are navigating with a virtual buffer as is likely, how will they trigger the hint popover to open? And once it's open, how will the user know it’s there? Should we use a new value of the haspopup object attribute for these, e.g. `haspopup=hint`? See https://issues.chromium.org/issues/377923492 for more discussion.
281+
- Set a [minimum role](https://www.w3.org/TR/html-aam-1.0/#dfn-minimum-role) of "tooltip" on the target popover.
282+
- Set `aria-expanded=true` when the rich hint is open, and `false` when it is not.
283+
- Create an `aria-details` relation between the interest invoker and the rich hint popover.
257284
285+
As with `popovertarget`, when a rich hint is shown, [sequential focus navigation](https://html.spec.whatwg.org/#focus-navigation-scope-owner) will be adjusted so that the target popover is "next" in the tab navigation cycle after the interest invoker. Since by definition "plain hints" do not have anything focusable, sequential focus navigation is not affected.
258286
259-
## PFAQ (Potentially/Frequently Asked Questions)
287+
See also, https://github.com/w3c/aria/issues/979.
288+
289+
## FAQ (Frequently Asked Questions)
290+
291+
### Why No `interestaction` Attribute?
292+
293+
The `command`/`commandfor` API, as its name suggests, provides *two* attributes. One (`commandfor`) is the link to the target element, and the other (`command`) describes what action to take on the target element. That is appropriate, because when activating a button, many different types of actions could be desired, even for the same target element. A button might want to open, open-modal, close, **or** request-close a dialog, for example. Or it might want to play, pause, **or** mute a video.
294+
295+
The same is not true for `interesttarget`. When the target is a popover, the only set of actions that makes sense is to *show* the popover when interest is shown, and *hide* the popover when interest is lost. There are no identified use cases that invert those actions. Alternatively, defining show and lose interest actions to both *toggle* the popover can lead to serious out-of-sync problems that would be major footguns. So for popovers, there is no need for a separate attribute controlling the behavior, because there is only one rational set of behaviors. And as described above, popovers are the only kind of target element that comes with default actions. Other actions might use the `"interest"` and `"loseinterest"` events to add additional behavior, but in that case, they can provide their own definitions of actions to take. And again because of the above points, there isn't a future-compat problem like there might be for the `commandfor` attribute.
296+
297+
See https://github.com/openui/open-ui/issues/1064#issuecomment-2581511411 (particularly [this comment](https://github.com/openui/open-ui/issues/1064#issuecomment-2581511411)) for more discussion of this section.
298+
299+
### Why a keyboard hot-key and not just keyboard focus?
300+
301+
There are pros and cons to both methods.
302+
303+
#### Focus element to show interest (possibly after delay)
304+
305+
There are two approaches: instantly show interest when an element is focused, or show interest after the element has been focused for a period of time. Most people seem to favor a delay, to avoid extreme annoyance for keyboard users. Perhaps re-use [the mouse delays](#Mouse-delays) or create a separate version for keyboard focus delays. To avoid accidental neglect of the keyboard delays/users, it might be better to re-use the same delays for both mouse and keyboard.
306+
307+
Pros:
308+
- very discoverable - simply focus an element and wait.
309+
310+
Cons:
311+
- hard to avoid / annoying. Users simply trying to keyboard-navigate through a document might inadvertently trigger popovers. Note that if the target popover is a "rich hint", it will be next in the tab navigation cycle, forcing the user on a "detour" in this case. It's further possible that the rich hint itself has additional interest targets, which can open their own rich hints, trapping the user for a significant number of tab stops.
312+
- can be slow to activate, due to the delay.
313+
314+
#### Hot-key to show interest
315+
316+
Pros:
317+
- No chance for "hijacking" the tab navigation cycle.
318+
- Fast/immediate to activate (no delays needed).
319+
320+
Cons:
321+
- Not very discoverable.
322+
323+
#### Conclusion: hot-key
324+
325+
Mouse users are fundamentally different from keyboard users, in that a mouse user can roughly-instantly move the mouse between any two arbitrary points on the screen. In contrast, keyboard users live within a sequential "linked list" of focusable elements, and can only navigate forward or backward, one step at a time. For this reason, keyboard users will have a harder time avoiding accidentally showing interest in elements that they merely stopped on briefly while navigating to another element. The same can be true for mouse users, if they stop their mouse while moving between points, but this is much more likely to happen via keyboard focus navigation.
326+
327+
Hot-keys of **all types** are often not very discoverable. "Power users" of the keyboard tend to search out these hot-keys and remember them, while "occasional" keyboard users do not. Here, we rely on the fact that most UX designers consider tooltips and hovercards to be "auxiliary" and not required for proper functioning of the site.
328+
329+
The idea (described in [the keyboard section](#Keyboard)) to add helpful text to the "location" area on the bottom left of the browser window may alleviate much of the lack of discoverability here.
330+
331+
See https://github.com/openui/open-ui/issues/1133.
260332
261333
### Why the name `interest`? Why not `hover` or `focus`?
262334
@@ -266,14 +338,20 @@ are not terms which encompass all viable methods of interaction. Many
266338
it was deemed that `interest` is the best name to explain the concept of a
267339
"hover or focus or equivalent".
268340
269-
### Why is `interesttarget` on a lot more elements than `commandfor`?
341+
See https://github.com/openui/open-ui/issues/1136.
342+
343+
### Why is `interesttarget` supported on more elements than `commandfor`?
270344
271345
While _invocation_ should only be limited to buttons, disclosure of
272346
supplementary information can be expanded to _all_ interactive elements. There
273347
are many useful use cases for offering a hovercard on anchors, such as signalling
274348
that they are external, or that they will open in a new window, or to show
275349
preview information (think: preview windows on iOS Safari or the hovercards that
276-
display on GitHub over a user's handle).
350+
display on GitHub over a user's handle). To start, a limited set of elements is
351+
supported, to make sure they can be made accessibly. This set could be expanded
352+
in the future.
353+
354+
See https://github.com/openui/open-ui/issues/839.
277355
278356
### Why is `interesttarget` not unlimited, like `title` is?
279357
@@ -288,10 +366,6 @@ For example, *arbitrary* elements are not usually focusable, and it is unclear h
288366
289367
The events `interest` and `loseinterest` are intentionally abstract to allow more complex usability concepts to unfold. It is possible that a future capability might be to add automatic "safe areas" or "hit triangles", which allow the user to move the pointer between the Interest Invoker (e.g. the button) and Interestee (e.g. the hovercard), regardless of the `interest-target-hide-delay` setting. See [#963](https://github.com/openui/open-ui/issues/963) for more.
290368
291-
### Is `interesttarget` the right name?
292-
293-
See https://github.com/openui/open-ui/issues/1136 for more discussion.
294-
295369
### What if I (the developer) don't want the touchscreen context menu
296370
297371
It might be the case that in some circumstances, the "developer knows best" that the UA-provided context menu isn't needed/helpful on some element that uses `interesttarget` attribute. In that case, the (existing) mechanism to do that is to call `preventDefault()` on the `contextmenu` event, which will cancel the UA menu.

0 commit comments

Comments
 (0)