Skip to content

feat(Sankey): support accessibilityLayer, title and desc props#7546

Merged
PavelVanecek merged 1 commit into
recharts:mainfrom
MahinAnowar:fix/sankey-accessibility-layer
Jul 12, 2026
Merged

feat(Sankey): support accessibilityLayer, title and desc props#7546
PavelVanecek merged 1 commit into
recharts:mainfrom
MahinAnowar:fix/sankey-accessibility-layer

Conversation

@MahinAnowar

@MahinAnowar MahinAnowar commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Description

Sankey currently rejects the accessibilityLayer, title and desc props at the type level, and even at runtime title/desc get stripped by svgPropertiesNoEvents before they reach Surface, so there's no way to give the chart an accessible name or description.

This adds the three props to SankeyProps and handles them locally in SankeyImpl: title/desc are passed explicitly to the existing Surface (which already knows how to render them), and role/tabIndex default to application/0 when accessibilityLayer is on (the default, same as every other chart), while explicit role/tabIndex props still win. Same precedence logic as MainChartSurface.

I deliberately did not move Sankey onto RootSurface — that was the approach in #7153 and the concern there was that it drags in ZIndex portal support as a side effect. No changes to Surface either. Keyboard navigation wiring for Sankey nodes/links is out of scope here; this covers the props and the SVG attributes.

Related Issue

Fixes #7151

Motivation and Context

Users migrating from 2.x lost the ability to set accessibilityLayer/title/desc on Sankey (TS errors, and silently dropped at runtime). Every other chart supports them.

How Has This Been Tested?

Added an accessibility describe block to test/chart/Sankey.spec.tsx: default role/tabindex, accessibilityLayer={false} omitting them, explicit role/tabIndex overriding the defaults, and title/desc rendering. The default-attributes and title/desc tests fail on current main and pass with this change; the full Sankey spec (33 tests), AccessibilityLayer.spec.tsx and Sankey.typed.spec.tsx all pass locally, plus tsc and eslint on the changed files.

Screenshots (if appropriate):

n/a — attribute-only change, no visual difference.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • I have added a storybook story or VR test, or extended an existing story or VR test to show my changes

Summary by CodeRabbit

  • New Features
    • Added accessibility support to Sankey charts by default.
    • Charts now include appropriate keyboard navigation and application semantics.
    • Added support for custom titles and descriptions for screen readers.
    • Added options to disable the accessibility layer or override accessibility attributes.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Sankey now supports accessibility-layer configuration, SVG titles and descriptions, and default role/tabIndex behavior. Tests cover defaults, disabling the layer, explicit attribute overrides, and rendered descriptive elements.

Changes

Sankey accessibility

Layer / File(s) Summary
Accessibility props and defaults
src/chart/Sankey.tsx
SankeyProps adds accessibilityLayer, title, and desc; the default accessibility layer is enabled.
Accessibility rendering and validation
src/chart/Sankey.tsx, test/chart/Sankey.spec.tsx
SankeyImpl derives role and tabIndex values, passes accessibility content to Surface, and tests default, disabled, overridden, title, and description behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: ckifer

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The change adds accessibilityLayer and title support for Sankey and renders the SVG title as requested by #7151.
Out of Scope Changes check ✅ Passed The PR stays focused on Sankey accessibility props and tests, with no obvious unrelated code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title is concise and accurately summarizes the Sankey accessibility props change.
Description check ✅ Passed The description follows the template and includes the required sections, issue link, testing, and checklist.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/chart/Sankey.tsx (1)

860-861: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add JSDoc for title and desc.

accessibilityLayer documents its default, but title/desc have no descriptions. Since API docs are auto-generated from these JSDoc comments, the props will render undocumented.

📝 Suggested docs
-  title?: string;
-  desc?: string;
+  /**
+   * Text rendered inside the SVG `<title>` element, announced by screen readers.
+   */
+  title?: string;
+  /**
+   * Text rendered inside the SVG `<desc>` element, announced by screen readers.
+   */
+  desc?: string;

