Skip to content

Refactor Shape props to reduce bundle sizes#7349

Merged
PavelVanecek merged 3 commits into
mainfrom
shape-props
May 21, 2026
Merged

Refactor Shape props to reduce bundle sizes#7349
PavelVanecek merged 3 commits into
mainfrom
shape-props

Conversation

@PavelVanecek

@PavelVanecek PavelVanecek commented May 20, 2026

Copy link
Copy Markdown
Collaborator

Description

The Shape component had an unfortunate design where it accepted a string enum and resolved that into individual components. This works but it forces the Shape to import all components in compile time so that it is ready to resolve them at runtime, which forces all of them into each consumer bundle. Now, most consumers of Shape don't actually use all of the shapes, they only use one hardcoded one so we inflate the bundle sizes for no reason.

So I swapped it from string enum into actually accepting the component as a prop, and added that component as default and that reduces the bundle sizes because now we don't import everything. You can see this effect in the treeshaking bundle snapshot.

Why now? Because I am adding more default shapes in the animation PR so this effect would be even more pronounced, so let's get it done now.

Shape is not exported so it's a private component and so I consider this a backwards compatible change.

Bundle size measurements

Measured with scripts/treeshaking.ts on the previous HEAD versus this branch (tree-shaken / min+gzip):

Component Before After Delta Before gzip After gzip Delta gzip
Bar 308.72 KB 288.03 KB -20.69 KB 30.12 KB 27.61 KB -2.51 KB
BarStack 312.40 KB 291.72 KB -20.68 KB 30.47 KB 27.96 KB -2.51 KB
Funnel 266.92 KB 243.50 KB -23.42 KB 26.49 KB 23.85 KB -2.64 KB
Line 292.08 KB 271.77 KB -20.31 KB 28.44 KB 25.67 KB -2.77 KB
Pie 282.73 KB 268.92 KB -13.81 KB 28.00 KB 26.06 KB -1.94 KB
RadialBar 292.61 KB 271.21 KB -21.40 KB 28.86 KB 26.27 KB -2.59 KB
Scatter 287.81 KB 269.78 KB -18.03 KB 28.14 KB 25.76 KB -2.38 KB

Motivation and Context

Smaller bundle size

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)
  • Bundle size reduction

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

  • Refactor

    • Refactored internal shape rendering system across all chart types (Bar, Funnel, Line, Pie, RadialBar, Scatter) to use explicit default shape definitions instead of shape type strings.
    • Updated shape component integration to improve consistency in how custom and default shapes are applied throughout the charting library.
  • Tests

    • Updated test expectations to reflect changes in shape payload data structure.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eb334e24-610d-4340-bb30-0502346f0f7c

📥 Commits

Reviewing files that changed from the base of the PR and between 403b826 and b6d98b2.

📒 Files selected for processing (23)
  • scripts/treeshaking-groups/Bar.ts
  • scripts/treeshaking-groups/BarStack.ts
  • scripts/treeshaking-groups/Funnel.ts
  • scripts/treeshaking-groups/Line.ts
  • scripts/treeshaking-groups/Pie.ts
  • scripts/treeshaking-groups/RadialBar.ts
  • scripts/treeshaking-groups/Scatter.ts
  • src/cartesian/Bar.tsx
  • src/cartesian/Funnel.tsx
  • src/cartesian/Line.tsx
  • src/cartesian/Scatter.tsx
  • src/polar/Pie.tsx
  • src/polar/RadialBar.tsx
  • src/util/ActiveShapeUtils.tsx
  • src/util/BarUtils.tsx
  • src/util/FunnelUtils.tsx
  • src/util/RadialBarUtils.tsx
  • src/util/ScatterUtils.tsx
  • src/util/types.ts
  • test/component/Legend.itemSorter.spec.tsx
  • test/component/Legend.spec.tsx
  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/polar/Pie/Pie.spec.tsx
💤 Files with no reviewable changes (8)
  • scripts/treeshaking-groups/Bar.ts
  • scripts/treeshaking-groups/Pie.ts
  • scripts/treeshaking-groups/Scatter.ts
  • scripts/treeshaking-groups/RadialBar.ts
  • test/polar/Pie/Pie.spec.tsx
  • scripts/treeshaking-groups/BarStack.ts
  • scripts/treeshaking-groups/Line.ts
  • scripts/treeshaking-groups/Funnel.ts

Walkthrough

This PR refactors Recharts' shape rendering system from shapeType-based string dispatch to a first-class renderDefaultShape architecture. It introduces explicit default shape constants for all chart components, tightens shape prop contracts to required where defaults are now guaranteed, and broadens the ActiveShape type union to enable more flexible shape customization.

