plotly / plotly/dash

Tooltip bbox position is incorrect when inside a dcc.Loading component

Open
#3,015 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug P3
Dominant language
Python
Stars
24.4k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
13

Description

First of all, I want to express my appreciation for this excellent product.

Context

I have a graph that takes a long time to render, and I want to display a loading indicator before it renders.

dash                      2.18.1
dash-bootstrap-components 1.6.0
dash-core-components      2.0.0
dash-html-components      2.0.0
dash-table                5.0.0
  • OS: Windows 11 Pro 23H2
  • Browser: Chrome
  • Version: 128.0.6613.139

Bug

When the graph is nested inside a dcc.Loading component, the tooltip's bbox position is misaligned with the plot when displayed.
From my investigation, in Dash 2.17.0, the tooltip's bbox position is correct regardless of whether it's nested inside a loading component.
However, starting from Dash 2.17.1, the tooltip's bbox position becomes incorrect when nested.

Expected behavior

The tooltip's bbox position should be correct regardless of whether the graph is nested inside a dcc.Loading component.

Screenshots

Here I show the tooltip's bbox position problem using my minimal reproduction example.

Dash 2.17.0

スクリーンショット 2024-09-24 105542

Dash 2.17.1

スクリーンショット 2024-09-24 105634

Dash 2.18.1

スクリーンショット 2024-09-24 105734

Minimal Reproduction Example

poetry install
poetry run python main.py
poetry.lock
[tool.poetry]
name = "dash-tooltip-test"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.12"
dash = "=2.18.1"
plotly = "^5.24.1"
pandas = "^2.2.3"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
main.py
from typing import Optional

import plotly.express as px
from dash import Dash, Input, Output, dcc, html, no_update

APP = Dash()
APP.title = "Tooltip Test"
APP.layout = html.Div(
    [
        html.H1("Tooltip Test (Dash 2.18.1)"),
        html.H2("With Loading"),
        dcc.Loading(
            id="loading",
            type="default",
            children=[
                dcc.Graph(
                    id="graph-with-loading",
                    figure=px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16]),
                ),
            ],
        ),
        dcc.Tooltip(id="tooltip-with-loading"),
        html.H2("Without Loading"),
        dcc.Graph(
            id="graph-without-loading",
            figure=px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16]),
        ),
        dcc.Tooltip(id="tooltip-without-loading"),
    ]
)


@APP.callback(
    Output("tooltip-with-loading", "show"),
    Output("tooltip-with-loading", "bbox"),
    Output("tooltip-with-loading", "children"),
    Input("graph-with-loading", "hoverData"),
)
def display_tooltip_with_loading(hoverData: Optional[dict]) -> tuple[bool, dict, str]:
    if hoverData is None:
        return False, no_update, no_update

    bbox = hoverData["points"][0]["bbox"]
    return (
        True,
        bbox,
        f"x: {hoverData['points'][0]['x']}, y: {hoverData['points'][0]['y']}",
    )


@APP.callback(
    Output("tooltip-without-loading", "show"),
    Output("tooltip-without-loading", "bbox"),
    Output("tooltip-without-loading", "children"),
    Input("graph-without-loading", "hoverData"),
)
def display_tooltip_without_loading(
    hoverData: Optional[dict],
) -> tuple[bool, dict, str]:
    if hoverData is None:
        return False, no_update, no_update

    bbox = hoverData["points"][0]["bbox"]
    return (
        True,
        bbox,
        f"x: {hoverData['points'][0]['x']}, y: {hoverData['points'][0]['y']}",
    )


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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the minimal reproduction in main.py with the listed Dash versions, then compare hoverData['points'][0]['bbox'] for the graphs inside and outside dcc.Loading. Trace the dcc.Graph tooltip and dcc.Loading interaction; done means the nested graph's tooltip bbox aligns with the plot without changing the non-loading case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-visualization, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.