Skip to content

Conversation

@sfc-gh-nbellante
Copy link
Contributor

@sfc-gh-nbellante sfc-gh-nbellante commented Jan 8, 2026

Describe your changes

Changed file upload error messages in chat input to display as tooltips instead of inline text. This improves the UI by:

  1. Making the file chips more compact
  2. Showing error messages only when hovering over the file
  3. Using the standard tooltip component for error display

Screenshot or video (only for visual changes)

Designs

image

Actual

image image

Note: still need clarity on the x icon hover colors so will have that in a separate PR with the error text colors too.

Testing Plan

  • E2E Tests: Updated existing Playwright tests to verify error messages appear in tooltips instead of inline
  • Tests now check that:
    • Error tooltips appear when hovering over file chips
    • Error tooltips contain the correct error messages
    • Tooltips disappear after successful retry uploads
  • Added js tests for the file chip and tested for the newly added a11y for the errors

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

@snyk-io
Copy link
Contributor

snyk-io bot commented Jan 8, 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
Contributor

github-actions bot commented Jan 8, 2026

✅ PR preview is ready!

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

Copy link
Contributor Author

sfc-gh-nbellante commented Jan 8, 2026

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

📈 Frontend coverage change detected

The frontend unit test (vitest) coverage has increased by 0.0200%

  • Current PR: 86.5900% (12828 lines, 1719 missed)
  • Latest develop: 86.5700% (12821 lines, 1721 missed)

✅ Coverage change is within normal range.

📊 View detailed coverage comparison

@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch from ed68149 to dbd224c Compare January 8, 2026 17:18
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-icon-border-radius branch from 5c4ff72 to 7992f54 Compare January 8, 2026 17:18
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch 2 times, most recently from 56c60d9 to 8b7b2fb Compare January 8, 2026 17:48
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-icon-border-radius branch 2 times, most recently from 114c830 to cc7e6e4 Compare January 8, 2026 20:56
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch from 8b7b2fb to ca26e50 Compare January 8, 2026 20:56
@sfc-gh-nbellante sfc-gh-nbellante marked this pull request as ready for review January 8, 2026 20:56
@sfc-gh-nbellante sfc-gh-nbellante changed the base branch from fixit/file-chip-icon-border-radius to graphite-base/13542 January 8, 2026 21:24
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch from ca26e50 to c403751 Compare January 8, 2026 21:32
@sfc-gh-nbellante sfc-gh-nbellante changed the base branch from graphite-base/13542 to fixit/file-chip-icon-border-radius January 8, 2026 21:32
@sfc-gh-nbellante sfc-gh-nbellante marked this pull request as draft January 8, 2026 21:34
@sfc-gh-nbellante sfc-gh-nbellante added security-assessment-completed Security assessment has been completed for PR change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Jan 8, 2026
@sfc-gh-nbellante sfc-gh-nbellante changed the title Show file upload error as tooltip instead of inline text [feat] Replace inline error messages with tooltips in st.chat_input file upload UI Jan 8, 2026
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-icon-border-radius branch from 44c5a57 to 111ca6a Compare January 8, 2026 22:02
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch from c403751 to ab30b4c Compare January 8, 2026 22:02
@sfc-gh-nbellante sfc-gh-nbellante marked this pull request as ready for review January 8, 2026 22:02
@sfc-gh-nbellante sfc-gh-nbellante added change:chore PR contains maintenance or housekeeping change and removed change:feature PR contains new feature or enhancement implementation labels Jan 9, 2026
@sfc-gh-nbellante sfc-gh-nbellante marked this pull request as ready for review January 9, 2026 04:29
Copilot AI review requested due to automatic review settings January 9, 2026 04:29
Copy link
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

This PR replaces inline error messages with hover tooltips in the st.chat_input file upload UI to create a more compact and visually clean design. Error messages are now displayed in tooltips when users hover over file chips in an error state, using the standard Tooltip component.

Key Changes

  • Removed inline error display in favor of tooltip-based error messages
  • File chips now show file size consistently, with errors appearing only on hover
  • Updated E2E tests to verify tooltip behavior and interactions

Reviewed changes

Copilot reviewed 3 out of 15 changed files in this pull request and generated 2 comments.