Changes

Shape Rendering Architecture

Layer / File(s) Summary
Core Shape component and type refactor
src/util/ActiveShapeUtils.tsx, src/util/types.ts
The Shape component's rendering logic is rewritten to accept a required renderDefaultShape renderer. The component uses type guards to route options (React elements, functions, plain objects) to appropriate render paths. The ActiveShape type union is broadened to support elements with partial props, functions with optional index parameters returning ReactNode, and plain object prop overrides.
Bar shape default and internal prop wiring
src/util/BarUtils.tsx, src/cartesian/Bar.tsx
defaultBarShape is exported as Rectangle and wired into BarRectangle via renderDefaultShape. The Bar component makes shape required across internal rendering components by importing and using defaultBarShape, updating defaultBarProps to include the default, and refactoring hasCustomShape logic to distinguish default from custom shapes.
Line curve default and shape rendering
src/cartesian/Line.tsx
Curve is imported and defaultLineShape is created. The internal shape prop is tightened to required. StaticCurve is updated to use Shape with renderDefaultShape={defaultLineShape} instead of shapeType="curve". The default is exported in defaultLineProps.
Scatter symbols and custom shape type alignment
src/util/ScatterUtils.tsx, src/cartesian/Scatter.tsx
ScatterSymbol now uses a local renderSymbols helper and passes renderDefaultShape={renderSymbols} into Shape. The option prop type changes to ActiveShape<ScatterShapeProps & InnerSymbolsProp, SVGPathElement> | SymbolType. The exported ScatterCustomizedShape type updates to include InnerSymbolsProp in the shape props rather than the element type.
Funnel trapezoid shape default and rendering
src/util/FunnelUtils.tsx, src/cartesian/Funnel.tsx
defaultFunnelShape is exported as Trapezoid and wired into FunnelTrapezoid via renderDefaultShape. FunnelTrapezoidProps is updated to accept a narrowed shape union. Funnel.tsx imports the default and adds it to defaultFunnelProps.
Pie sector shape type and rendering overhaul
src/polar/Pie.tsx
Sector import and defaultPieSectorShape constant are introduced. The exported PieShape type is narrowed to ActiveShape<PieSectorShapeProps, SVGPathElement>. Sector rendering is refactored: Shape now receives renderDefaultShape={defaultPieSectorShape}, option={sectorOptions ?? shape}, explicit index and isActive, replacing the previous shapeType="sector" and inline option selection.
RadialBar sector shape default and active shape logic
src/util/RadialBarUtils.tsx, src/polar/RadialBar.tsx
defaultRadialBarShape is exported as Sector and wired into RadialBarSector via renderDefaultShape. Active shape option selection is refactored to use activeShape only when non-null, falling back to shape. The default is added to defaultRadialBarProps.
Bundle composition and treeshaking expectations
scripts/treeshaking-groups/*.ts
expectedInBundle arrays are updated across all chart treeshaking files to remove Curve, Rectangle, Sector, Symbols, and Trapezoid where they are no longer exposed in bundle composition, reflecting the internal-only nature of default shapes.
Test payload expectations and type error removal
test/component/Legend*.spec.tsx, test/component/Tooltip/*.spec.tsx, test/polar/Pie/*.spec.tsx
Test expectations are updated to include shape: Curve in legend item payloads for line charts. Imports are consolidated to use the main barrel export. A @ts-expect-error comment is removed from the Pie test, indicating improved type compatibility.

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • recharts/recharts#6738: Directly related refactor of Shape/ShapeProps in ActiveShapeUtils.tsx removing the propTransformer API in tandem with the shapeType-to-renderDefaultShape transition.
  • recharts/recharts#6482: Overlapping changes to src/polar/Pie.tsx sector shape handling, including PieShape type and active/inactive sector rendering logic.
  • recharts/recharts#7067: Related changes to src/cartesian/Bar.tsx filtering behavior around bar shape handling in computeBarRectangles.

Suggested Labels

enhancement

Suggested Reviewers

  • ckifer
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refactor Shape props to reduce bundle sizes' clearly and specifically summarizes the main change: refactoring the Shape component's prop design to achieve bundle size reductions.
Description check ✅ Passed The description covers key required sections: a clear explanation of the problem and solution, motivation (bundle size reduction), and types of changes are indicated. Bundle size measurements are provided showing the impact.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch shape-props

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 and usage tips.

@chromatic-com

chromatic-com Bot commented May 20, 2026

Copy link
Copy Markdown

Tip

All tests passed and all changes approved!

🟢 UI Tests: 193 tests unchanged
🟢 UI Review: 193 stories published -- no changes
Storybook icon Storybook Publish: 193 stories published

@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

PavelVanecek and others added 3 commits May 21, 2026 12:12
Move Shape off the shared shapeType switch so each consumer provides its
own default renderer. This keeps the runtime behavior intact while letting
bundles tree-shake unrelated shapes.

Measured with scripts/treeshaking.ts (tree-shaken / min+gzip):
- Bar: 308.72 KB -> 288.03 KB / 30.12 KB -> 27.61 KB
- BarStack: 312.40 KB -> 291.72 KB / 30.47 KB -> 27.96 KB
- Funnel: 266.92 KB -> 243.50 KB / 26.49 KB -> 23.85 KB
- Line: 292.08 KB -> 271.77 KB / 28.44 KB -> 25.67 KB
- Pie: 282.73 KB -> 268.92 KB / 28.00 KB -> 26.06 KB
- RadialBar: 292.61 KB -> 271.21 KB / 28.86 KB -> 26.27 KB
- Scatter: 287.81 KB -> 269.78 KB / 28.14 KB -> 25.76 KB

Co-authored-by: Copilot <[email protected]>
@PavelVanecek PavelVanecek changed the title Shape props Refactor Shape props to reduce bundle sizes May 21, 2026
@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Bundle Report

Changes will decrease total bundle size by 33.87kB (-0.61%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.4MB 451 bytes (0.03%) ⬆️
recharts/bundle-es6 1.23MB 284 bytes (0.02%) ⬆️
recharts/bundle-umd 588.84kB -138 bytes (-0.02%) ⬇️
recharts/bundle-treeshaking-cartesian 693.24kB -8.6kB (-1.23%) ⬇️
recharts/bundle-treeshaking-polar 459.37kB -25.86kB (-5.33%) ⬇️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-es6

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Bar.js 78 bytes 30.38kB 0.26%
cartesian/Line.js 115 bytes 30.15kB 0.38%
polar/Pie.js 148 bytes 28.94kB 0.51%
polar/RadialBar.js 78 bytes 22.39kB 0.35%
cartesian/Funnel.js 49 bytes 20.33kB 0.24%
util/ActiveShapeUtils.js -618 bytes 4.63kB -11.78%
util/ScatterUtils.js 119 bytes 1.73kB 7.39% ⚠️
util/BarUtils.js 101 bytes 1.65kB 6.51% ⚠️
util/RadialBarUtils.js 107 bytes 760 bytes 16.39% ⚠️
util/FunnelUtils.js 107 bytes 603 bytes 21.57% ⚠️
view changes for bundle: recharts/bundle-umd

Assets Changed:

Asset Name Size Change Total Size Change (%)
Recharts.js -138 bytes 588.84kB -0.02%
view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Bar.js 81 bytes 32.13kB 0.25%
cartesian/Line.js 123 bytes 31.77kB 0.39%
polar/Pie.js 156 bytes 30.76kB 0.51%
polar/RadialBar.js 71 bytes 23.84kB 0.3%
cartesian/Funnel.js 42 bytes 21.82kB 0.19%
util/ActiveShapeUtils.js -664 bytes 5.59kB -10.62%
util/BarUtils.js 157 bytes 2.77kB 6.01% ⚠️
util/ScatterUtils.js 128 bytes 2.54kB 5.31% ⚠️
util/RadialBarUtils.js 180 bytes 1.68kB 11.97% ⚠️
util/FunnelUtils.js 177 bytes 1.48kB 13.54% ⚠️
view changes for bundle: recharts/bundle-treeshaking-cartesian

Assets Changed:

Asset Name Size Change Total Size Change (%)
bundle.js -8.6kB 693.24kB -1.23%
view changes for bundle: recharts/bundle-treeshaking-polar

Assets Changed:

Asset Name Size Change Total Size Change (%)
bundle.js -25.86kB 459.37kB -5.33%

@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.04%. Comparing base (403b826) to head (b6d98b2).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7349   +/-   ##
=======================================
  Coverage   89.03%   89.04%           
=======================================
  Files         548      548           
  Lines       40522    40534   +12     
  Branches     5570     5567    -3     
=======================================
+ Hits        36079    36093   +14     
+ Misses       4434     4432    -2     
  Partials        9        9           

☔ View full report in Codecov by Sentry.
📢 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.

@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@PavelVanecek
PavelVanecek marked this pull request as ready for review May 21, 2026 05:46
@PavelVanecek
PavelVanecek merged commit 9a13660 into main May 21, 2026
60 checks passed
@PavelVanecek
PavelVanecek deleted the shape-props branch May 21, 2026 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant