Skip to content

Add delta_description to st.metric#13848

Merged
lukasmasuch merged 29 commits intodevelopfrom
lukasmasuch/metric-delta-desc
Feb 17, 2026
Merged

Add delta_description to st.metric#13848
lukasmasuch merged 29 commits intodevelopfrom
lukasmasuch/metric-delta-desc

Conversation

@lukasmasuch
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch commented Feb 6, 2026

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)

image

GitHub Issue Link (if applicable)

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]

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.
Copilot AI review requested due to automatic review settings February 6, 2026 16:34
@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Feb 6, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 6, 2026

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-13848/streamlit-1.54.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-13848.streamlit.app (☁️ Deploy here if not accessible)

@lukasmasuch lukasmasuch added security-assessment-completed change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Feb 6, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Metric protobuf with a delta_description field and plumb it through the Python st.metric() API.
  • Update the frontend Metric component 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.

@lukasmasuch lukasmasuch changed the title Add delta_description parameter to st.metric Add delta_description to st.metric Feb 6, 2026
@lukasmasuch lukasmasuch changed the title Add delta_description to st.metric Add delta_description to st.metric Feb 6, 2026
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.
@lukasmasuch lukasmasuch force-pushed the lukasmasuch/metric-delta-desc branch from 98e1dd8 to 22daf90 Compare February 6, 2026 19:23
@lukasmasuch lukasmasuch force-pushed the lukasmasuch/metric-delta-desc branch from d54d9d1 to c4d7041 Compare February 6, 2026 19:35
@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Feb 6, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Feb 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 6, 2026

Summary

This PR adds a new delta_description parameter to st.metric(), allowing users to display a short descriptive text (e.g., "month over month", "vs. last quarter") next to the delta value. The implementation spans the full stack:

  • Proto: New string delta_description = 12 field in Metric.proto.
  • Python backend (lib/streamlit/elements/metric.py): New delta_description: str | None = None keyword argument, passed through to the proto.
  • Frontend (Metric.tsx, styled-components.ts): New StyledDeltaContainer and StyledDeltaDescription components to render the description. Adds accessibility support via aria-describedby linking the delta to its description.
  • Tests: 3 Python unit tests, 7 TypeScript unit tests, and E2E coverage integrated into existing test cases.

Also includes a minor refactor of the delta_arrow mapping logic to use a dictionary lookup (_DELTA_ARROW_TO_PROTO) consistent with the existing _DELTA_COLOR_TO_PROTO pattern.

Code Quality

Python backend (lib/streamlit/elements/metric.py):

  • Clean, well-structured implementation. The delta_description parameter is keyword-only (after the *), which is correct.
  • The _DELTA_ARROW_TO_PROTO dictionary refactor is a nice improvement that follows the same pattern as _DELTA_COLOR_TO_PROTO.
  • The docstring for delta_description is clear and follows the existing parameter documentation style.
  • The parameter defaults to None and only sets the proto field when non-None, which is the correct protobuf pattern (empty string is the default for proto3 string fields).

Frontend (Metric.tsx):

  • Good use of useId() for generating unique ARIA IDs -- this is the React-recommended approach.
  • The aria-describedby pattern correctly links the delta badge to the description for screen readers, and is only set when deltaDescription exists.
  • The conditional rendering logic (deltaExists || deltaDescription) correctly handles the case where delta_description is provided without a delta value.
  • The title attribute on StyledDeltaDescription provides a native browser tooltip for truncated text, which is a thoughtful UX touch.

Styled components (styled-components.ts):

  • StyledDeltaContainer uses flexbox row layout with proper overflow handling.
  • StyledDeltaDescription uses flexShrink: 1 + minWidth: 0 which correctly allows truncation while the delta badge (flexShrink: 0) stays fixed-width.
  • Text truncation with textOverflow: "ellipsis" is handled at both the container and the nested markdown levels.
  • Gap uses 0.5em (relative unit), which follows the guideline of avoiding pixel sizes.

