# DataTable Tooltips

DataTable Tooltips allow you to provide additional information about table cells or headers when hovering your mouse over cells.

These properties can be used to specify `DataTable` tooltips:

- `tooltip`: Column based tooltip configuration applied to all rows
- `tooltip_conditional`: Conditional tooltips overriding `tooltip`
- `tooltip_data`: Statically defined tooltip for each row/column combination
- `tooltip_header`: Statically defined tooltip for each header column and optionally each header row
- `tooltip_delay`: Table-wide default delay before the tooltip is displayed
- `tooltip_duration`: Table-wide default duration before the tooltip disappears. Set to nothing to prevent the tooltip from disappearing.

See DataTable Reference for detailed descriptions.

## Tooltips on Individual Cells

Use tooltips on individual cells if your data is abbreviated, cut-off, or if you'd like to display more context about your data.

This example displays the same data in the cell within the header:

    using Dash
    using OrderedCollections, DataFrames

    data_election = OrderedDict(
                "Date" =>
                [
                    "July 12th, 2013 - July 25th, 2013",
                    "July 12th, 2013 - August 25th, 2013",
                    "July 12th, 2014 - August 25th, 2014",
                ],
                "Election Polling Organization" =>
                ["The New York Times", "Pew Research", "The Washington Post"],

            "Rep" => [1, -20, 3.512],
            "Dem" => [10, 20, 30],
            "Ind" => [2, 10924, 3912],

                "Region" =>
                [
                    "Northern New York State to the Southern Appalachian Mountains",
                    "Canada",
                    "Southern Vermont",
                ],

    )

    df = DataFrame(data_election)

    nme = names(df)
    app = dash()

    app.layout = dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        tooltip_data=[
            Dict(
              [n =>  Dict("value" =>  string(df[row,n]), "type" =>  "markdown")
                for n in nme]
            ) for row in 1:nrow(df)
        ],

        # Overflow into ellipsis
        style_cell=Dict(
            "overflow" =>  "hidden",
            "textOverflow" =>  "ellipsis",
            "maxWidth" =>  0,
        ),
        tooltip_delay=0,
        tooltip_duration = nothing
    )

    run_server(app, "0.0.0.0", debug=true)

Date | Election Polling Organization | Rep | Dem | Ind | Region
--- | --- | --- | --- | --- | ---
July 12th, 2013 - July 25th, 2013 | The New York Times | 1 | 10 | 2 | Northern New York State to the Southern Appalachian Mountains
July 12th, 2013 - August 25th, 2013 | Pew Research | -20 | 20 | 10924 | Canada
July 12th, 2014 - August 25th, 2014 | The Washington Post | 3.512 | 30 | 3912 | Southern Vermont

The shape of the `toolip_data` is a list of dictionaries, where each dictionary's key matches the `column.id` and each dictionary's value is a dict with `value` & `type`. Alternatively, it can be a single value and `type` will be a string instead of `markdown`.

    using Dash
    using CSV, DataFrames

    app = dash()

    app.layout = dash_datatable(
        data=[
            Dict("shop" =>  "Bakersfield", "sales" =>  4, "goal" =>  10),
            Dict("shop" =>  "Berkeley", "sales" =>  10, "goal" =>  1),
            Dict("shop" =>  "Big Bear Lake", "sales" =>  5, "goal" =>  4)
        ],
        columns=[
            Dict("id" =>  "shop", "name" =>  "Store Location"),
            Dict("id" =>  "sales", "name" =>  "Sales Revenue"),
            Dict("id" =>  "goal", "name" =>  "Revenue Goal"),
        ],
        tooltip_data=[
            Dict(
                "shop" =>  "Location at Bakersfield",
                "sales" =>  "\$4M in Revenue",
                "goal" =>  Dict("value" =>  "6M **under** Goal", "type" =>  "markdown")
            ),
            Dict(
                "shop" =>  "Location at Berkeley",
                "sales" =>  "\$10M in Revenue",
                "goal" =>  Dict("value" =>  "9M **over** Goal", "type" =>  "markdown")
            ),
            Dict(
                "shop" =>  "Location at Big Bear Lake",
                "sales" =>  "\$5M in Revenue",
                "goal" =>  Dict("value" =>  "1M **over** Goal", "type" =>  "markdown")
            ),
        ],
        tooltip_delay=0,
        tooltip_duration=nothing
    )
    run_server(app, "0.0.0.0", debug=true)

