Repository: streamlit/streamlit

Issue:
Add tooltip to st.metric(0 to provide more information on a KPI

### Problem

It would help our business users to have a bit more description available on KPIs.

### Solution

**MVP:** Could we add a tooltip to the _st.metric()_ function?   That would provide a lot of drill down flexibility, background description and the ability to use f-strings to include more detailed information




Discussion:
Hey @knorthover, thanks for bringing this up! We have this on our roadmap. Can't give you an exact timeline but I guess we'll work on this at the end of this year or beginning of next year. 
Hi, I thaught about it too! It would be nice to have at least the 'unsafe_allow_html' arg, so that we can force this function! Of course, a dedicated parameter such as 'help' would be the best ! 

I think that it could be very useful for many dashboards. 
I'd love this feature too...!
I would like to see a component that is a tooltip its self, something like `st.tooltip`. It would allow to use tooltips for markdowns, headers, metrics, tables, charts...
+1, I am constantly being asked questions about metrics and it would be great to have built-in tooltips for this. Generally, I think most elements should have the option to have a tooltip.

Resolving patch:
diff --git a/e2e/scripts/st_tooltips.py b/e2e/scripts/st_tooltips.py
--- a/e2e/scripts/st_tooltips.py
+++ b/e2e/scripts/st_tooltips.py
@@ -70,3 +70,4 @@
 st.text_area("textarea", help=leading_indent_regular_text_tooltip)
 st.select_slider("selectslider", options=["a", "b", "c"], help=indented_code_tooltip)
 st.button("some button", help=no_indent_tooltip)
+st.metric("some metric", value=500, help=no_indent_tooltip)
diff --git a/lib/streamlit/elements/metric.py b/lib/streamlit/elements/metric.py
--- a/lib/streamlit/elements/metric.py
+++ b/lib/streamlit/elements/metric.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 from textwrap import dedent
-from typing import cast, TYPE_CHECKING, Union
+from typing import cast, TYPE_CHECKING, Union, Optional
 from typing_extensions import TypeAlias, Literal
 
 import attr
@@ -46,6 +46,7 @@ def metric(
         value: Value,
         delta: Delta = None,
         delta_color: DeltaColor = "normal",
+        help: Optional[str] = None,
     ) -> "DeltaGenerator":
         """Display a metric in big bold font, with an optional indicator of how the metric changed.
 
@@ -72,6 +73,8 @@ def metric(
              negative. This is useful when a negative change is considered
              good, e.g. if cost decreased. If "off", delta is  shown in gray
              regardless of its value.
+        help : str
+            An optional tooltip that gets displayed next to the metric label.
 
         Example
         -------
@@ -109,6 +112,8 @@ def metric(
         metric_proto.body = self.parse_value(value)
         metric_proto.label = self.parse_label(label)
         metric_proto.delta = self.parse_delta(delta)
+        if help is not None:
+            metric_proto.help = dedent(help)
 
         color_and_direction = self.determine_delta_color_and_direction(
             cast(DeltaColor, clean_text(delta_color)), delta


Test patch:
diff --git a/frontend/src/components/elements/Metric/Metric.test.tsx b/frontend/src/components/elements/Metric/Metric.test.tsx
--- a/frontend/src/components/elements/Metric/Metric.test.tsx
+++ b/frontend/src/components/elements/Metric/Metric.test.tsx
@@ -90,4 +90,10 @@ describe("Metric element", () => {
       "#ff2b2b"
     )
   })
+
+  it("should render TooltipIcon if help text provided", () => {
+    const props = getProps({ help: "help text" })
+    const wrapper = mount(<Metric {...props} />)
+    expect(wrapper.find("TooltipIcon").prop("content")).toBe("help text")
+  })
 })
diff --git a/lib/tests/streamlit/metric_test.py b/lib/tests/streamlit/metric_test.py
--- a/lib/tests/streamlit/metric_test.py
+++ b/lib/tests/streamlit/metric_test.py
@@ -187,3 +187,8 @@ def test_invalid_delta_color(self):
             "'normal', 'inverse', or 'off'",
             str(exc.exception),
         )
+
+    def test_help(self):
+        st.metric("label_test", value="500", help="   help text")
+        c = self.get_delta_from_queue().new_element.metric
+        self.assertEqual(c.help, "help text")