Minor observations:

  • The paddingBottom: theme.spacing.threeXS on StyledDeltaContainer (line 134) introduces bottom padding for the delta row. Previously this padding was absent since the delta badge was a standalone element. This is a subtle visual change but should be fine since it appears intentional for the new layout.

Test Coverage

Python unit tests (lib/tests/streamlit/elements/metric_test.py):

  • 3 new tests covering: default None behavior, with delta, and without delta. All have docstrings.
  • The tests correctly verify the proto field values.
  • Good coverage of the key scenarios (with delta, without delta, default).

Frontend unit tests (Metric.test.tsx):

  • 7 new tests in a well-organized describe("Delta description") block.
  • Tests cover: rendering with delta, rendering without delta, not rendering when absent, correct styling, title attribute, aria-describedby link, and ensuring no problematic ARIA patterns.
  • Good use of RTL queries (getByTestId, queryByTestId) following the correct patterns for presence/absence assertions.
  • The aria-describedby test properly verifies the ID linkage between the delta and description elements.

E2E tests (e2e_playwright/st_metric_test.py):

  • Delta description is tested across multiple existing test functions (not as separate tests, which is efficient per E2E best practices):
    • test_second_metric_in_first_row verifies "since open" text.
    • test_third_metric_in_first_row verifies visibility with long description.
    • test_border verifies delta_description with material icon.
    • test_code_in_help_shows_up_properly verifies "year over year" text.
    • test_custom_delta_color_render verifies "month over month" with yellow delta.
  • Good approach of adding delta_description to existing E2E test scenarios rather than creating separate test scripts.
  • Snapshot tests will capture the visual appearance across themes and browsers.

Coverage gap (minor): No typing test file exists for st.metric in lib/tests/streamlit/typing/. However, the PR description doesn't mention adding one, and this appears to be a pre-existing gap not introduced by this PR.

Backwards Compatibility

  • Fully backwards compatible. The delta_description parameter defaults to None, and when None, the proto field is not set (defaults to empty string in proto3), so existing code is unaffected.
  • The proto field uses field number 12 (next available), which is correct.
  • The _DELTA_ARROW_TO_PROTO refactor is a pure internal refactor with identical behavior.
  • The new StyledDeltaContainer wrapper around the delta area doesn't change the rendering when deltaDescription is absent because the container condition (deltaExists || deltaDescription) and the inner condition deltaExists preserve the original behavior.
  • The addition of flexShrink: 0 to StyledMetricDeltaText and the wrapper StyledDeltaContainer with paddingBottom may cause minor visual differences for existing metrics (the delta badge is now wrapped in a flex container with some bottom padding). This is captured in the snapshot updates.

Security & Risk

  • No security concerns. The delta_description is rendered through StreamlitMarkdown with allowHTML={false}, preventing XSS.
  • The title attribute uses the raw deltaDescription string, but title attributes are inherently safe (HTML-escaped by React).
  • No risk of injection since all user-provided strings go through the protobuf serialization layer.

Accessibility

  • Well implemented. The aria-describedby pattern correctly associates the delta value with its description for screen readers.
  • useId() generates stable, unique IDs that work correctly with React's server-side rendering and concurrent features.
  • The title attribute provides a native tooltip for sighted users on hover, which helps when the description is truncated.
  • The test at line 745 (does not use container aria-label fallback for markdown deltas) correctly ensures no over-engineering of ARIA patterns that could confuse screen readers.
  • One minor observation: when only deltaDescription is provided without delta, the description renders alone. In this case, the description has no aria-describedby target since there's no delta element. This is acceptable since the description itself is readable by screen readers via its text content.

Recommendations

