Dash checkbox in style of graph legend

Hi all,

I’m building a dashboard containing multiple plots using Dash and mainly plotly express. All of the plots in the dashboard contain data from the same categories, so the legends are the same. The colors of the different lines are also equal, since I’m using the color_discrete_map property of the plotly express plots.

I now want to hide all the legends on the plots (since they’re equivalent) and only show one checklist in the style of a legend, so that the users can select which of the categories is shown. But I can’t for the life of me figure out how to change the style of the checklist to match that of a legend or find an alternative solution. Do you have an idea how I could accomplish this?

Here’s some test code I have, to illustrate my point:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.express as px
import plotly.io as pio
import dash_bootstrap_components as dbc


app = dash.Dash(__name__, external_stylesheets=[dbc.themes.FLATLY])

fruits = {
    "Day": [1, 2, 3, 4, 5, 6, 7],
    "Visitors": [43, 34, 65, 56, 29, 76, 80],
    "Bounce_Rate": [65, 67, 78, 65, 45, 52, 10],
    "Nice_Fruits": ["apple", "apple", "grape", "apple", "grape", "grape", "apple"],
}
df_all_fruits = pd.DataFrame(fruits)

fruits = df_all_fruits["Nice_Fruits"].unique()

colors = pio.templates[pio.templates.default].layout.colorway
fruit_colors = {x: colors[i] for i, x in enumerate(fruits)}

checklist = dbc.FormGroup(
    [
        dbc.Label("Choose data to show"),
        dbc.Checklist(  # <-- I'd like to have this checkbox in the style of a legend (or have a similar component here)
            id="fruits-checklist",
            options=[{"label": i, "value": i} for i in fruits],
            value=fruits,
        ),
    ]
)

app.layout = html.Div(
    children=[
        html.H1(children="Fruit bounce rate"),
        checklist,
        html.Div(id="graphs-div"),
    ],
)


@app.callback(
    Output("graphs-div", "children"),
    [Input("fruits-checklist", "value")],
)
def update_graph(values):
    df = df_all_fruits
    df = df[df["Nice_Fruits"].isin(values)]

    return [
        dcc.Graph(figure=get_plot(df, "Visitors", "Bounce_Rate")),
        dcc.Graph(figure=get_plot(df, "Day", "Visitors")),
    ]


def get_plot(df, x_axis, y_axis):
    fig = px.scatter(
        df, x=x_axis, y=y_axis, color="Nice_Fruits", color_discrete_map=fruit_colors
    )
    fig.update_layout(transition_duration=500)
    fig.update_traces(showlegend=False)

    return fig


if __name__ == "__main__":
    app.run_server(debug=True)

I also thought about just having another plot, just not showing any data and only the legend, but couldn’t figure out how to do that either.

Do you have any ideas?