Search code examples
javascriptgoogle-chromeshadow-domcustom-element

Why does [contenteditable] become unfocusable in Chrome 117 (and 118 beta)


I have been working on a project that creates a custom element with a <slot> in the shadowRoot. Starting with the release of Chrome 117 if someone clicks on a contenteditable div the element gains focus and they can type, however if you click away and back, then the element is no longer focusable. Here is a minimal example of this (demo):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <input id="test-input" />

    <example-component>
      <div contenteditable="true">
        <h1>Hello World!</h1>
        <p>This is an example</p>
      </div>
    </example-component>

    <script>
      customElements.define(
        "example-component",
        class extends HTMLElement {
          constructor() {
            super();
            this.attachShadow({ mode: "open" });
            this.shadowRoot.innerHTML = `
            <slot></slot>
          `;
          }
        }
      );
    </script>
  </body>
</html>

This bug only appears in Chrome version 117 (and 118 beta), and not in any other browsers (that I can test on my mac). Anyone have any ideas?


Solution

  • It appears to be a bug in Chrome (bug #1484447). A recent patch was committed (src) that updates /third_party/blink/renderer/core/css/resolver/style_resolver.cc (lines 1193 to 1201) and adds the following code:

    // contenteditable attribute (implemented by -webkit-user-modify) should
    // be propagated from shadow host to distributed node.
    if (!style_request.IsPseudoStyleRequest() && element.AssignedSlot()) {
      if (Element* parent = element.parentElement()) {
        if (const ComputedStyle* shadow_host_style =
                parent->GetComputedStyle()) {
          state.StyleBuilder().SetUserModify(shadow_host_style->UserModify());
        }
      }
    }
    

    This allows shadow host nodes to look above to their parent nodes to see if they are editable.