Store Location | Sales Revenue | Revenue Goal
--- | --- | ---
Bakersfield | 4 | 10
Berkeley | 10 | 1
Big Bear Lake | 5 | 4

This example displays different content in each column than what is displayed in the cell.

    using Dash
    using CSV, DataFrames

    df = DataFrame(Dict(
        "shop" =>  ["Bakersfield", "Berkely", "Big Bear Lake"],
        "sales" =>  [3, 1, 5],
        "goal" =>  [10, 1, 4],
        "address" =>  [
            "3000 Mall View Road, Suite 1107\n\nBakersfield, CA\n\n93306",
            "2130 Center Street, Suite 102\n\nBerkeley, CA\n\n94704",
            "652 Pine Knot Avenue\n\nBig Bear Lake, CA\n\n92315"
        ]
    ))

    app = dash()

    dict_data = Dict.(pairs.(eachrow(df)))

    app.layout = dash_datatable(
        data= dict_data,
        columns=[Dict("id" =>  c, "name" =>  c) for c in ["shop", "sales", "goal"]],
        tooltip_data=[Dict(
            "shop" =>  Dict("value" =>  row[:address], "type" =>  "markdown"),
            "sales" =>  Dict(
                "value" =>  "Sales were $(string(abs(row[:goal] - row[:sales]))) $((row[:goal] > row[:sales]) ? "less" : "more") than the goal",
                "type" =>  "markdown"
            ),
            "goal" =>  "Goal was $((row[:goal] > row[:sales]) ? "not achieved" : "achieved")"
        ) for row in dict_data],
        tooltip_delay=0,
        tooltip_duration=nothing
    )
    run_server(app, "0.0.0.0", debug=true)

shop | sales | goal
--- | --- | ---
Bakersfield | 3 | 10
Berkely | 1 | 1
Big Bear Lake | 5 | 4

## Tooltips in Column Headers

If your column headers are abbreviated or cut-off (See DataTable Width), then place a tooltip in the header with `tooltip_header`.

We recommend providing some light styling to the header to indicate that it is "hoverable". We use the dotted underline with `text-decoration`. This isn't supported in IE11.

In this example, the headers are cut-off because they are too long. Our tooltip is the original name of the column.

    using Dash
    using OrderedCollections, DataFrames

    data_election = OrderedDict(
                "Date" =>
                [
                    "July 12th, 2013 - July 25th, 2013",
                    "July 12th, 2013 - August 25th, 2013",
                    "July 12th, 2014 - August 25th, 2014",
                ],
                "Election Polling Organization" =>
                ["The New York Times", "Pew Research", "The Washington Post"],

            "Rep" => [1, -20, 3.512],
            "Dem" => [10, 20, 30],
            "Ind" => [2, 10924, 3912],

                "Region" =>
                [
                    "Northern New York State to the Southern Appalachian Mountains",
                    "Canada",
                    "Southern Vermont",
                ],

    )

    df = DataFrame(data_election)

    app = dash()

    dict_data = Dict.(pairs.(eachrow(df)))

    app.layout = dash_datatable(
        data= dict_data,
        columns=[Dict("id" =>  c, "name" =>  c) for c in ["shop", "sales", "goal"]],
        tooltip_header=Dict(i =>  i for i in names(df)),

        # Style headers with a dotted underline to indicate a tooltip
        style_header=Dict(
            "textDecoration" =>  "underline",
            "textDecorationStyle" =>  "dotted",
        ),

        # Overflow into ellipsis
        style_cell=Dict(
            "overflow" =>  "hidden",
            "textOverflow" =>  "ellipsis",
            "maxWidth" =>  0,
        ),
        tooltip_delay=0,
        tooltip_duration=nothing
    )
    run_server(app, "0.0.0.0", debug=true)

