Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add support for responsive y-axis width #5880

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

Open
wants to merge 14 commits into
base: 3.x
Choose a base branch
Loading
from

Conversation

saurabhraj123
Copy link

@saurabhraj123 saurabhraj123 commented May 29, 2025

Summary

A fixed width of 60px is given to the y-axis by default. If the label size increases, it overflows. Added a prop named isWidthResponsive, which dynamically calculates the yAxis width based on the width of the ticks.

Refer to this issue: #5861

Description

I have added a new prop named isWidthResponsive. When this is made true, it dynamically calculates the width of the y-axis when:

  • The label prop is either a string/number or an object.
  • If the label prop is a function or a react element, default width of 60px is used as the old flow.

The following logic is used to achieve the same:

  • Calculate width of each y-axis label and find out the maximum width.
  • If valid label prop is present, it calculates its width as well along with tickWidth and tickMargin.
  • Now the final calculated width = maxWidth + tickWidth + tickMargin + 5px. A 5px gap is for gap between the tick and the y-axis label.

This PR rotates the y-axis label to 270 degrees by default as its the most commonly used layout.

Related Issue

#5861 #2027

Motivation and Context

This feature is long awaited and being asked for since 2017 - Refer #947. When I worked on it, I had to do a lot of customisations to achieve this but I feel this feature should be present by default.

How Has This Been Tested?

I have done manual testing by examining different charts in the storybook. Also, the automated test cases are used.

Screenshots (if appropriate):

Before:

Screenshot 2025-05-29 at 11 54 04 PM

After:
Screenshot 2025-05-29 at 11 55 12 PM

Without labels:
Screenshot 2025-05-29 at 11 56 34 PM

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 extended an existing story to show my changes

@ckifer
Copy link
Member

ckifer commented May 30, 2025

Can you add some unit tests

@PavelVanecek
Copy link
Collaborator

Before looking into code, is it possible to have the API as width="auto"? If we add a new prop then we have to define what happens when people pass in both width and isWidthResponsive. Discoverability suffers.

Copy link
Contributor

@Copilot Copilot AI left a 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 adds support for a responsive y-axis width by dynamically calculating the required width based on label and tick dimensions. Key changes include the addition of new utility functions in YAxisUtils.tsx, an update action in cartesianAxisSlice.ts, and corresponding adjustments in the Text, Label, YAxis, and CartesianAxis components to handle responsive labeling.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/util/YAxisUtils.tsx New helper functions to modify label props and calculate y-axis width.
src/state/cartesianAxisSlice.ts Added updateYAxisWidth action to update state with new width values.
src/component/Text.tsx Refactored Text component to use forwardRef for better ref handling.
src/component/Label.tsx Enhanced Label component with labelRef support for width calculation.
src/cartesian/YAxis.tsx Integrated isWidthResponsive prop and responsive width calculation.
src/cartesian/CartesianAxis.tsx Updated ref handling to collect tick refs used for width measurement.

src/util/YAxisUtils.tsx Outdated Show resolved Hide resolved
Copy link
Collaborator

@PavelVanecek PavelVanecek left a comment

Choose a reason for hiding this comment

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

Okay the "after" variant looks much better. Let's have that as a new breaking change in 3.x @ckifer?

@saurabhraj123 thank you for the PR. Would you mind to fix the conflicts? Then we can have a look at what the CI build looks like and what is the visual diff.

src/cartesian/CartesianAxis.tsx Outdated Show resolved Hide resolved
src/cartesian/CartesianAxis.tsx Outdated Show resolved Hide resolved
src/util/YAxisUtils.tsx Outdated Show resolved Hide resolved
@saurabhraj123
Copy link
Author

Before looking into code, is it possible to have the API as width="auto"? If we add a new prop then we have to define what happens when people pass in both width and isWidthResponsive. Discoverability suffers.

You're right. The width="auto" property makes more sense. I will use that.

@saurabhraj123
Copy link
Author

Can you add some unit tests

I will work on it @ckifer.

@PavelVanecek
Copy link
Collaborator

Run npm run test-build-output -- --update to get new bundle file snapshots, that will fix the build

@PavelVanecek
Copy link
Collaborator

Also, the YAxis label can be defined two different ways, 1. with label prop or 2. with <YAxis><Label /> child component, do your changes work with both?

@saurabhraj123 saurabhraj123 marked this pull request as draft May 30, 2025 15:27
@saurabhraj123 saurabhraj123 marked this pull request as ready for review May 30, 2025 15:28
@saurabhraj123
Copy link
Author

Run npm run test-build-output -- --update to get new bundle file snapshots, that will fix the build

The command runs successfully in local but produces no change. Do I need to do something else?

@ckifer
Copy link
Member

ckifer commented May 30, 2025

If it's not working you can also add to the snapshots manually if you look at the failing build

src/cartesian/CartesianAxis.tsx Outdated Show resolved Hide resolved
src/util/YAxisUtils.tsx Outdated Show resolved Hide resolved
src/component/Text.tsx Show resolved Hide resolved
@PavelVanecek
Copy link
Collaborator

PavelVanecek commented May 31, 2025

Run npm run test-build-output -- --update to get new bundle file snapshots, that will fix the build

