ComposedFocusMixin

Normalizes focus treatment for custom elements with Shadow DOM

Overview

Purpose: Normalizes focus treatment for custom elements with Shadow DOM

This mixin works at the beginning of the Elix render pipeline:

eventsmethods → setState → render DOM → post-render

Provides the component with:

  • mousedown event listener that provides default focus-handling behavior.

Usage

import ComposedFocusMixin from "elix/src/base/ComposedFocusMixin.js";
class MyElement extends ComposedFocusMixin(HTMLElement) {}

This mixin exists because the default behavior for mousedown should set the focus to the closest ancestor of the clicked element that can take the focus. As of Nov 2018, Chrome and Safari don't handle this as expected when the clicked element is reassigned across more than one slot to end up inside a focusable element. In such cases, the focus will end up on the body. Firefox exhibits the behavior we want. See https://github.com/w3c/webcomponents/issues/773.

This mixin normalizes behavior to provide what Firefox does. When the user mouses down inside anywhere inside the component's light DOM or Shadow DOM, we walk up the composed tree to find the first element that can take the focus and put the focus on it.