Date | Election Polling Organization | Rep | Dem | Ind | Region
--- | --- | --- | --- | --- | ---
July 12th, 2013 - July 25th, 2013 | The New York Times | 1 | 10 | 2 | Northern New York State to the Southern Appalachian Mountains
July 12th, 2013 - August 25th, 2013 | Pew Research | -20 | 20 | 10924 | Canada
July 12th, 2014 - August 25th, 2014 | The Washington Post | 3.512 | 30 | 3912 | Southern Vermont

Alternatively, you can specify a different name within `tooltip_header` or specify a subset of columns:

    using Dash
    using OrderedCollections, DataFrames

    data_election = OrderedDict(
                "Date" =>
                [
                    "July 12th, 2013 - July 25th, 2013",
                    "July 12th, 2013 - August 25th, 2013",
                    "July 12th, 2014 - August 25th, 2014",
                ],
                "Election Polling Organization" =>
                ["The New York Times", "Pew Research", "The Washington Post"],

            "Rep" => [1, -20, 3.512],
            "Dem" => [10, 20, 30],
            "Ind" => [2, 10924, 3912],

                "Region" =>
                [
                    "Northern New York State to the Southern Appalachian Mountains",
                    "Canada",
                    "Southern Vermont",
                ],

    )

    df = DataFrame(data_election)

    app = dash()

    app.layout =  dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        tooltip_header=Dict(
            "Region" =>  "Reg",
            "Temperature" =>  "Temp",
            "Pressure" =>  "Pre",
        ),

        # Style headers with a dotted underline to indicate a tooltip
        style_header_conditional=[Dict(
            "if" =>  Dict("column_id" =>  col),
            "textDecoration" =>  "underline",
            "textDecorationStyle" =>  "dotted",
        ) for col in ["Region", "Temperature", "Pressure"]],

        # Overflow into ellipsis
        style_cell=Dict(
            "overflow" =>  "hidden",
            "textOverflow" =>  "ellipsis",
            "maxWidth" =>  0,
        ),
        tooltip_delay=0,
        tooltip_duration=nothing
    )

    run_server(app, "0.0.0.0", debug=true)

Date | Election Polling Organization | Rep | Dem | Ind | Region
--- | --- | --- | --- | --- | ---
July 12th, 2013 - July 25th, 2013 | The New York Times | 1 | 10 | 2 | Northern New York State to the Southern Appalachian Mountains
July 12th, 2013 - August 25th, 2013 | Pew Research | -20 | 20 | 10924 | Canada
July 12th, 2014 - August 25th, 2014 | The Washington Post | 3.512 | 30 | 3912 | Southern Vermont

Note that ellipses aren't displayed in headers. This is a bug, subscribe to plotly/dash-table#735 for details.

If your `DataTable` has multiple rows of headers, then use a list as the value of the `tooltip_header` items.

For merged cells, the values must repeat in each cell.

    using Dash
    using CSV, DataFrames

    df = DataFrame(Dict(
        "shop" =>  ["Bakersfield", "Berkely", "Big Bear Lake"],
        "sales" =>  [3, 1, 5],
        "goal" =>  [10, 1, 4],
        "address" =>  [
            "3000 Mall View Road, Suite 1107\n\nBakersfield, CA\n\n93306",
            "2130 Center Street, Suite 102\n\nBerkeley, CA\n\n94704",
            "652 Pine Knot Avenue\n\nBig Bear Lake, CA\n\n92315"
        ]
    ))

    app = dash()

    dict_data = Dict.(pairs.(eachrow(df)))

    app.layout = dash_datatable(
      columns=[
        Dict("name" =>  ["", "Year"], "id" =>  "year"),
        Dict("name" =>  ["City", "Montreal"], "id" =>  "montreal"),
        Dict("name" =>  ["City", "Toronto"], "id" =>  "toronto"),
        Dict("name" =>  ["City", "Ottawa"], "id" =>  "ottawa"),
        Dict("name" =>  ["City", "Vancouver"], "id" =>  "vancouver"),
        Dict("name" =>  ["Climate", "Temperature"], "id" =>  "temp"),
        Dict("name" =>  ["Climate", "Humidity"], "id" =>  "humidity"),
    ],
    data=[Dict(
        "year" =>  i, "montreal" =>  i * 10, "toronto" =>  i * 100,
        "ottawa" =>  i * -1, "vancouver" =>  i * -10, "temp" =>  i * -100,
        "humidity" =>  i * 5,
    ) for i in 1:10],
    merge_duplicate_headers=true,

    tooltip_header=Dict(
        "year" =>  ["", "Year the measurement was taken"],
        "montreal" =>  ["Average Measurements Across City", "Montreal, QC, Canada"],
        "toronto" =>  ["Average Measurements Across City", "Toronto, ON, Canada"],
        "ottawa" =>  ["Average Measurements Across City", "Ottawa, ON, Canada"],
        "vancouver" =>  ["Average Measurements Across City", "Vancouver, BC, Canada"],
        "temp" =>  ["Average for a Year", "Celcius"],
        "humidity" =>  ["Average for a Year", "Percentage"],
    ),

    style_header=Dict(
        "textDecoration" =>  "underline",
        "textDecorationStyle" =>  "dotted",
    ),
    )
    run_server(app, "0.0.0.0", debug=true)

