igvteam / igv.js

Embeddable genomic visualization component based on the Integrative Genomics Viewer
MIT License
636 stars 224 forks source link

igv.js styling breaks inside shadow DOM #1795

Closed twrightsman closed 3 months ago

twrightsman commented 3 months ago

Embedding igv.js inside of a shadow DOM breaks the UI since the CSS is manually applied to the document root and cannot style elements inside of the shadow DOM.

See https://github.com/marimo-team/marimo/issues/1165 for an example.

jrobinso commented 3 months ago

That's not a use case we support, if you have suggestions please leave them here.

twrightsman commented 3 months ago

I appreciate your response @jrobinso. I understand if you're unwilling to support Marimo specifically, but shouldn't an app such as igv.js that is expected to be embedded support being inside of a shadow DOM?

If I do come up with a patch that solves the situation for both cases, I'll open a PR if that's something the team is open to.

jrobinso commented 3 months ago

@twrightsman This is the first times its been requested, and I have never heard the term "shadow DOM" until now. One possibility might be to optional pass in the node onto which the style element is attached, with the default node being document.head, so replace document.head with the supplied node. This might require some minor refactoring of the startup sequence. Would that solve your issue?

    document.head.append(style)
twrightsman commented 3 months ago

Yeah, the shadow DOM was new to me as well. I'm not much of a web developer, but I looked into the APIs for this and I think I have the beginning of something that will work on modern browsers.

The CSS attachment would need to be refactored to occur at browser creation, by appending a CSSStyleSheet to the element.getRootNode().adoptedStyleSheets, where element is the element that is passed to igv.createBrowser. A check would be needed to see if the style sheet is already present in the root, so the same style sheet doesn't keep getting added with each new browser created.

element.getRootNode() would be document in the normal case and ShadowRoot if inside a shadow DOM, so this shouldn't break anything or change any behavior, except IGV within a shadow DOM will now style itself properly.

I can try my hand at web development and make a patch for this, if you'd prefer.

jrobinso commented 3 months ago

This looks promising. I will experiment with it when I can find some time, it might not be today. Ping this issue again if too much time passes. I would like to find an alternative to injecting a