Tooltip bbox position is incorrect when inside a dcc.Loading component
Nobody has claimed this yet.
- 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
Dash 2.17.1
Dash 2.18.1
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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