| City | Climate
--- | --- | ---
Year | Montreal | Toronto | Ottawa | Vancouver | Temperature | Humidity
0 | 0 | 0 | 0 | 0 | 0 | 0
1 | 10 | 100 | -1 | -10 | -100 | 5
2 | 20 | 200 | -2 | -20 | -200 | 10
3 | 30 | 300 | -3 | -30 | -300 | 15
4 | 40 | 400 | -4 | -40 | -400 | 20
5 | 50 | 500 | -5 | -50 | -500 | 25
6 | 60 | 600 | -6 | -60 | -600 | 30
7 | 70 | 700 | -7 | -70 | -700 | 35
8 | 80 | 800 | -8 | -80 | -800 | 40
9 | 90 | 900 | -9 | -90 | -900 | 45

## A Single Tooltip in the Column

As an alternative or in addition to column header tooltips, place a tooltip to appear on the entire column with the `tooltip` property.

This can also be helpful with large tables where the user may lose track of the column headers.

If the tooltip is specified for both headers and cells, you can use the `use_with` property instead of specifying a separate `tooltip_header` and `tooltip`.

    using Dash
    using OrderedCollections, DataFrames

    data_election = OrderedDict(
                "Date" =>
                [
                    "July 12th, 2013 - July 25th, 2013",
                    "July 12th, 2013 - August 25th, 2013",
                    "July 12th, 2014 - August 25th, 2014",
                ],
                "Election Polling Organization" =>
                ["The New York Times", "Pew Research", "The Washington Post"],

            "Rep" => [1, -20, 3.512],
            "Dem" => [10, 20, 30],
            "Ind" => [2, 10924, 3912],

                "Region" =>
                [
                    "Northern New York State to the Southern Appalachian Mountains",
                    "Canada",
                    "Southern Vermont",
                ],

    )

    df = DataFrame(data_election)

    app = dash()

    dict_data = Dict.(pairs.(eachrow(df)))

    app.layout = dash_datatable(
        data= dict_data,
        columns=[Dict("id" =>  c, "name" =>  c) for c in ["shop", "sales", "goal"]],
        tooltip =Dict(i =>  Dict(
            "value" =>  i,
            "use_with" =>  "both"  # both refers to header & data cell
        ) for i in names(df)),

        # Style headers with a dotted underline to indicate a tooltip
        style_header=Dict(
            "textDecoration" =>  "underline",
            "textDecorationStyle" =>  "dotted",
        ),

        # Overflow into ellipsis
        style_cell=Dict(
            "overflow" =>  "hidden",
            "textOverflow" =>  "ellipsis",
            "maxWidth" =>  0,
        ),
        tooltip_delay=0,
        tooltip_duration=nothing
    )
    run_server(app, "0.0.0.0", debug=true)

