Legend Tooltips

I have a use-case where I would like to offer extended information on a legend item on hover - the legend labels are fairly simple, but warrant an extended explanation that does not format nicely.

Is it possible to add tooltips to legend entries?

Thanks.

1 Like

Here’s one possible solution: http://codepen.io/etpinard/pen/zKBoVj

2 Likes

Thank you, etienne, this is very helpful.

Thanks! In my case, I used the event to manually render the legend svg last because I wanted it to display above annotations.

1 Like

That’s pretty great. Could anyone help me modify the script to add an ‘x’ button to delete each trace on click?

Hi Etienne,

I know that this issue is pretty old but if I want to have legends tooltip on two different graphs on the same page, how does that work

because in my case It doesn’t work, mouseover doesn’t get triggered by other graph’s legends

please advice

Sample using your hack: https://codepen.io/anon/pen/MOqmpE

Regards
Akash

HI Etinenne,
I am wokring on angular 5 . As per the example give in you link.

How can bind Plotly.plot(gd, data).then(attach);
gd.on(‘plotly_afterplot’, attach);

Is there any an example in angular 5
I am doing this way:
Plotly.newPlot(this.el.nativeElement, this.graphData, layout, { displayModeBar: false });

I have all the data getting from back end in this.graphData,layout.
But not sure where to add Plotly.plot(gd, data).then(attach);
gd.on(‘plotly_afterplot’, attach);

Please advise.

Thank you
Venkat

Hi Etienne,
I am using the code you have suggest. Its working fine when there is one graph in the page.
But I have 2 graphs and both of them different attach property.
Its not working as I am using
var legendLayer = d3.select(‘g.legend’);
var items = legendLayer.selectAll(‘g.traces’);

how can i get the legend ad traces of each graph. Please advise.
div id=“graph” div

Thank you
Aditya

if you have two graphs, then you probably two legends (right?), so something like

var legendLayer = d3.selectAll(‘g.legend’);
var items = legendLayer.selectAll(‘g.traces’);

should do it.

Hi Etienne,
its not working . if I add var legendLayer = d3.select(‘g.legend’);
Here is the code pen https://codepen.io/anon/pen/MOqmpE
can you please look in to it.

I think few other developers are also looking a solution for this.

Thank you for the help.

Here’s a working version: https://codepen.io/etpinard/pen/qJgXgd

Its working but if we mouse over on the bottom graph the top one is also showing the tool tip.
Can we get it independently. Like if we mouse over on the bottom graph only its tool tip needs to be shown.
Can You please advise.
Here is the screen shot of the example.

It took me a while but I worked out how to do this. Codepen herehttps://codepen.io/anon/pen/JeWPjE

super its working .
Thank you dallimor.

Is it possible to do this in Plotly Dash applications, where you cannot inject arbitrary JavaScript?

The Information you shared above is great. I have been reading all you shared here. In this you explained everything very well. If i want any further guideline we will contact you here https://community.plotly.com/t/legend-tooltips/2124/14-results/

from dash import Dash, html, dcc, clientside_callback, ClientsideFunction
from dash.dependencies import Input, Output
import plotly.express as px


df = px.data.iris()

app = Dash(__name__)

app.layout = html.Div([
    html.Div(id='dummy', style={'display': 'none'}),
    dcc.Graph(id='graph',
              style={'width': '100vw', 'height': '80vh'},
              figure=px.scatter(df,
                                x='sepal_width', y='sepal_length', color='species')),
])

clientside_callback(
    ClientsideFunction(
        namespace='clientside',
        function_name='add_legend_hover'
    ),
    Output('dummy', 'children'),
    Input('graph', 'figure'),
)

if __name__ == '__main__':
    app.run_server(debug=True, port=8000)

window.dash_clientside = Object.assign({}, window.dash_clientside, {
    clientside: {
        add_legend_hover: function(figure) {
            setTimeout(function() {
                var d3 = Plotly.d3;
                var legendLayer = d3.selectAll('.legend');
                var items = legendLayer.selectAll('.traces');
                var tooltip;

                items.on('mouseover', (d) => {
                    tooltip = legendLayer.append('text')
                        .classed('class', true)
                        .text(d[0].trace.name)
                });

                items.on('mouseout', () => {
                    if(tooltip) tooltip.remove();
                });
            }, 500); // Wait for the plot to be fully rendered
        }
    }
});