254a7b9971
- Update DataLinksContextMenu API to accept position objects for keyboard events - Add getMenuPosition helper function to calculate position from element - Update WithContextMenu to handle position objects and elements - Simplify pie chart keyboard handler to use position object API - Position calculation logic now in core component (DataLinksContextMenu) - Addresses review feedback about keyboard accessibility and position calculation
4.5 KiB
4.5 KiB
Contribution: Pie Chart Keyboard Focus Indicator Fix
Issue
Issue #114227: Keyboard focus indicator is not visible on data links in Pie Chart visualization
When keyboard users navigate through a Pie Chart panel using the Tab key, data links (clickable links on chart segments) do not show a visible focus indicator. This makes it impossible for keyboard-only users to know which element is currently focused, reducing navigation clarity and accessibility.
Problem Analysis
Root Cause
- Pie chart slices with data links are rendered as SVG
<g>elements - These elements are not naturally keyboard focusable (SVG elements need
tabIndexto be focusable) - No focus event handlers were attached to trigger visual feedback
- No keyboard activation support (Enter/Space keys)
Two Rendering Cases
- Single link case:
DataLinksContextMenuwraps the slice in an<a>tag - Multiple links case:
DataLinksContextMenuprovides anopenMenufunction via render prop
Solution Approach
1. Data Link Detection
- Check for data links using
arc.data.hasLinksandarc.data.getLinks - Determine if slice should be focusable based on presence of links
2. Keyboard Accessibility
- Added
tabIndex={0}for slices with data links (multiple links case) - Added
tabIndex={-1}for slices wrapped in<a>tag (single link case) to prevent double focus - Added
role="link"andaria-labelfor proper screen reader support
3. Focus Indicator
- Leveraged Grafana's existing
DataHoverEventsystem for highlighting - On focus, publish
DataHoverEventto trigger the same visual highlight as mouse hover - On blur, publish
DataHoverClearEventto clear the highlight - Used a small delay on blur to prevent flickering during focus transitions
4. Keyboard Activation
- Added
handleKeyDownto handle Enter key presses - For multiple links: Create synthetic mouse event and call
openMenudirectly - For single link: Dispatch native click event to trigger the
<a>tag's default behavior
5. Single Link Case Handling
- Detected when slice is wrapped in
<a>tag (whenopenMenuis undefined) - Attached focus/blur event listeners to the parent
<a>tag - Ensured inner
<g>element hastabIndex={-1}to prevent tab order conflicts - Ensured
<a>tag is properly focusable (remove anytabIndex="-1"if present)
6. Tab Order Optimization
- Sorted slices with data links first in the DOM to ensure proper tab order
- This ensures keyboard users reach interactive elements before non-interactive ones
Implementation Details
Key Changes in PieChart.tsx
-
Imports: Added
useRefanduseEffectfrom React -
SliceProps Interface: Added
outerRadiusandinnerRadiusprops to calculate click coordinates -
PieSlice Component:
- Added
elementRefandblurTimeoutReffor DOM manipulation and blur handling - Detected data links:
hasDataLinksDirectandhasDataLinks - Determined focusability:
shouldBeFocusable(true only for multiple links case) - Added
useEffecthook to handle single link case (<a>tag focus/blur) - Added
handleFocuscallback to publishDataHoverEventon focus - Added
handleBlurcallback to publishDataHoverClearEventon blur (with delay) - Added
handleKeyDowncallback to handle Enter key activation - Updated
<g>element with accessibility attributes:tabIndex={shouldBeFocusable ? 0 : -1}role={shouldBeFocusable ? 'link' : undefined}aria-label={shouldBeFocusable ? ... : undefined}onKeyDown={shouldBeFocusable ? handleKeyDown : undefined}onFocus={hasDataLinks ? handleFocus : undefined}onBlur={hasDataLinks ? handleBlur : undefined}style={{ outline: 'none' }}to remove browser default outline
- Added
-
PieChart Component:
- Added sorting to
pie.arcs.mapto put slices with data links first - Passed
outerRadiusandinnerRadiustoPieSlicecomponents
- Added sorting to
Testing
Expected Behavior
- Tab navigation reaches slices with data links
- Focused slice shows visual highlight (scales up, others fade)
- Enter key activates the data link menu
- Tab order is logical (data link slices appear before non-link slices)
Files Modified
public/app/plugins/panel/piechart/PieChart.tsx