As per coding guidelines: "Update TypeScript interfaces and JSDoc comments in source code to automatically update API documentation".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/chart/Sankey.tsx` around lines 860 - 861, Add JSDoc comments describing
the `title` and `desc` properties in the relevant TypeScript interface near
`accessibilityLayer`, so generated API documentation includes both props. Keep
the descriptions focused on their accessibility purpose and preserve the
existing property types.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/chart/Sankey.spec.tsx`:
- Around line 75-114: Update each accessibility test in the Sankey describe
block to call act(() => vi.runOnlyPendingTimers()) immediately after its
render(...) call, ensuring the queued ReportChartSize update completes before
querying or asserting on the SVG and title/description elements.

---

Nitpick comments:
In `@src/chart/Sankey.tsx`:
- Around line 860-861: Add JSDoc comments describing the `title` and `desc`
properties in the relevant TypeScript interface near `accessibilityLayer`, so
generated API documentation includes both props. Keep the descriptions focused
on their accessibility purpose and preserve the existing property types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0d05ffde-5db6-4bfa-ae74-cebce4ef40ea

📥 Commits

Reviewing files that changed from the base of the PR and between 97e0c77 and 94531d8.

📒 Files selected for processing (2)
  • src/chart/Sankey.tsx
  • test/chart/Sankey.spec.tsx