The command runs successfully in local but produces no change. Do I need to do something else?

Ah sorry I forgot. First npm run build that will generate the bundles, then npm run test-build-output -- --update that will update the bundle snapshot. Then you can run npm run build again to verify that it worked, commit and push.

Copy link

codecov bot commented Jun 2, 2025

Codecov Report

Attention: Patch coverage is 74.30168% with 46 lines in your changes missing coverage. Please review.

Project coverage is 95.38%. Comparing base (3d2b625) to head (19fd24f).
Report is 16 commits behind head on 3.x.

Files with missing lines Patch % Lines
src/util/YAxisUtils.tsx 3.33% 29 Missing ⚠️
src/state/cartesianAxisSlice.ts 27.27% 8 Missing ⚠️
src/cartesian/YAxis.tsx 79.31% 6 Missing ⚠️
src/component/Text.tsx 96.05% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              3.x    #5880      +/-   ##
==========================================
- Coverage   95.54%   95.38%   -0.16%     
==========================================
  Files         184      187       +3     
  Lines       18776    19076     +300     
  Branches     3790     3831      +41     
==========================================
+ Hits        17939    18196     +257     
- Misses        831      874      +43     
  Partials        6        6              

☔ 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.

Label width calculation will be handled in another PR
@saurabhraj123
Copy link
Author

Can you add some unit tests

I am done with all other changes and was trying to add some test cases but I don't know why, but the render method is not rendering the y-axis properly when width='auto' is passed. It gives null when I try to get it using querySelector.

This is the test code I am using:

 it('should render y-axis with dynamically calculated width', async () => {
    const ticks = [0, 400, 1200, 1600];

    const { container } = render(
      <BarChart width={100} height={100}>
        <YAxis width="auto" ticks={ticks} />
        <CartesianGrid />
      </BarChart>,
    );

    const yAxis = container.querySelector('.yAxis');
    const yAxisWidth = yAxis.getBoundingClientRect().width;
    const yAxisLine = yAxis.querySelector('line');

    expect(yAxis).toBeVisible();
    expect(yAxisLine).toHaveAttribute('width', String(Math.round(yAxisWidth)));
  });

@ckifer
Copy link
Member

ckifer commented Jun 2, 2025

You're going to need to mock getBoundingClientRect. We should have a utility to do that somewhere

Copy link

codecov bot commented Jun 2, 2025

Bundle Report

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

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 963.75kB 17.33kB (1.83%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
state/selectors/axisSelectors.js 257 bytes 56.05kB 0.46%
component/Label.js 112 bytes 16.23kB 0.7%
cartesian/CartesianAxis.js 178 bytes 13.6kB 1.33%
chart/generateCategoricalChart.js -2.05kB 9.96kB -17.04%
component/Text.js 79 bytes 9.4kB 0.85%
cartesian/ReferenceLine.js 64 bytes 8.55kB 0.75%
cartesian/YAxis.js 1.37kB 8.15kB 20.25% ⚠️
chart/RechartsWrapper.js 869 bytes 8.07kB 12.07% ⚠️
chart/CartesianChart.js (New) 7.7kB 7.7kB 100.0% 🚀
cartesian/ReferenceArea.js -4 bytes 6.96kB -0.06%
cartesian/ReferenceDot.js -4 bytes 6.36kB -0.06%
context/chartLayoutContext.js -1.59kB 5.08kB -23.79%
state/selectors/selectChartOffset.js 143 bytes 4.2kB 3.52%
container/RootSurface.js (New) 4.07kB 4.07kB 100.0% 🚀
state/cartesianAxisSlice.js 1.65kB 3.71kB 79.56% ⚠️
context/chartDataContext.js 311 bytes 3.08kB 11.24% ⚠️
container/Surface.js 96 bytes 2.71kB 3.67%
util/Constants.js 93 bytes 2.63kB 3.66%
container/ClipPathProvider.js (New) 2.26kB 2.26kB 100.0% 🚀
util/YAxisUtils.js (New) 2.15kB 2.15kB 100.0% 🚀
chart/LineChart.js 917 bytes 1.37kB 201.98% ⚠️
container/ClipPath.js (Deleted) -1.34kB 0 bytes -100.0% 🗑️

@saurabhraj123
Copy link
Author

getBoundingClientRect

But YAxis itself is not being rendered when width="auto" is passed. I wanted to get the width of the axis that is being rendered and then use the util function get the width and compare them. In my current code, I get yAxis = null.

I also used debug. I found that YAxis doesn't even exist in the DOM.

Am I missing something or is it some limitation of the testing library?

@PavelVanecek
Copy link
Collaborator

Do you have any insight as of why is it not being rendered? If you add console.log({updatedYAxisWidth}) what do you see? If you place a debugger what do you see?

We have tests that show that YAxis does in fact render, for example in test/cartesian/YAxis.spec.tsx, so the testing library can do that.

Coltin was recommending to use mockGetBoundingClientRect({ width: 80, height: 30 });, have you tried that? Look at test/component/Legend.spec.tsx for example. jsdom by default returns all zeroes from getBoundingClientRect() (because it doesn't layout) so we have to mock the results in jsdom environment.

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.

3 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.