facultyai / dash-bootstrap-components

Bootstrap components for Plotly Dash
https://dash-bootstrap-components.opensource.faculty.ai/
Apache License 2.0
1.12k stars 220 forks source link

Support tooltips without IDs #1003

Closed multimeric closed 6 months ago

multimeric commented 8 months ago

Bootstrap supports a much simpler tooltip mechanism by adding the data-bs-toggle="tooltip" attribute to an element, which means you don't have to generate a unique tooltip element and a unique ID for each element that has a tooltip. I assume that the initialisation JS is already being run in order to support the Tooltip component, so we could easily support this other mechanism either by just passing through all data-* elements in the element constructors:

import dash_bootstrap_components as dbc

dbc.Button(**{
    "title": "Tooltip text",
    "data-bs-toggle": "tooltip",
    "data-bs-placement": "right"
})

Alternatively we could have a high-level argument like "tooltip" that takes a dictionary of options:

import dash_bootstrap_components as dbc

dbc.Button(tooltip={
    "text": "Tooltip text",
    "placement": "right" 
})
tcbegley commented 8 months ago

Hi @multimeric,

Thanks for raising this. The data attribute you're referring to is indeed how Bootstrap JS works. However because Plotly Dash and all component libraries are built on React, the underlying implementation is quite different. In particular, this library is built on top of React-Bootstrap. You can see how Tooltips work here, and you'll notice it's quite different.

The ID / target pattern was arrived taking into account various constraints including limitations of Dash itself (some of which have been addressed since the first version of this library came out), and the way things are implemented in Reactstrap (a different React library with Bootstrap components that was originally the basis for dbc).

I'm open to alternative patterns that make things easier, as long as changes are backwards compatible.

Regarding your two suggestions, they both suffer from a major problem which is that I don't see how we could implement either option in a way that doesn't only work for components in this library. E.g. suppose I wanted to add a tooltip to a html.Div. We can target a particular id, but we don't have the ability to add a custom prop, nor do I see atm how we could search the whole tree of components for those data attributes.

multimeric commented 7 months ago

Okay, I see your point. From looking at the React Bootstrap docs, I wonder if adapting the following would be okay:

  const Link = ({ id, children, title }) => (
    <OverlayTrigger overlay={<Tooltip id={id}>{title}</Tooltip>}>
      <a href="#">{children}</a>
    </OverlayTrigger>

It's true that they use id here, but I don't think it's mandatory. We could call the Link element something more appropriate.

tcbegley commented 6 months ago

Hi again, I experimented with some options in #1007 but I don't think it really adds much, and I'm inclined to instead only support a single way of doing things, both to keep things simple for users and for maintainers.