Date | Election Polling Organization | Rep | Dem | Ind | Region
--- | --- | --- | --- | --- | ---
July 12th, 2013 - July 25th, 2013 | The New York Times | 1 | 10 | 2 | Northern New York State to the Southern Appalachian Mountains
July 12th, 2013 - August 25th, 2013 | Pew Research | -20 | 20 | 10924 | Canada
July 12th, 2014 - August 25th, 2014 | The Washington Post | 3.512 | 30 | 3912 | Southern Vermont

## Conditional Tooltips

Tooltips can also be customized based on conditions. The `tooltip_conditional` has the same syntax as the `style_data_conditional` property, see the conditional formatting chapter for many examples.

If both `tooltip_conditional` and `tooltip` would display a tooltip for a cell, the conditional tooltip takes priority. If multiple conditions match the data row, the last match has priority.

    using Dash
    using OrderedCollections, DataFrames

    data = OrderedDict(
          "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
          "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
          "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
          "Humidity" => [10, 20, 30, 40, 50, 60],
          "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
    )

    df = DataFrame(data)

    app = dash()

    app.layout =  dash_datatable(
            data=Dict.(pairs.(eachrow(df))),
            columns=[Dict("name" =>c, "id" => c) for c in names(df)],
            tooltip_conditional=[
              Dict(
                  "if" =>  Dict(
                      "filter_query" =>  "{Region} contains $(string("New"))"
                  ),
                  "type" =>  "markdown",
                  "value" =>  "This row is significant."
              )
          ],

          style_data_conditional=[
              Dict(
                  "if" =>  Dict(
                      "filter_query" =>  "{Region} contains $(string("New"))"
                  ),
                  "backgroundColor" =>  "#0074D9",
                  "color" =>  "white",
                  "textDecoration" =>  "underline",
                  "textDecorationStyle" =>  "dotted",
              )
          ],
          tooltip_delay=0,
          tooltip_duration=nothing
        )

    run_server(app, "0.0.0.0", debug=true)

Date | Region | Temperature | Humidity | Pressure
--- | --- | --- | --- | ---
2015-01-01 | Montreal | 1 | 10 | 2
2015-10-24 | Toronto | -20 | 20 | 10924
2016-05-10 | New York City | 3.512 | 30 | 3912
2017-01-10 | Miami | 4 | 40 | -10
2018-05-10 | San Francisco | 10423 | 50 | 3591.2
2018-08-15 | London | -441.2 | 60 | 15

## Images in Tooltips

Markdown supports images with this syntax: `![alt](src)` where `alt` refers to the image's alt text and `src` is the path to the image (the `src` property).

The `src` can refer to images within your project's "assets" folder or absolute URLs. If referring to an image in the `assets` folder, we recommend using `dash.get_relative_path` so that the image URL is correct when working locally and when deploying to Dash Enterprise.

    using Dash
    using CSV, DataFrames

    app = dash()

    app.layout =  dash_datatable(
      data=[
          Dict("shop" =>  "Bakersfield", "sales" =>  4, "goal" =>  10),
          Dict("shop" =>  "Berkeley", "sales" =>  10, "goal" =>  1),
          Dict("shop" =>  "Big Bear Lake", "sales" =>  5, "goal" =>  4)
      ],
      columns=[
          Dict("id" =>  "shop", "name" =>  "Store Location"),
          Dict("id" =>  "sales", "name" =>  "Sales Revenue"),
          Dict("id" =>  "goal", "name" =>  "Revenue Goal"),
      ],
      tooltip_data=[
          Dict(
              "shop" =>  Dict(
                  "value" =>  "Location at Bakersfield\n\n![Bakersfield]($(string("/assets/images/table/bakers.jpg")))",
                  "type" =>  "markdown"
              )
          ),
          Dict(
              "shop" =>  Dict(
                  "value" =>  "Location at Berkeley\n\n![Berkeley]($(string("/assets/images/table/berkley.jpg")))",
                  "type" =>  "markdown"
              )
          ),
          Dict(
              "shop" =>  Dict(
                  "value" =>  "Location at Big Bear Lake\n\n![Big Bear Lake](https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Big_Bear_Valley%2C_California.jpg/1200px-Big_Bear_Valley%2C_California.jpg)",
                  "type" =>  "markdown"
              )
          ),
      ],

      # Style headers with a dotted underline to indicate a tooltip
      style_data_conditional=[Dict(
          "if" =>  Dict("column_id" =>  "shop"),
          "textDecoration" =>  "underline",
          "textDecorationStyle" =>  "dotted",
      )],

      tooltip_delay=0,
      tooltip_duration=nothing
    )

    run_server(app, "0.0.0.0", debug=true)