No blocking issues found. The following are minor, non-blocking suggestions:

  1. Consider input validation for delta_description: The backend currently accepts any string (including empty strings). An empty string "" would render the StyledDeltaDescription container with no visible text. Consider treating "" the same as None in the backend (i.e., if delta_description is not None and delta_description != ""), or document that empty strings are a no-op.

  2. Consider adding a typing test: While this is a pre-existing gap, adding a lib/tests/streamlit/typing/metric_types.py file with assert_type checks for the new delta_description parameter would improve type safety coverage.

  3. Minor CSS note: The StyledDeltaDescription nested CSS selectors ("& > div" > "& > p") duplicate the truncation pattern found in StyledTruncateText. If this pattern is reused further in the future, it might be worth extracting into a shared mixin. This is very low priority.

Verdict

APPROVED: 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 opus-4.6-thinking. Please verify the feedback and use your judgment.

Empty string "" is now treated the same as None, avoiding setting
an unnecessary proto field. Added test to verify the behavior.
@lukasmasuch lukasmasuch force-pushed the lukasmasuch/metric-delta-desc branch from 4d94966 to 9b15ee4 Compare February 6, 2026 20:42
lukasmasuch and others added 2 commits February 12, 2026 16:06
Consolidate Python tests into a single parameterized test and
combine redundant TypeScript tests for cleaner, more maintainable
test code while preserving the same coverage.
@lukasmasuch
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

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.
@streamlit streamlit deleted a comment from github-actions bot Feb 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Consolidated Code Review: delta_description support for st.metric

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 the full stack:

  • Protobuf: New delta_description field (field number 12) added to Metric.proto.
  • Python backend: New optional delta_description parameter with docstring, truthy-check validation, and proto serialization. Also refactors delta_arrow mapping to a dictionary lookup (_DELTA_ARROW_TO_PROTO), consistent with the existing _DELTA_COLOR_TO_PROTO pattern.
  • Frontend: New StyledDeltaContainer and StyledDeltaDescription styled components. The description renders next to the delta badge with ellipsis overflow, title attribute for hover, and aria-describedby ARIA linkage.
  • Refactoring: Moves text truncation from a StyledTruncateText wrapper into a reusable truncate prop on StreamlitMarkdown, simplifying metric JSX and benefiting future consumers.

Reviewer Consensus

Both reviewers (gpt-5.3-codex-high and opus-4.6-thinking) approved the PR unanimously. There were no disagreements on any aspect of the review. Below is a synthesis of their findings.

Code Quality

Agreement: High quality, follows existing patterns.

Both reviewers found the code well-structured and consistent with codebase conventions:

  • The _DELTA_ARROW_TO_PROTO dictionary refactoring is a clean improvement.
  • The truncate prop on StreamlitMarkdown is a good abstraction that eliminates wrapper components and improves reusability.
  • Styling uses proper flexbox layout with overflow: hidden, gap, flexShrink: 1, and minWidth: 0 for robust truncation behavior.
  • Concerns (rendering vs. styling) are well-separated across files.

Minor observation (opus-4.6-thinking): The truthy check if delta_description: on line 418 of metric.py silently discards empty strings. This is intentional and tested (confirmed by metric_test.py line 608), but using if delta_description is not None: would be more explicit and consistent with how format is handled on line 415. This is a stylistic point, not a blocker.

Test Coverage

Agreement: Comprehensive and well-structured.

Both reviewers highlighted the thorough multi-layer testing:

  • Python unit tests: 3 new parameterized test cases covering None, empty string, with-delta, and without-delta scenarios.
  • Frontend unit tests: 7 new tests covering rendering states, styling/title behavior, and accessibility wiring, with good positive + negative assertion patterns.
  • StreamlitMarkdown tests: 2 new tests validating the truncate prop in both true/false states.
  • E2E tests: delta_description tested across multiple existing test functions with varying lengths, material icons, and layout contexts. Snapshots cover light/dark themes and all three browsers.

Backwards Compatibility

