Revisit accessibility pattern for tooltips on badges/labels: button wrapper vs tabindex approach
Summary
Following a discussion in gitlab-org/gitlab!186486 (merged), we need to revisit our current accessibility pattern for making tooltips and popovers on non-focusable elements keyboard accessible. This includes tooltips or popovers attached to badges, labels or icons.
Current Pattern
Our current Pajamas tooltip guidelines recommend wrapping elements with tooltips in buttons:
so we don't have to add
tabindex=0to the icon.
This pattern was implemented in MR !186486 for pipeline labels, where gl-badge elements were wrapped in <button> elements with specific styling to make them appear as non-interactive badges while maintaining keyboard accessibility.
The Problem
The current button wrapper approach creates challenges:
- Semantic confusion: We're creating buttons that don't perform actions, which feels semantically incorrect
- Styling complexity: Only some labels are wrapped in buttons, requiring manual class management for consistent spacing and layout
- Responsive design issues: Different wrapping patterns make it difficult to create consistent responsive layouts (mobile/desktop stacking)
Alternative Approach
An alternative approach would be to use tabindex="0" directly on the badge elements instead of wrapping them in buttons. Testing shows this also makes tooltips keyboard accessible.
Questions to Address
- What was the original reasoning behind preferring button wrappers over
tabindex="0"? - Are there accessibility benefits to the button approach that we're missing?
- Should we consider updating our guidelines to prefer
tabindex="0"for non-interactive tooltip triggers? - How does this align with modern accessibility best practices?
Related Resources
- Original MR: gitlab-org/gitlab!186486 (merged)
- Related accessibility issue: https://gitlab.com/gitlab-org/gitlab/-/issues/511871
- Heydon Pickering's article on Tooltips & Toggletips
- Related component:
app/assets/javascripts/vue_shared/components/badges/hover_badge.vue
Next Steps
If we decide to change the pattern:
- Update Pajamas guidelines
- Create a migration MR to update existing implementations
- Communicate changes via #frontend, #accessibility channels and Engineering FYI
- Consider implementing this pattern directly in the design system for
GlBadge
Stakeholders
/cc @gitlab-org/working-group/accessibility @gitlab-org/foundations/design-system/engineering
This issue was created following the discussion in gitlab-org/gitlab!186486 (comment 2823158382)