Comment on lines +75 to +114
describe('accessibility', () => {
it('should add tabindex and role to the svg element by default', () => {
const { container } = render(<Sankey width={1000} height={500} data={exampleSankeyData} />);

const svg = container.querySelector('svg');
assertNotNull(svg);
expect(svg).toHaveAttribute('role', 'application');
expect(svg).toHaveAttribute('tabindex', '0');
});

it('should not add tabindex and role to the svg element when accessibilityLayer=false', () => {
const { container } = render(
<Sankey width={1000} height={500} data={exampleSankeyData} accessibilityLayer={false} />,
);

const svg = container.querySelector('svg');
assertNotNull(svg);
expect(svg).not.toHaveAttribute('role');
expect(svg).not.toHaveAttribute('tabindex');
});

it('should prefer explicit role and tabIndex over the accessibilityLayer defaults', () => {
const { container } = render(
<Sankey width={1000} height={500} data={exampleSankeyData} role="img" tabIndex={-1} />,
);

const svg = container.querySelector('svg');
assertNotNull(svg);
expect(svg).toHaveAttribute('role', 'img');
expect(svg).toHaveAttribute('tabindex', '-1');
});

it('should set title and description correctly', () => {
const { container } = render(
<Sankey width={1000} height={500} data={exampleSankeyData} title="Sankey title" desc="Sankey description" />,
);

expect(container.querySelector('title')).toHaveTextContent('Sankey title');
expect(container.querySelector('desc')).toHaveTextContent('Sankey description');
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== test/chart/Sankey.spec.tsx ==\n'
wc -l test/chart/Sankey.spec.tsx
sed -n '1,220p' test/chart/Sankey.spec.tsx

printf '\n== Sankey implementation candidates ==\n'
git ls-files | rg '(^|/)(Sankey|ReportChartSize|useChartWidth|useChartHeight|ChartSize)' || true

printf '\n== vitest setup ==\n'
wc -l vitest.setup.ts
sed -n '1,240p' vitest.setup.ts

Repository: recharts/recharts

Length of output: 11165


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== locate vitest setup ==\n'
git ls-files | rg 'vitest.*setup|setup.*vitest|test/setup|test/.*setup' || true

printf '\n== Sankey implementation outline ==\n'
ast-grep outline src/chart/Sankey.tsx --view expanded || true

printf '\n== chart layout context outline ==\n'
ast-grep outline src/context/chartLayoutContext.tsx --view expanded || true

printf '\n== search for timer advancement patterns in Sankey-related tests ==\n'
rg -n "runOnlyPendingTimers|useFakeTimers|createSelectorTestCase|render\\(<Sankey|render\\(" test/chart/Sankey.spec.tsx test test-vr -g '*Sankey*' -g '*.spec.tsx' -g '*.spec.ts' || true

Repository: recharts/recharts

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== test/vitest.setup.ts ==\n'
sed -n '1,220p' test/vitest.setup.ts

printf '\n== Sankey implementation (relevant slices) ==\n'
sed -n '1220,1425p' src/chart/Sankey.tsx

printf '\n== chart layout context (ReportChartSize) ==\n'
sed -n '200,280p' src/context/chartLayoutContext.tsx

Repository: recharts/recharts

Length of output: 10597


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== search for setChartSize and autobatch markers ==\n'
rg -n "setChartSize|prepareAutoBatched|SHOULD_AUTOBATCH|autoBatch|requestAnimationFrame" src test -g '*.ts' -g '*.tsx' | sed -n '1,220p'

printf '\n== locate chart size reducer/action file candidates ==\n'
git ls-files src/state src/context | rg 'chart.*(size|layout)|layout|store|slice' || true

Repository: recharts/recharts

Length of output: 7621


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== src/state/layoutSlice.ts ==\n'
sed -n '1,140p' src/state/layoutSlice.ts

printf '\n== src/state/store.ts ==\n'
sed -n '1,180p' src/state/store.ts

printf '\n== any auto-batched chart size tests? ==\n'
rg -n "ReportChartSize|setChartSize\\(|useChartWidth\\(|useChartHeight\\(" test src -g '*.ts' -g '*.tsx' | sed -n '1,220p'

Repository: recharts/recharts

Length of output: 11259


Advance the pending timers after each render(...).
Sankey doesn’t populate useChartWidth/useChartHeight until ReportChartSize flushes through the rAF-batched store update, so these SVG assertions can race the queued size commit. Add act(() => vi.runOnlyPendingTimers()); after each render in this block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/chart/Sankey.spec.tsx` around lines 75 - 114, Update each accessibility
test in the Sankey describe block to call act(() => vi.runOnlyPendingTimers())
immediately after its render(...) call, ensuring the queued ReportChartSize
update completes before querying or asserting on the SVG and title/description
elements.

Source: Path instructions

@PavelVanecek PavelVanecek left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approve but I'm going to treat it as a new feature rather than a bugfix

@PavelVanecek PavelVanecek changed the title fix(Sankey): support accessibilityLayer, title and desc props feat(Sankey): support accessibilityLayer, title and desc props Jul 12, 2026
@PavelVanecek PavelVanecek added the enhancement Enhancement to a current API label Jul 12, 2026
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 1.22kB (0.02%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.45MB 501 bytes (0.03%) ⬆️
recharts/bundle-es6 1.27MB 501 bytes (0.04%) ⬆️
recharts/bundle-umd 586.29kB 213 bytes (0.04%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-es6

Assets Changed:

Asset Name Size Change Total Size Change (%)
chart/Sankey.js 501 bytes 38.49kB 1.32%
view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
chart/Sankey.js 501 bytes 40.3kB 1.26%
view changes for bundle: recharts/bundle-umd

Assets Changed:

Asset Name Size Change Total Size Change (%)
Recharts.js 213 bytes 586.29kB 0.04%

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.18%. Comparing base (38175dd) to head (94531d8).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7546   +/-   ##
=======================================
  Coverage   88.17%   88.18%           
=======================================
  Files         613      613           
  Lines       14246    14254    +8     
  Branches     3579     3585    +6     
=======================================
+ Hits        12562    12570    +8     
  Misses       1494     1494           
  Partials      190      190           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@PavelVanecek
PavelVanecek merged commit 82d2bec into recharts:main Jul 12, 2026
58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Enhancement to a current API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sankey - removed accessibilityLayer?

2 participants