File Description
frontend/lib/src/components/widgets/ChatInput/fileUpload/ChatUploadedFile.tsx Refactored to conditionally wrap error file chips in Tooltip component; removed inline error text display
frontend/lib/src/components/widgets/ChatInput/fileUpload/styled-components.ts Removed unused StyledChatUploadedFileError styled component
e2e_playwright/st_chat_input_test.py Updated tests to verify error tooltips appear on hover instead of inline; added tooltip visibility assertions
e2e_playwright/__snapshots__/linux/st_chat_input_test/*.png Added new snapshot files for error tooltip appearance and updated error file chip snapshots

@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch 2 times, most recently from fdd0f59 to e357f7d Compare January 9, 2026 04:52
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch from e357f7d to d7cff11 Compare January 9, 2026 05:01
@sfc-gh-lmasuch sfc-gh-lmasuch added the ai-review If applied to PR or issue will run AI review workflow label Jan 9, 2026
@lukasmasuch
Copy link
Collaborator

@cursor review

@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Jan 9, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

Summary

This PR replaces inline error messages with tooltips for file upload errors in st.chat_input. The changes make file chips more compact by showing error messages only when hovering over the file chip, using the standard Tooltip component with the error prop for error display.

Key changes:

  • ChatUploadedFile.tsx: Wraps error-state file chips with <Tooltip error> instead of displaying inline error text
  • styled-components.ts: Removes StyledChatUploadedFileError, adds StyledVisuallyHidden for accessibility
  • ChatUploadedFile.test.tsx: New comprehensive unit test file for the component
  • E2E tests: Updated to verify tooltip behavior instead of inline error text

Code Quality

The code is well-structured and follows the established patterns in the Streamlit codebase:

React best practices followed:

  • Proper use of memo for component memoization
  • useCallback for handler stability with correct dependency arrays
  • useId() for unique accessible IDs

Excellent accessibility implementation:

  • aria-invalid={isError || undefined} properly indicates error state
  • aria-describedby links to visually hidden error message
  • role="alert" on hidden element ensures screen readers announce errors immediately
  • Clear comment explaining WCAG 3.3.1 compliance rationale (lines 176-182 in ChatUploadedFile.tsx)

Clean code removal:

  • StyledChatUploadedFileError styled component properly removed
  • No orphaned references to the old inline error display

Proper eslint handling:

  • StyledVisuallyHidden uses the standard visually-hidden CSS pattern with appropriate eslint disable comment explaining why hardcoded values are necessary

Minor observation:

  • The sizeDisplay is computed but always shown (line 163-165), even in error states. This is intentional per the design (showing file size alongside error tooltip), which is a reasonable UX choice.

Test Coverage

Frontend Unit Tests (ChatUploadedFile.test.tsx):

✅ Comprehensive test coverage including:

  • Aria-label verification for uploaded files
  • Error state accessibility (aria-invalid, aria-describedby, role="alert")
  • Retry functionality (click and keyboard activation)
  • Delete button behavior with correct aria-labels
  • Negative assertions (no alert when not in error state)

The tests follow RTL best practices:

  • Uses userEvent for user interactions
  • Appropriate use of getBy*, queryBy* patterns
  • Tests behavior, not implementation details

E2E Tests (st_chat_input_test.py):

✅ Properly updated to test new tooltip behavior:

  • Verifies tooltip appears on hover
  • Verifies tooltip content contains correct error message
  • Good negative assertion: expect(themed_app.get_by_test_id("stTooltipErrorContent")).not_to_be_visible() before hover
  • Snapshot tests for both file chip and tooltip

The E2E tests follow best practices from .cursor/rules/e2e_playwright.mdc:

  • Uses expect for auto-wait assertions
  • Uses get_by_test_id locators
  • Screenshots specific elements, not the whole page

Backwards Compatibility

No breaking changes. This is a purely visual/UX change:

  • No Python API changes
  • No changes to protobuf definitions
  • File upload functionality remains identical
  • Error messages are still shown, just in a different UI element (tooltip vs inline)

Users will not need to modify any code to adopt this change.

Security & Risk

No security concerns identified:

  • No new user inputs processed
  • No changes to file upload handling logic
  • No changes to server communication
  • Changes are purely presentational

Low regression risk:

  • The error tooltip uses the existing, well-tested Tooltip component with its error prop
  • Accessibility is actually improved with the new implementation (visually hidden alert for screen readers)

Recommendations

The implementation is solid. A few optional suggestions for future consideration:

  1. Consider adding a tooltip test in unit tests: While E2E tests verify the tooltip appears, the unit test file doesn't test that the Tooltip component wrapper is rendered correctly when in error state. This is acceptable since the Tooltip component itself is already well-tested, but could be added for completeness.

  2. Test coverage enhancement (optional): Consider adding a test case for the scenario where onRetry is provided but fileInfo.file is undefined (retry should not be possible). The current tests cover the happy path where both are present.

Verdict

APPROVED: This is a well-implemented UX improvement that follows React best practices, includes comprehensive accessibility support, and has thorough test coverage at both unit and E2E levels. The code is clean, well-documented, and backwards compatible.


This is an automated AI review. Please verify the feedback and use your judgment.

Copy link

@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 bugs!

Comment on lines +183 to +188
{isError && (
<StyledVisuallyHidden id={errorId} role="alert">
Error: {errorMessage}
</StyledVisuallyHidden>
)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpick: Wouldn't it be possible to handle this from within Tooltip by making the tooltip content always accessible? And isn't there a way to directly attach this to the tooltip DOM element, or is there no DOM element related to the tooltip if it's not rendered? cc @sfc-gh-bnisco for expertise on accessibility.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for flagging, I had to do some investigation on this one.

To directly answer Lukas's comments: We could update the Tooltip API to ensure it always exists in the DOM, but that would be a change across every usage of Tooltip, and may cause unexpected side-effects without auditing every usage. Generally speaking, most component libraries only render Tooltip instances when they are triggered, so right now our behavior is aligned with that and we probably don't want to change that.

It looks like the main thing here is that this uses role="alert", which is not a pattern we have used much internally, but is a legitimate usecase here. Since the Tooltip DOM element doesn't exist until it's triggered, there is nothing that could be used in aria-describedby with current implementation, hence the addition of this StyledVisuallyHidden span. This seems reasonable to me.

I have a different piece of a11y feedback, but will put in a separate comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the discussion guys. I came to the same conclusion Bob did about the tooltip not being present until hover putting us in a sort of catch 22 situation when trying to solve this globally. I didn't think of the idea where we change tooltip to be present in the DOM always, but agree that involves more risk.

Copy link
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

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

LGTM 👍 the accessibility aspect might need another check

Comment on lines +183 to +188
{isError && (
<StyledVisuallyHidden id={errorId} role="alert">
Error: {errorMessage}
</StyledVisuallyHidden>
)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for flagging, I had to do some investigation on this one.

To directly answer Lukas's comments: We could update the Tooltip API to ensure it always exists in the DOM, but that would be a change across every usage of Tooltip, and may cause unexpected side-effects without auditing every usage. Generally speaking, most component libraries only render Tooltip instances when they are triggered, so right now our behavior is aligned with that and we probably don't want to change that.

It looks like the main thing here is that this uses role="alert", which is not a pattern we have used much internally, but is a legitimate usecase here. Since the Tooltip DOM element doesn't exist until it's triggered, there is nothing that could be used in aria-describedby with current implementation, hence the addition of this StyledVisuallyHidden span. This seems reasonable to me.

I have a different piece of a11y feedback, but will put in a separate comment.

@sfc-gh-bnisco
Copy link
Collaborator

Kapture.2026-01-09.at.10.00.47.mp4

question: Why does clicking (or hitting enter with keyboard when focused) on this element cause the error state to go away?

@sfc-gh-nbellante sfc-gh-nbellante force-pushed the fixit/file-chip-error-tooltip branch from d7cff11 to a419335 Compare January 10, 2026 23:05
The aria-label now always shows filename and size (not error message)
to avoid screen readers double-announcing the error. Error is conveyed
via aria-describedby linking to the visually hidden error element.
@sfc-gh-nbellante sfc-gh-nbellante merged commit 6e7afbf into develop Jan 11, 2026
45 checks passed
@sfc-gh-nbellante sfc-gh-nbellante deleted the fixit/file-chip-error-tooltip branch January 11, 2026 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:chore PR contains maintenance or housekeeping change impact:users PR changes affect end users security-assessment-completed Security assessment has been completed for PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants