I develop and maintain ginkgobioworks/plotly-plot, a Polymer element that encapsulates plotly.js. Polymer is a web-component framework written by Google, which uses browser functionality known as the "shadow DOM" to isolate the internals of web components from the rest of the page.
Polymer 1.x has two kinds of shadow DOM implementations: native shadow DOM (v0), and a
shim called "shady DOM." Native shadow DOM is newer and yields improved
performance, but it has poor support in browsers outside of Chrome
and can cause problems with existing code. For this reason, shady DOM is
still the default implementation in Polymer 1.x.
Unfortunately, native shadow DOM is currently incompatible with plotly.js. The
icon toolbar layout code in the plotly.js library fails for all plotly plots
rendered inside a shadow DOM.
Since it's a pain to create your own elements without the tools in a code pen, the easiest example to observe is on the plotly-plot demo page.
You can render the page either with shady DOM (the default) or with shadow DOM by passing in the ?dom=shadow GET parameter, which forces Polymer to use native shadow DOM v0 in browsers that support it.
Under shady DOM (no GET parameter), the elements behave as expected. Under shadow DOM (with the GET parameter), however, the toolbars fail to render entirely.
I don't know why this is the case. It might have to do with SVG support for the buttons, or CSS effects.
The work-around on my side is that anyone who consumes my element must not turn on native shadow DOM rendering on any page that renders a plotly-plot widget. This is fine for small, simple pages, but can be a real drag when front-end performance is at stake.
I'm wondering if there might be a relatively easy fix that would prevent this from happening鈥攊f there is, it'd be nice to do it. If not, it's probably not worth doing any serious rewriting for this use case.
In any case, thought you'd be interested to know.
Thanks very much for the report. Nice work with plotly-plot !
the toolbars fail to render entirely.
Just to clarify, by _toolbars_ you're referring to the plotly modebar?
If so, I suspect a similar issue to https://github.com/plotly/plotly.js/issues/702
Closing due to lack of activity.
@etpinard whoops鈥攄idn't see your responses. Yes, I did mean the modebar, and yes, the behavior is just like #702. I'm fine with this being closed relative to that issue, if resolving #702 also fixes this bug. (Although, tbh, this particular case might be more of a Shadow DOM/Polymer issue than a plotly issue, since turning on Shadow DOM ought to have no effect.)
Also, thank you! 馃槉
Cheers!
I have the same problem with the legend.
I'm using Polymer 1.0 and Polymer 2.0. They have by default native Shadow DOM v1 turned on if the browser supports it. And the result is like this

In Polymer 1.0 you can turn off native shadow DOM and everything works fine but If you plan to use Plotly with native shadow DOM v1 toolbar and legend are not working as expected.
I think this can have a huge impact for who wants to use Plotly + web components since Shadow DOM v1 has became W3C spec.
I am also experiencing this issue - it seems like it makes it impossible to use plotly with polymer and perhaps even native webcomponents. I attempted to use the child-window branch in #702 but it did not fix the problem.
I believe the problem is in the way that plotly adds style to the document. When the plotly.js script is loaded it initializes itself by running the following function for a number of css styles:
lib.addStyleRule = function(selector, styleString) {
if(!lib.styleSheet) {
var style = document.createElement('style');
// WebKit hack :(
style.appendChild(document.createTextNode(''));
document.head.appendChild(style);
lib.styleSheet = style.sheet;
}
var styleSheet = lib.styleSheet;
if(styleSheet.insertRule) {
styleSheet.insertRule(selector + '{' + styleString + '}', 0);
}
else if(styleSheet.addRule) {
styleSheet.addRule(selector, styleString, 0);
}
else lib.warn('addStyleRule failed');
};
This appends a new style tag to the head of the document. Chrome doesn't seem to totally understand this because if you try to inspect the element it just appears empty. This is not a problem if you are not using a shadowRoot as the styles are still correctly applied. However, in a shadowRoot the style encapsulation screws things up and the styles are not found.
You can get around this by adding the required styles to your template style section. This is kind of a mess but it does work. I have created an example project that shows the initial problem and the hack working at: plotly-polymer-fix
There is a script at happybase that claims to be a cross-browser way to create css styles dynamically. I replaced the original implementation of addStyleRule with this one and it also does not work.
I've also found that the following css restores proper behavior in my polymer component:
/* plotly require those class to render correctly */
.js-plotly-plot .plotly .main-svg {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
EDIT: actually never mind, it's just slightly better, and jdfergason's styles are much more complete. However, there are still some issues with getting the position of the mouse for the zoom / hover actions.
This is because css must be defined inside the component's shadow dom.
Just generate the final css and do what you need with it:
sass .\node_modules\plotly.js\src\css\style.scss > plolty.css
Then do what you want with css, if you are using lit-element your can expose the css this way:
import { css } from 'lit-element';
const plotlyStyle = css`
.js-plotly-plot .plotly,
.js-plotly-plot .plotly div {
direction: ltr;
font-family: 'Open Sans', verdana, arial, sans-serif;
margin: 0;
padding: 0;
}
........
*** css from generated plotly.css file ***
........
.plotly-notifier .notifier-close:hover {
color: #444;
text-decoration: none;
cursor: pointer;
}
`;
export default plotlyStyle;
Then you are free to import this piece of css in your individual components.