-
Notifications
You must be signed in to change notification settings - Fork 4k
[fix] Ensure help Tooltips are accessible #13379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[fix] Ensure help Tooltips are accessible #13379
Conversation
✅ 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!
|
frontend/lib/src/components/shared/TooltipIcon/TooltipIcon.test.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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 enhances accessibility for help tooltips across Streamlit widgets by making them keyboard-navigable and properly labeled for screen readers. The changes fix issue #13330 by introducing focusable button triggers with appropriate ARIA labels for all help tooltips.
Key Changes
- Introduced
WidgetLabelHelpIconandWidgetLabelHelpIconInlinewrapper components that ensure help tooltips have accessible names - Refactored
TooltipIconto render a focusable<button>with requiredariaLabelwhen no custom trigger is provided - Updated
WidgetLabelto wrap label text inaria-hidden="true"span, preventing duplicate announcements while keeping help icons accessible - Standardized focus ring styling by introducing
getFocusRingBoxShadowutility (applied in Checkbox)
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
TooltipIcon.tsx |
Core accessibility improvements: renders focusable button trigger with required aria-label, adds getHelpTooltipAriaLabel utility |
TooltipIcon.test.tsx |
Comprehensive test coverage for keyboard navigation, focus management, and aria-label generation |
WidgetLabelHelpIcon.tsx |
New wrapper component for standard widget help tooltips with automatic aria-label generation |
WidgetLabelHelpIconInline.tsx |
New wrapper component for inline help tooltips (checkboxes, radio buttons, etc.) |
WidgetLabel.tsx |
Wraps label text in aria-hidden span to prevent duplicate screen reader announcements |
WidgetLabel.test.tsx |
Tests verifying help icons remain accessible and no nested labels are rendered |
BaseWidget/styled-components.ts |
Added deprecation notices for StyledWidgetLabelHelp and StyledWidgetLabelHelpInline |
BaseWidget/index.ts |
Exports new wrapper components |
TooltipIcon/styled-components.ts |
Added StyledTooltipTriggerButton with focus-visible styles, refined icon selector |
| Widget components (TimeInput, TextInput, TextArea, Slider, NumberInput, Multiselect, FileUploader, DateTimeInput, DateInput, CameraInput, AudioInput) | Replaced direct TooltipIcon usage with WidgetLabelHelpIcon, passing label prop for accessible naming |
| Inline widgets (Checkbox, ButtonGroup, Radio, BaseColorPicker, Metric) | Replaced direct TooltipIcon usage with WidgetLabelHelpIconInline, passing label prop |
Checkbox.tsx |
Refactored to use getFocusRingBoxShadow utility for consistent focus styling |
ChatFileUploadButton.tsx |
Added comment and explicit role="presentation" to react-dropzone wrapper to prevent duplicate tab stops |
st_slider_test.py |
Added keyboard accessibility test using tab_until_focused helper |
st_number_input_test.py |
Added exact=True to get_by_label to avoid matching help button |
st_chat_input_test.py |
Updated to use semantic role-based query instead of test-id |
help_tooltip_test.py |
Updated to use more specific test-id selector |
📈 Frontend coverage change detectedThe frontend unit test (vitest) coverage has increased by 0.0300%
🎉 Great job on improving test coverage! |
8058013 to
8eeeed6
Compare
19fc960 to
9d2389d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 4 comments.
frontend/lib/src/components/widgets/ChatInput/fileUpload/ChatFileUploadButton.tsx
Outdated
Show resolved
Hide resolved
9d2389d to
bd91eae
Compare
8eeeed6 to
92962c4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 4 comments.
frontend/lib/src/components/widgets/BaseWidget/WidgetLabelHelpIconInline.tsx
Show resolved
Hide resolved
frontend/lib/src/components/widgets/BaseWidget/styled-components.ts
Outdated
Show resolved
Hide resolved
92962c4 to
8f4981c
Compare
fe94434 to
9678331
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 1 comment.
frontend/lib/src/components/shared/TooltipIcon/TooltipIcon.test.tsx
Outdated
Show resolved
Hide resolved
📈 Python coverage change detectedThe Python unit test coverage has increased by 0.0048%
✅ Coverage change is within normal range. Coverage by files
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 33 out of 33 changed files in this pull request and generated no new comments.
890c54b to
2b0685b
Compare
970be49 to
b9ebcd3
Compare
b9ebcd3 to
a97d86d
Compare
2b0685b to
a43eaa6
Compare
a97d86d to
13c6d1e
Compare
a43eaa6 to
4a5eaaa
Compare
2b8e1d2 to
8a2c991
Compare
4a5eaaa to
1ca104b
Compare
|
@cursor review |
| outline: `${theme.sizes.borderWidth} solid ${theme.colors.primary}`, | ||
| outlineOffset: theme.spacing.threeXS, | ||
| borderRadius: theme.radii.default, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Its probably intended that this is using outline instead of boxShadow as we use with some other aspects? Does it make sense to unify this at some point. My personal preference would be the outline style, the box shadow feels a bit heavy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, actually I want do intend to keep this consistent for now. Since everything else is boxShadow, I'm going to switch this over.
But you're right that we should unify this across the app and set up clear rules _ guidelines for this. I think we should run it by design to see what they think long-term.
Some food for thought: Tailwind uses box-shadow but react-aria uses outline.
lukasmasuch
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
8a2c991 to
c1661f5
Compare
a721158 to
df76e8b
Compare
c1661f5 to
2e5419f
Compare
df76e8b to
4d7a96e
Compare
Merge activity
|
4d7a96e to
fb7e0b0
Compare

Describe your changes
Improved accessibility of help tooltips across Streamlit components:
WidgetLabelHelpIconandWidgetLabelHelpIconInlinecomponentsScreenshot or video (only for visual changes)
In this video, I navigate to the Tooltip via keyboard, it displays. I tab away and it is hidden. When I tab back, it displays, I click
escapeand the Tooltip itself is hidden but the trigger focus state remains:Kapture.2025-12-16.at.16.08.26.mp4
In this video, I use the keyboard to bring focus to the
Helpon a Streamlit component (in this case, a Slider), to show how keyboarding works here too:Kapture.2025-12-16.at.16.09.24.mp4
GitHub Issue Link (if applicable)
Testing 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.