Agreement: Fully backwards compatible, no breaking changes.

  • delta_description defaults to None; existing calls are unaffected.
  • Protobuf field 12 is additive; older frontends ignore it, newer frontends handle its absence via proto3 defaults.
  • The truncate prop defaults to undefined/false; existing StreamlitMarkdown usages are unaffected.
  • StyledTruncateText removal is purely internal.
  • _DELTA_ARROW_TO_PROTO refactoring is a behavioral no-op.

Security & Risk

Agreement: No security concerns; low regression risk.

  • delta_description is rendered through StreamlitMarkdown with allowHTML={false}, preventing XSS.
  • title attribute and aria-describedby IDs (via React useId()) are safely handled.
  • No dangerouslySetInnerHTML, eval, or other dangerous patterns.
  • The truncate refactoring changes DOM structure slightly (removes a wrapper div), but updated E2E snapshots across all browsers confirm visual equivalence. A follow-up commit (925105e10) addressed an extra height regression from lineHeight: "normal".

Accessibility

Agreement: Good accessibility implementation.

  • aria-describedby links the delta element to its description for screen readers.
  • title attribute provides native tooltips for truncated text.
  • useId() generates unique ARIA IDs, avoiding collisions.
  • When deltaDescription is provided without a delta value, the description renders as regular accessible text content (no broken ARIA reference).

Recommendations

  1. Consider is not None check (minor, non-blocking): Using if delta_description is not None: instead of if delta_description: on line 418 of metric.py would be more explicit and consistent with the format parameter handling. Both reviewers noted this is not a blocker.

  2. Add typing test as follow-up (both reviewers agreed): Consider adding a typing-focused test for st.metric(..., delta_description=...) in lib/tests/streamlit/typing/ to improve type safety coverage.

  3. Note snapshot churn in PR description (gpt-5.3-codex-high): If not already done, note that the broad snapshot updates are expected from truncation/line-height adjustments to ease reviewer verification.

Verdict

APPROVED

Both reviewers approved unanimously. The feature is coherently implemented across backend, frontend, and protobuf with thorough test coverage, good accessibility practices, full backwards compatibility, and clean code that follows existing patterns. No blocking issues were identified.

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.py are focused and preserve existing metric parsing/validation flow.
  • Frontend changes in frontend/lib/src/components/elements/Metric/Metric.tsx and frontend/lib/src/components/elements/Metric/styled-components.ts keep concerns well-separated (rendering vs. styling).
  • Reuse of StreamlitMarkdown truncation in frontend/lib/src/components/shared/StreamlitMarkdown/StreamlitMarkdown.tsx and frontend/lib/src/components/shared/StreamlitMarkdown/styled-components.ts improves 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.py verify proto assignment behavior for None, empty, and populated delta_description.
  • Frontend unit tests in frontend/lib/src/components/elements/Metric/Metric.test.tsx cover render/no-render states, styling/title behavior, and accessibility wiring.
  • StreamlitMarkdown tests in frontend/lib/src/components/shared/StreamlitMarkdown/StreamlitMarkdown.test.tsx validate the new truncate style behavior.
  • E2E updates in e2e_playwright/st_metric.py and e2e_playwright/st_metric_test.py validate runtime rendering and snapshot results.

Overall, the changed behavior appears adequately tested.

Backwards Compatibility

No breaking change detected:

  • delta_description is an additive, optional keyword-only parameter on st.metric.
  • Protobuf adds a new field number (delta_description = 12) without altering existing field semantics.
  • Existing st.metric calls without the new parameter continue to behave as before.

Security & Risk

