Search code examples
javascriptreactjsmaterial-uiweb-componentshadow-dom

Presence of a <button> element prevents text being highlighted with React App in Web Component with Shadow DOM in Chrome


A weird issue, but I have a minimum reproducable example here: https://codesandbox.io/s/falling-architecture-hvrsd?file=/src/index.js

screenshot from example showing non-working state

screenshot from example showing working state

Using the divs at the top you can toggle between showing and hiding the button with the WHY? text, which will prevent and enable respectively, highlighting the text at the bottom Try and Highlight This Text and You only can if the button isn't shown.

I'm using a Web Component and Shadow DOM as this is for a chrome extension, and am looking to avoid conflicting styles.

You can comment out the web component stuff in index.js and just render the demo directly with ReactDOM.render() and this behavior will not be observed.

I am also not sure if it is limited to just <button> elements causing this.

EDIT: It works in Firefox, but not in Chrome or the newest Chromium Edge

let shadow = document.getElementById("root").attachShadow({ mode: 'open', delegatesFocus: true });
const button = document.createElement('button');
button.innerText='Test';

const p = document.createElement('p');
p.innerText = 'Cannot highlight this in Chrome';
shadow.appendChild(button);
shadow.appendChild(p);
<div id="root"></div>


Solution

  • Though I'm not sure of the inner-workings, it looks like it has something to do with const shadowRoot = this.attachShadow({ ... delegatesFocus: true}). If you set delegatesFocus to false, selection will work just fine. MDN indicates this is experimental and chrome-only: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus