Add delta_description to st.metric#13848
Conversation
Implement support for configuring descriptive text next to delta values in metrics (e.g., "month over month", "vs. last quarter"). The description is displayed in a muted gray font with ellipsis overflow handling. Includes accessibility improvements with ARIA labels and native browser tooltips.
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
✅ PR preview is ready!
|
There was a problem hiding this comment.
Pull request overview
Adds a new delta_description parameter to st.metric() so apps can show supplementary context (e.g., “month over month”) alongside the delta, with corresponding backend/proto plumbing, frontend rendering/styling, and automated test coverage.
Changes:
- Extend the
Metricprotobuf with adelta_descriptionfield and plumb it through the Pythonst.metric()API. - Update the frontend
Metriccomponent to render the description next to the delta with truncation/tooltip behavior. - Add/extend Python unit tests, frontend unit tests (incl. a11y assertions), and Playwright E2E tests for the new behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| proto/streamlit/proto/Metric.proto | Adds delta_description field to the Metric proto message. |
| lib/streamlit/elements/metric.py | Adds delta_description parameter and sets the proto field when provided; refactors delta-arrow mapping. |
| lib/tests/streamlit/elements/metric_test.py | Adds unit tests validating default and explicit delta_description proto behavior. |
| frontend/lib/src/components/elements/Metric/styled-components.ts | Adds layout/styling for delta+description row and muted description text. |
| frontend/lib/src/components/elements/Metric/Metric.tsx | Renders deltaDescription next to delta and adds ARIA/title attributes. |
| frontend/lib/src/components/elements/Metric/Metric.test.tsx | Adds rendering/styling/a11y unit tests for delta description. |
| e2e_playwright/st_metric.py | Adds app scenarios for delta description (incl. long text truncation). |
| e2e_playwright/st_metric_test.py | Adds E2E checks + snapshot coverage for delta description rendering and tooltip/title. |
delta_description to st.metric
delta_description to st.metric delta_description to st.metric
Add flexShrink and minWidth to StyledMetricDeltaText to ensure proper truncation behavior when used alongside StyledDeltaDescription in the flex container.
Instead of dedicated tests, add delta_description to existing metrics that already have screenshot tests. This includes a material icon case.
Enables material icons, rainbow colors, and other markdown features in delta_description text.
- Long ellipsized description on "Apples I've eaten" (with chart) - Description without border on "Test 9"
Changed flexShrink from 1 to 0 on StyledMetricDeltaText so the delta badge doesn't shrink. Only the description should truncate.
Updated screenshots now include delta_description in various metrics.
The switch from inline-flex to flex layout removed implicit line-height spacing. Add paddingBottom to match the previous visual appearance.
98e1dd8 to
22daf90
Compare
d54d9d1 to
c4d7041
Compare
SummaryThis PR adds a new
Also includes a minor refactor of the Code QualityPython backend (
Frontend (
Styled components (
Minor observations:
Test CoveragePython unit tests (
Frontend unit tests (
E2E tests (
Coverage gap (minor): No typing test file exists for Backwards Compatibility
Security & Risk
Accessibility
RecommendationsNo blocking issues found. The following are minor, non-blocking suggestions:
VerdictAPPROVED: Well-implemented feature with thorough test coverage, good accessibility support, and full backwards compatibility. The code follows existing patterns and conventions throughout the stack. This is an automated AI review using |
Empty string "" is now treated the same as None, avoiding setting an unnecessary proto field. Added test to verify the behavior.
4d94966 to
9b15ee4
Compare
Consolidate Python tests into a single parameterized test and combine redundant TypeScript tests for cleaner, more maintainable test code while preserving the same coverage.
|
@cursor review |
Replace hacky nested CSS selectors with a dedicated truncate prop on StreamlitMarkdown. This encapsulates truncation logic in one place, removes the need for consumers to know the internal DOM structure, and improves code maintainability. - Add truncate prop to StreamlitMarkdown component - Add truncation styles to StyledStreamlitMarkdown - Remove StyledTruncateText wrapper from Metric component - Clean up nested CSS selectors in StyledDeltaDescription - Add unit tests for truncate functionality
Visual snapshots updated after adding truncate prop to StreamlitMarkdown. The changes are minor visual adjustments from the new truncation styling.
Add lineHeight: "normal" to truncate styles to reset inherited line heights. The old StyledTruncateText wrapper had this style, but it was missing from the new truncate prop implementation. Without this, when inheritFont is true and the parent has a large line-height (like metric values), the markdown container would inherit it, adding ~10px extra height.
Snapshots reflect correct metric heights now that lineHeight: normal is applied in the truncate styles.
Consolidated Code Review:
|
| Reviewer | Verdict |
|---|---|
gpt-5.3-codex-high |
APPROVED |
opus-4.6-thinking |
APPROVED |
Consolidated review by opus-4.6-thinking.
📋 Review by `gpt-5.3-codex-high`
Summary
This PR adds delta_description support to st.metric end-to-end: protobuf schema, Python API marshalling, frontend rendering/styling, and expanded unit/e2e coverage. It also introduces a reusable truncate prop in StreamlitMarkdown to handle single-line ellipsis reliably for metric label/value/delta content.
Code Quality
The implementation is clean and consistent with existing Streamlit patterns:
- Backend changes in
lib/streamlit/elements/metric.pyare focused and preserve existing metric parsing/validation flow. - Frontend changes in
frontend/lib/src/components/elements/Metric/Metric.tsxandfrontend/lib/src/components/elements/Metric/styled-components.tskeep concerns well-separated (rendering vs. styling). - Reuse of
StreamlitMarkdowntruncation infrontend/lib/src/components/shared/StreamlitMarkdown/StreamlitMarkdown.tsxandfrontend/lib/src/components/shared/StreamlitMarkdown/styled-components.tsimproves maintainability versus ad-hoc truncation wrappers. - No blocking code-quality defects were identified.
Test Coverage
Coverage is strong and proportionate to the feature:
- Python unit tests added in
lib/tests/streamlit/elements/metric_test.pyverify proto assignment behavior forNone, empty, and populateddelta_description. - Frontend unit tests in
frontend/lib/src/components/elements/Metric/Metric.test.tsxcover render/no-render states, styling/title behavior, and accessibility wiring. StreamlitMarkdowntests infrontend/lib/src/components/shared/StreamlitMarkdown/StreamlitMarkdown.test.tsxvalidate the newtruncatestyle behavior.- E2E updates in
e2e_playwright/st_metric.pyande2e_playwright/st_metric_test.pyvalidate runtime rendering and snapshot results.
Overall, the changed behavior appears adequately tested.
Backwards Compatibility
No breaking change detected:
delta_descriptionis an additive, optional keyword-only parameter onst.metric.- Protobuf adds a new field number (
delta_description = 12) without altering existing field semantics. - Existing
st.metriccalls without the new parameter continue to behave as before.
Security & Risk
No security concerns identified:
- Rendering continues to use
StreamlitMarkdownwithallowHTML={false}for metric text paths. - The change is primarily presentation/data-plumbing, with low regression risk beyond expected visual deltas already covered by updated snapshots.
Accessibility
Accessibility handling is improved:
- Delta text is associated with description via
aria-describedbyinfrontend/lib/src/components/elements/Metric/Metric.tsx. - Native tooltip support for truncated description text is provided via
title. - Frontend tests include accessibility-related assertions for these attributes.
Recommendations
- Consider adding a follow-up typing-focused test for the new
st.metric(..., delta_description=...)public API parameter when/if metric typing coverage is expanded. - If desired, note in PR discussion that the broad snapshot churn is expected from truncation/line-height adjustments to ease reviewer verification.
Verdict
APPROVED: The feature is implemented coherently across backend/frontend/proto with solid test coverage and no blocking regressions identified.
This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.
📋 Review by `opus-4.6-thinking`
Summary
This PR adds a new delta_description parameter to st.metric() that displays descriptive text next to the delta value (e.g., "month over month", "vs. last quarter"). The implementation spans all layers:
- Protobuf: New
delta_descriptionfield (field number 12) added toMetric.proto. - Python backend: New
delta_descriptionparameter with docstring, validation (truthy check), and proto serialization. Also refactorsdelta_arrowmapping to use a dictionary lookup (_DELTA_ARROW_TO_PROTO). - Frontend: New
StyledDeltaContainerandStyledDeltaDescriptionstyled components. The description renders next to the delta badge with ellipsis overflow,titleattribute for hover, and ARIAaria-describedbylinking. - Refactoring: Moves text truncation from a
StyledTruncateTextwrapper component into a newtruncateprop onStreamlitMarkdown, simplifying the Metric component's JSX and making truncation reusable.
Code Quality
The code is well-structured and follows existing patterns in the codebase.
Strengths:
- The
_DELTA_ARROW_TO_PROTOdictionary refactoring (line 84-88 ofmetric.py) is a nice cleanup, consistent with the existing_DELTA_COLOR_TO_PROTOpattern. - The
truncateprop onStreamlitMarkdownis a good abstraction that eliminates the need forStyledTruncateTextwrappers, making the code cleaner and the truncation behavior reusable. - The
StyledDeltaContainerproperly uses flexbox withoverflow: hiddenandgapfor layout (lines 109-117 ofstyled-components.ts). - The
StyledDeltaDescriptionuses appropriate text truncation styles withflexShrink: 1andminWidth: 0(lines 119-130).
Minor observations:
-
In
metric.pyline 418,if delta_description:uses a truthy check rather thanif delta_description is not None:. This means an empty string""will not be sent to the frontend. The test at line 608 ofmetric_test.pyconfirms this is intentional (empty string maps to""), which is consistent - an empty description is treated the same as no description. This is fine and prevents sending meaningless empty strings over the wire. -
The
paddingBottomonStyledDeltaContainer(line 116 ofstyled-components.ts) matches the existingpaddingBottomonStyledMetricValueText(line 77), maintaining visual consistency. However, note that when both delta and delta description are shown together,StyledMetricDeltaText(the delta badge itself) no longer has its ownpaddingBottom- this is handled by the parent container, which is correct.
Test Coverage
Test coverage is comprehensive and well-structured:
Python unit tests (3 new parameterized test cases in metric_test.py):
- Tests
None, empty string, with delta, and without delta scenarios. - Properly asserts both
deltaanddelta_descriptionproto fields.
Frontend unit tests (7 new tests in Metric.test.tsx):
- Rendering with delta + description, description without delta, and absence when not provided.
- Styling verification (fontSize, title attribute).
- Accessibility test for
aria-describedbylinkage. - Good positive + negative assertion pattern (e.g., checking
stMetricDeltais not present when delta is empty).
StreamlitMarkdown tests (2 new tests):
- Verifies truncate styles are applied when
truncateis true. - Verifies truncate styles are NOT applied when
truncateis false (good anti-regression assertion).
E2E tests (st_metric_test.py):
delta_descriptionis tested across multiple existing test functions (test_second_metric_in_first_row,test_third_metric_in_first_row,test_border,test_code_in_help_shows_up_properly,test_custom_delta_color_render).- The E2E app script (
st_metric.py) includes severaldelta_descriptionexamples with varying lengths, material icons, and layout contexts. - Snapshot tests cover visual rendering across light/dark themes and all three browsers.
Overall test coverage is thorough and follows the testing guidelines well.
Backwards Compatibility
This change is fully backwards compatible:
- The new
delta_descriptionparameter defaults toNone, so existingst.metric()calls are unaffected. - The protobuf field
delta_description = 12is additive (new field number) - older frontends will simply ignore it, and newer frontends will handle its absence gracefully (empty string default in proto3). - The
truncateprop onStreamlitMarkdowndefaults toundefined/false, so existing usages are unaffected. - The
StyledTruncateTextremoval is a purely internal refactoring - it was not part of any public API. - The
_DELTA_ARROW_TO_PROTOrefactoring is a behavioral no-op.
Security & Risk
No security concerns identified:
- The
delta_descriptionis rendered throughStreamlitMarkdownwithallowHTML={false}, preventing XSS. - The
titleattribute is set to the raw description string, which is safely handled by the browser. - No user input is used in any dangerous context (no
dangerouslySetInnerHTML, no eval, etc.). - The
aria-describedbyIDs are generated via React'suseId(), which is safe.
Regression risk: Low. The truncate prop refactoring removes StyledTruncateText and replaces it with a truncate prop on StreamlitMarkdown. This changes the DOM structure slightly (removes a wrapper div), but the updated E2E snapshots across all browsers confirm visual equivalence. The lineHeight: "normal" addition in the truncate styles is explicitly noted as fixing inherited line-height issues, and a follow-up commit (925105e10) addressed an extra height regression.
Accessibility
Good accessibility implementation:
aria-describedby: The delta element (StyledMetricDeltaText) is linked to the description viaaria-describedby, allowing screen readers to announce the description in context with the delta value.titleattribute: TheStyledDeltaDescriptiondiv has atitleattribute set to the description text, providing native browser tooltips on hover for sighted users when text is truncated.useId(): React'suseId()hook generates unique IDs for the ARIA relationship, avoiding ID collisions.- No
aria-hiddenmisuse: The implementation correctly avoids hiding interactive content.
One minor consideration: When deltaDescription is provided without a delta value (the delta badge is not rendered), the description still renders but has no aria-describedby relationship since there's no delta element to link. The description is still accessible as regular text content, so this is fine.
Recommendations
-
Consider
is not Nonecheck fordelta_description: On line 418 ofmetric.py, the truthy checkif delta_description:silently discards empty strings. While the current behavior is reasonable and tested, usingif delta_description is not None:would be more explicit and consistent with howformatis handled on line 415 (if format is not None:). This is a very minor stylistic point and not a blocker. -
Consider adding a typing test: The codebase has typing tests in
lib/tests/streamlit/typing/for public API parameters. While there isn't currently one forst.metric, adding one with the newdelta_descriptionparameter would improve type safety coverage. This can be done as a follow-up.
Verdict
APPROVED: Well-implemented feature with thorough test coverage, good accessibility practices, full backwards compatibility, and clean code that follows existing patterns. The truncate prop refactoring is a nice improvement that makes the codebase cleaner. No blocking issues identified.
This is an automated AI review by opus-4.6-thinking.
- Change `if delta_description:` to `if delta_description is not None:` for consistency with format parameter handling - Add metric_types.py typing test covering all st.metric parameters including delta_description
The id attribute on the delta element was never used. The aria-describedby accessibility feature only needs the ID on the description element.
Replace color: fadedText60 with isCaption (opacity: 0.6) so that colored text, badges, and icons in delta_description are faded consistently with regular text. Simplifies StyledDeltaDescription by removing redundant styling now handled by StreamlitMarkdown props.
Remove the `-delta-description` suffix from the useId() generated ID since useId() already returns a unique ID, making the additional suffix unnecessary.
## Describe your changes Implements the `delta_description` parameter for `st.metric()` to display descriptive text next to delta values. The description appears in a muted gray font (similar to `st.caption`) with ellipsis overflow handling for responsive layouts. Includes accessibility improvements with ARIA labels for screen readers and native browser tooltips for mouse hover. ## Screenshot or video (only for visual changes) <img width="719" height="150" alt="image" src="https://github.com/user-attachments/assets/9cbc73a8-aff1-4a2f-a312-2b78b2fe0822" /> ## GitHub Issue Link (if applicable) - Closes #13690 ## Testing Plan - **Unit Tests (Python)**: 3 new tests verify delta_description parameter parsing and proto field setting - **Unit Tests (TypeScript)**: 7 new tests including accessibility tests for aria-label and aria-hidden attributes - **E2E Tests (Playwright)**: 3 new tests verify rendering with/without delta and title attribute - **Accessibility**: Tests confirm proper ARIA attributes for screen readers and title attribute for browser tooltips - All existing tests pass (68 Python, 58 Frontend unit tests; 6 E2E tests) --- **Contribution License Agreement** By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license. --------- Co-authored-by: Prashant <[email protected]>
Describe your changes
Implements the
delta_descriptionparameter forst.metric()to display descriptive text next to delta values. The description appears in a muted gray font (similar tost.caption) with ellipsis overflow handling for responsive layouts. Includes accessibility improvements with ARIA labels for screen readers and native browser tooltips for mouse hover.Screenshot or video (only for visual changes)
GitHub Issue Link (if applicable)
st.metric#13690Testing Plan
Contribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.
Co-authored-by: Prashant [email protected]