No security concerns identified:

  • Rendering continues to use StreamlitMarkdown with allowHTML={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-describedby in frontend/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

  1. 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.
  2. 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_description field (field number 12) added to Metric.proto.
  • Python backend: New delta_description parameter with docstring, validation (truthy check), and proto serialization. Also refactors delta_arrow mapping to use a dictionary lookup (_DELTA_ARROW_TO_PROTO).
  • Frontend: New StyledDeltaContainer and StyledDeltaDescription styled components. The description renders next to the delta badge with ellipsis overflow, title attribute for hover, and ARIA aria-describedby linking.
  • Refactoring: Moves text truncation from a StyledTruncateText wrapper component into a new truncate prop on StreamlitMarkdown, 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_PROTO dictionary refactoring (line 84-88 of metric.py) is a nice cleanup, consistent with the existing _DELTA_COLOR_TO_PROTO pattern.
  • The truncate prop on StreamlitMarkdown is a good abstraction that eliminates the need for StyledTruncateText wrappers, making the code cleaner and the truncation behavior reusable.
  • The StyledDeltaContainer properly uses flexbox with overflow: hidden and gap for layout (lines 109-117 of styled-components.ts).
  • The StyledDeltaDescription uses appropriate text truncation styles with flexShrink: 1 and minWidth: 0 (lines 119-130).

Minor observations:

  1. In metric.py line 418, if delta_description: uses a truthy check rather than if delta_description is not None:. This means an empty string "" will not be sent to the frontend. The test at line 608 of metric_test.py confirms 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.

  2. The paddingBottom on StyledDeltaContainer (line 116 of styled-components.ts) matches the existing paddingBottom on StyledMetricValueText (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 own paddingBottom - 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 delta and delta_description proto 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-describedby linkage.
  • Good positive + negative assertion pattern (e.g., checking stMetricDelta is not present when delta is empty).

StreamlitMarkdown tests (2 new tests):

  • Verifies truncate styles are applied when truncate is true.
  • Verifies truncate styles are NOT applied when truncate is false (good anti-regression assertion).

E2E tests (st_metric_test.py):

  • delta_description is 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 several delta_description examples 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_description parameter defaults to None, so existing st.metric() calls are unaffected.
  • The protobuf field delta_description = 12 is additive (new field number) - older frontends will simply ignore it, and newer frontends will handle its absence gracefully (empty string default in proto3).
  • The truncate prop on StreamlitMarkdown defaults to undefined/false, so existing usages are unaffected.
  • The StyledTruncateText removal is a purely internal refactoring - it was not part of any public API.
  • The _DELTA_ARROW_TO_PROTO refactoring is a behavioral no-op.

Security & Risk

No security concerns identified:

  • The delta_description is rendered through StreamlitMarkdown with allowHTML={false}, preventing XSS.
  • The title attribute 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-describedby IDs are generated via React's useId(), 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 via aria-describedby, allowing screen readers to announce the description in context with the delta value.
  • title attribute: The StyledDeltaDescription div has a title attribute set to the description text, providing native browser tooltips on hover for sighted users when text is truncated.
  • useId(): React's useId() hook generates unique IDs for the ARIA relationship, avoiding ID collisions.
  • No aria-hidden misuse: 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

  1. Consider is not None check for delta_description: On line 418 of metric.py, the truthy check if delta_description: silently discards empty strings. While the current behavior is reasonable and tested, using if delta_description is not None: would be more explicit and consistent with how format is handled on line 415 (if format is not None:). This is a very minor stylistic point and not a blocker.

  2. 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 for st.metric, adding one with the new delta_description parameter 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.
lukasmasuch and others added 2 commits February 17, 2026 22:45
Remove the `-delta-description` suffix from the useId() generated ID since
useId() already returns a unique ID, making the additional suffix unnecessary.
@lukasmasuch lukasmasuch enabled auto-merge (squash) February 17, 2026 21:54
@lukasmasuch lukasmasuch merged commit 2e1bc60 into develop Feb 17, 2026
43 checks passed
@lukasmasuch lukasmasuch deleted the lukasmasuch/metric-delta-desc branch February 17, 2026 22:05
lukasmasuch added a commit that referenced this pull request Feb 20, 2026
## 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add delta description for st.metric

4 participants