Add meta on 'focus' event


#1

Hello,

This post is a follow up of an other post I’ve made in the chromium discussion group: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-discuss/nHH_y7yWRAY.

Context

We have video controls which are usually displayed for 3s when user interacts with the player. After this delay controls are hidden because what matters is the video being played.

Feature

In this context, only when user navigates using keyboard, we want to keep controls visible until they loose focus, instead of 3s ellapsed without interaction.

Solution right now

let fromMouse = false
element.addEventListener('mousedown', () => {
 fromMouse = true
 setTimeout(() => {
    fromMouse = false
  })
})
element.addEventListener('focus', () => {
  const mustKeepControlsVisible = fromMouse === false
})

This solution is almost what we are planning to use in production. I would like to suggest something more reliable.

Proposal

Add relatedEvent to focus and blur events. This new property may be one of null, mousedownEvent, touchstartEvent and keydownEvent.

element.addEventListener('focus', (e) => {
  const mustKeepControlsVisible = e.relatedEvent && e.relatedEvent.type === 'keydown'
})

Existing proposals on same subject

Introduce a new CSS selector, :serial-focus that could be used to differentiate focus.

element.addEventListener('focus', () => {
  const mustKeepControlsVisible = element.matches(':serial-focus')
})

Also introduce a new CSS selector, :visual-focus-ring-is-not-required that could be used as shown below.

element.addEventListener('focus', () => {
  const mustKeepControlsVisible = element.matches(':visual-focus-ring-is-not-required') === false
})

Please let me know what you think :slight_smile:


#2

Can i ask you to clarify what your pseudo classes (particularly the second one) would match exactly? I feel like the :focus-visible proposal in selectors level 4 (currently in flux a bit) is the closest thing that might give you useful information here but I’m trying to make sure that I understand what you’re saying.


#3

I wanted to show how my problem could be solved by other existing proposal. They are not mine so my explanation may be mistaken.

  • :serial-focus proposal would match when element is focused in the context of a sequential navigation. Clicking would not be a sequential navigation while tabbing would.

  • :visual-focus-ring-is-not-required would match when focus is not given an input device used for navigation (keyboard, …). Also when accessibility service (voiceover,…) are inexistent of disabled.

Indeed, focus-visible would be enough :thinking:

element.addEventListener('focus', () => {
  const mustKeepControlsVisible = element.matches(':focus-visible')
})

#4

In this context, only when user navigates using keyboard, we want to keep controls visible until they loose focus, instead of 3s ellapsed without interaction.

Why would the user want to shift focus (possibly leaving the video and jumping to, say, the next link, thereby potentially moving the video out of view)?

Indeed, :focus-visible would be enough

If I’m not mistaking the d-pad navigation on a TV’s remote control is also considered keyboard input and would therefore keep the controls visible.


#5

Why would the user want to shift focus (possibly leaving the video and jumping to, say, the next link, thereby potentially moving the video out of view)?

I would say because user wants to navigate through controls in order to activate one of them using space/enter. When user tabs out, on the next link for instance, we would hide controls until they receive back the focus.

If I’m not mistaking the d-pad navigation on a TV’s remote control is also considered keyboard input and would therefore keep the controls visible.

It makes sense and that’s what we want. While user moves focus using keyboard or a TV remote control we want to keep controls visible so that they are not hidden while user is navigating through them.