Repository navigation
refactor: size charts from the card width before they mount (part 1/2) - #103684
luacmartins merged 9 commits into
Conversation
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
…-card-width # Conflicts: # src/components/Charts/BarChart/VerticalBarChartContent.tsx
|
@codex review |
|
@MelvinBot review |
|
@MelvinBot find regressions |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Code reviewThe approach looks correct. I found one change you need to make before merging and one optional suggestion. I didn't find any logic bugs. Must fix: knip fails because of this PR. Suggestion: the drift probe copies the chart config instead of sharing it.
What I verified
|
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Regression checkI found no confirmed functional regressions in the code. I found two low-severity behavior changes, both from reading the code. The web test came back blank, but the evidence points to the test environment, not this PR. 1. A spinner flashes when a chart mounts or switches type. 2. The pie chart now loses its state when its container width goes to 0. On main, the pie never waited for a width, so Candidates I ruled out
🤖 Web test steps verification results: ❌ fail The Spend over time line chart rendered correctly on first load, filling the card with its labels visible. After that, every chart view stayed blank, and so did Table view, even though the footer showed all 4 expenses ($260.75). This PR doesn't touch Table view, so the blank screens most likely come from the headless browser, not this PR. I didn't run a baseline on
|
|
Replying to this comment. Both fixed in |
|
Replying to this comment. Item 2 is fixed in |
|
@carlosmiceli Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
@dylanexpensify should this have gotten a C+ assigned to review first? |
Yeah it should've! Product is assigned to review a different scope, but agree for engineering reviews a C+ should happen first! |
dylanexpensify
left a comment
There was a problem hiding this comment.
refactor: product input not required
| return null; | ||
| } | ||
|
|
||
| if (!readyCanvas) { |
There was a problem hiding this comment.
Should we show the spinner only when isLoading is true?
There was a problem hiding this comment.
Right now the spinner shows while any of three things is missing: the data (isLoading), the chart's fonts, or the card's width. The fonts need to stay, since the chart can't draw without them and they finish loading only after it mounts. Main already shows the spinner while they load, and showing it only on isLoading would leave a blank card there instead.
You're right about the width though, good catch and thanks for pointing it out. That check is new in this PR, and it's the temporary loading state the description flags. Part 2 of this feature will handle it, so a chart that's only waiting for its card's width won't flash the spinner.
| chartBottom, | ||
| }); | ||
|
|
||
| const handleChartBoundsChange = (bounds: ChartBounds) => { |
There was a problem hiding this comment.
We already compute barLayout above from the predicted plot bounds:
const plotBounds = getCartesianPlotBounds(chartWidth, chartPaddingRight);
const barLayout = getBarLayout(plotBounds.width, data.length);
Should we reuse it here instead of recomputing it from the bounds victory-native reports?
There was a problem hiding this comment.
Good catch, thanks! Two sources for the same layout was a smell. Fixed in f63475a.
Reviewer Checklist
Screenshots/VideosMacOS: Chrome / SafariScreen.Recording.2026-10-14.at.22.56.34.mov |
|
@sharabai could you please also resolve conflict? |
|
@daledah thanks for the review! I fixed the code smell you pointed out. You're right about the spinner. It stays visible until the card is measured, even when the data has already loaded. #103210 replaces that loading state, and the two PRs are one feature split into two for review, so this will only be an issue between the two merges. I'd rather leave it for part 2 than fix it twice. Over to you! |
|
@sharabai conflicts |
|
@luacmartins conflicts are resolved. |
|
@cristipaval @luacmartins conflicts are resolved and checks are green, ready to merge whenever you are. |
|
🚧 luacmartins has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/luacmartins in version: 9.5.10-0 🚀
|
|
No help site update needed. This PR changes how the Insights charts measure their size before drawing, so no feature, label, or documented step changes for users. |
|
🚀 Deployed to staging by https://github.com/luacmartins in version: 9.5.12-0 🚀
|
|
No help site update needed. This PR only changes how the Insights charts measure their size before drawing, so no feature, label, or documented step changes for users. This matches my earlier review; the PR hasn't changed since. |
|
🚀 Deployed to production by https://github.com/cristipaval in version: 9.5.12-1 🚀
Bundle Size Analysis (Sentry): |






Explanation of Change
Part 1 of 2 of the chart spinner fade-in. Part 2, #103210, builds its fade-in on the sizing here.
Each chart entry point (
BarChart,LineChart,PieChart, web and native) wraps its chart inChartWidthBox, which measures the card aboveSkiaWebChart's lazy boundary. The chart bodies pass that width to victory-native asexplicitSizeinstead of measuring themselves withonLayout, and the line and vertical bar charts compute their plot bounds withgetCartesianPlotBoundsinstead of re-rendering fromonChartBoundsChange, so a chart draws its final layout in the render it mounts in.plotBoundsDrift.test.tschecks that prediction against victory-native's own bounds, rendering with the sameCARTESIAN_Y_AXISthe charts use.ChartWidthBoxand theexplicitSizehandoff are ported from #100610.Important
On native, a chart that remounts with its data already loaded shows the spinner until its card has been measured. On main that pass showed an empty box, or the pie chart's legend without its ring. #103210 replaces this loading state.
Fixed Issues
$ #103964
PROPOSAL:
Follow-up to #99560
Tests
Preconditions:
Both tests are regression coverage.
1. Charts fill the card and follow the window width (Account A, web)
2. Native (Account A, iOS or Android)
Offline tests
N/A: this change only affects how a chart is sized. It makes no requests and writes no Onyx data.
QA Steps
Same as tests.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
pr-103684-test-2-native.mp4
iOS: mWeb Safari
MacOS: Chrome / Safari
pr-103684-test-1-charts-fill-card-follow-window-width.mp4