Store Location | Sales Revenue | Revenue Goal
--- | --- | ---
Bakersfield | 4 | 10
Berkeley | 10 | 1
Big Bear Lake | 5 | 4

## Tables in Tooltips

Markdown supports tables with a syntax that looks like this:

    | City       | Value     | Return     |
    | :------------- | :----------: | -----------: |
    |  Montreal   | 41,531    | 431.245 |
    | Seattle   | 53,153 | 12.431 |

City | Value | Return
--- | --- | ---
Montreal | 41,531 | 431.245
Seattle | 53,153 | 12.431

This can be specified within a table's value:

    using Dash

    app = dash()

    markdown_table = """
    | City      | Value     | Return     |
    |-----------|-----------|------------|
    |  Montreal | 41,531    | 431.245    |
    | Seattle   | 53,153    | 12.431     |
    """

    app.layout =  dash_datatable(
      data=[
            Dict("shop" =>  "Bakersfield", "sales" =>  4, "goal" =>  10),
            Dict("shop" =>  "Berkeley", "sales" =>  10, "goal" =>  1),
            Dict("shop" =>  "Big Bear Lake", "sales" =>  5, "goal" =>  4)
        ],
        columns=[
            Dict("id" =>  "shop", "name" =>  "Store Location"),
            Dict("id" =>  "sales", "name" =>  "Sales Revenue"),
            Dict("id" =>  "goal", "name" =>  "Revenue Goal"),
        ],
        tooltip=Dict(
            c =>  Dict("value" =>  markdown_table, "type" =>  "markdown")
            for c in ["shop", "sales", "goal"]
        ),
        tooltip_delay=0,
        tooltip_duration=nothing
    )

    run_server(app, "0.0.0.0", debug=true)

Store Location | Sales Revenue | Revenue Goal
--- | --- | ---
Bakersfield | 4 | 10
Berkeley | 10 | 1
Big Bear Lake | 5 | 4

## Styling Tooltips

Tooltips can be styled with the `dash-tooltip` (container) and `dash-table-tooltip` (content) CSS classes. This can be specified within a CSS file inside your `assets/` folder or within the table itself with the `css` property.

    using Dash
    using OrderedCollections, DataFrames

    data = OrderedDict(
          "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
          "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
          "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
          "Humidity" => [10, 20, 30, 40, 50, 60],
          "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
    )

    df = DataFrame(data)

    app = dash()

    app.layout =  dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        tooltip_data=[
          Dict(
              column =>  Dict("value" =>  string(value), "type" =>  "markdown")
              for (column, value) in row
          ) for row in Dict.(pairs.(eachrow(df)))
      ],
      css=[Dict(
          "selector" =>  ".dash-table-tooltip",
          "rule" =>  "background-color =>  white; font-family =>  monospace;"
      )],

      tooltip_delay=0,
      tooltip_duration=nothing
    )

    run_server(app, "0.0.0.0", debug=true)

Date | Region | Temperature | Humidity | Pressure
--- | --- | --- | --- | ---
2015-01-01 | Montreal | 1 | 10 | 2
2015-10-24 | Toronto | -20 | 20 | 10924
2016-05-10 | New York City | 3.512 | 30 | 3912
2017-01-10 | Miami | 4 | 40 | -10
2018-05-10 | San Francisco | 10423 | 50 | 3591.2
2018-08-15 | London | -441.2 | 60 | 15

## Customizing Delay & Duration

Set `tooltip_delay` to `0` for the tooltips to appear immediately.

Set `tooltip_duration` to nothing in order for the tooltips to remain visible while you are hovering over them. Otherwise, they will disappear after `tooltip_duration` milliseconds.