Skip to content

fix: prevent animated line flicker with round/square strokeLinecap#7022

Merged
ckifer merged 4 commits intorecharts:mainfrom
roy7:fix/animated-line-linecap-flicker
Feb 20, 2026
Merged

fix: prevent animated line flicker with round/square strokeLinecap#7022
ckifer merged 4 commits intorecharts:mainfrom
roy7:fix/animated-line-linecap-flicker

Conversation

@roy7
Copy link
Contributor

@roy7 roy7 commented Feb 18, 2026

Summary

  • Fixes a flickering dot artifact at the line endpoint during stroke-dasharray draw animation when using strokeLinecap="round" or "square"
  • Root cause: floating-point imprecision in the SVG renderer's string-to-float roundtrip caused the dasharray pattern cycle to occasionally land a fraction of a pixel short of the path length, starting a phantom repeat dash at the endpoint
  • Fix: use totalLength as the dasharray gap instead of totalLength - curLength, ensuring the cycle always exceeds the path length so no repeat can occur
  • Applied to Line, Rectangle, and Trapezoid components

Fixes #6941

Why this approach

The flickering is caused by the SVG renderer independently parsing the dasharray values from strings back to floats. Even though curLength + (totalLength - curLength) equals exactly totalLength in JavaScript, the SVG renderer's parseFloat("X") + parseFloat("Y") can differ by a ULP, causing the pattern cycle to end a hair before the path endpoint. With strokeLinecap="round", the resulting repeat dash renders a visible dot.

We considered two alternatives:

  • Rounding values (e.g., toFixed(8)): Reduces the probability but doesn't eliminate it, requires choosing a magic number of decimal places, and changes the format of clean integer values
  • Adding epsilon to the gap: Same idea as our fix but with an arbitrary small value instead of a robust one

Using totalLength as the gap makes the cycle curLength + totalLength, which is always strictly greater than the path length (when curLength > 0). This eliminates the entire class of problem with no visual difference — any gap that extends past the end of the path is invisible since there's nothing to render beyond it.

Test plan

  • All 13,958 existing tests pass
  • Lint and type checks pass
  • Visually confirmed fix in Storybook with strokeLinecap="round", strokeWidth={4}, dot={false}
  • Verified with isolated SVG test that the dasharray pattern no longer produces endpoint artifacts

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Stroke animations for lines and shapes now use a consistent total-length trailing gap, preventing floating-point artifacts and ensuring smoother end-state visuals.
  • Documentation

    • Inline docs clarified dash-pattern behavior and guidance to avoid rendering artifacts.
  • Tests

    • Animation tests updated to expect the new, consistent stroke-dasharray semantics across affected shape components.

…echarts#6941)

When animating Line, Rectangle, and Trapezoid draw-on via strokeDasharray,
the gap was set to (totalLength - curLength), making the dash pattern cycle
equal to the path length. Floating-point imprecision in the SVG renderer's
string-to-float roundtrip could cause the cycle to land a hair short of the
path length, starting a phantom repeat dash at the endpoint. With
strokeLinecap="round" or "square", this repeat dash rendered as a visible
flickering dot at the line's final destination during animation.

Fix: use totalLength as the gap instead of (totalLength - curLength). The
cycle is now always longer than the path, so no repeat can occur.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

Walkthrough

Updated stroke-dasharray construction and animation targets: Line.tsx adds helpers to build dash patterns using the path totalLength as trailing gaps; Rectangle and Trapezoid animations now target a trailing gap equal to totalLength. Tests and a single manifest line updated to match the new semantics.

Changes

Cohort / File(s) Summary
Stroke dash helpers & logic
src/cartesian/Line.tsx
Added generateSimpleStrokeDasharray, repeat, and getStrokeDasharray. Dasharray construction now uses totalLength for trailing empty segments, pads repeated patterns to even length, and removed prior restLength logic; code path now selects pattern helpers when a dash pattern is provided.
Shape animation targets
src/shape/Rectangle.tsx, src/shape/Trapezoid.tsx
Changed stroke-dasharray animation end values from a zero/short trailing gap to using the full totalLength as the trailing gap (e.g., from "totalLength px 0px" to "totalLength px totalLength px").
Line animation tests
test/cartesian/Line.animation.spec.tsx
Updated assertions and inline comments to expect dasharray gaps equal to totalLength (e.g., 10px 100px, 100px 100px) across animation progress, completion, and re-render scenarios.
Rectangle animation tests
test/shape/Rectangle.animation.spec.tsx
Adjusted expectations from "1234px 0px" to "1234px 1234px" for initial and final animated stroke-dasharray values.
Manifest
package.json
Single-line update in manifest.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • ckifer
  • PavelVanecek
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main fix: preventing animated line flicker with round/square strokeLinecap, which is the primary objective of the changeset.
Description check ✅ Passed The description comprehensively covers the summary, root cause analysis, implementation approach, alternatives considered, test plan, and linked issue #6941, aligning well with the template requirements.
Linked Issues check ✅ Passed The PR directly addresses issue #6941 by fixing the flickering dot artifact at line endpoints during stroke-dasharray animation with round/square strokeLinecap, as required.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the flickering animation issue across Line, Rectangle, and Trapezoid components, with test updates reflecting the new dasharray semantics.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/cartesian/Line.animation.spec.tsx (1)

237-243: ⚠️ Potential issue | 🟡 Minor

Stale test description after expectation update

Line 237's it(...) description still says "100, 0" but the expectation was updated to "100px 100px" (line 243). Similarly, lines 379 and 387–388 contain comments referencing "0px hidden" that now contradict the updated expectations at lines 382 and 392.

📝 Proposed description and comment updates
-  it('should set the stroke-dasharray to 100, 0 when the animation is completed', async () => {
+  it('should set the stroke-dasharray to 100, 100 when the animation is completed', async () => {
-      // after travelling 100% of the path, the stroke-dasharray should be 100px visible and 0px hidden
+      // after travelling 100% of the path, the stroke-dasharray should be 100px visible and 100px gap (totalLength) to avoid float precision artifacts
-       * After the animation is completed, the stroke-dasharray should remain 100px visible and 0px hidden.
+       * After the animation is completed, the stroke-dasharray should remain 100px visible with a totalLength gap.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/cartesian/Line.animation.spec.tsx` around lines 237 - 243, Update the
stale test description and comments to match the changed expectation values:
change the it(...) description that currently references "100, 0" to reflect
"100px 100px" for the stroke-dasharray check in the test that uses
renderTestCase(), animationManager.setAnimationProgress(1) and getLine(), and
update the nearby comments that mention "0px hidden" to reflect the new expected
values used in the assertions (the lines around the other tests using getLine()
and animationManager). Ensure all human-readable strings and inline comments
match the actual assertions (e.g., "100px 100px" instead of "100, 0" and replace
"0px hidden" with the corresponding updated expectation).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@test/cartesian/Line.animation.spec.tsx`:
- Around line 237-243: Update the stale test description and comments to match
the changed expectation values: change the it(...) description that currently
references "100, 0" to reflect "100px 100px" for the stroke-dasharray check in
the test that uses renderTestCase(), animationManager.setAnimationProgress(1)
and getLine(), and update the nearby comments that mention "0px hidden" to
reflect the new expected values used in the assertions (the lines around the
other tests using getLine() and animationManager). Ensure all human-readable
strings and inline comments match the actual assertions (e.g., "100px 100px"
instead of "100, 0" and replace "0px hidden" with the corresponding updated
expectation).

- Add JSDoc docstrings to generateSimpleStrokeDasharray, repeat, and
  getStrokeDasharray functions (docstring coverage fix)
- Update stale test description "100, 0" → "100, 100"
- Update stale comments referencing "0px hidden" to reflect totalLength gap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (2)
src/cartesian/Line.tsx (2)

433-435: Add explicit return type annotation.

getStrokeDasharray lacks a : string return type. As per coding guidelines, return types should be explicit for non-trivial functions.

-const getStrokeDasharray = (length: number, totalLength: number, lines: number[]) => {
+const getStrokeDasharray = (length: number, totalLength: number, lines: number[]): string => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cartesian/Line.tsx` around lines 433 - 435, The function
getStrokeDasharray (params: length, totalLength, lines) is missing an explicit
string return type; update its signature to declare a return type of : string
(e.g., const getStrokeDasharray = (length: number, totalLength: number, lines:
number[]): string => ...) and ensure the implementation still returns a string
value to satisfy the annotation.

407-416: Missing explicit return type; O(n²) spread is worth addressing for long paths with small dash patterns.

Per coding guidelines, return types should be explicit. Additionally, the spread-inside-loop pattern allocates a new array on every iteration — for a tiny lineLength on a long path count can reach thousands, making this quadratic per animation tick.

♻️ Suggested improvement
-function repeat(lines: number[], count: number) {
+function repeat(lines: number[], count: number): number[] {
   const linesUnit = lines.length % 2 !== 0 ? [...lines, 0] : lines;
-  let result: number[] = [];
-
-  for (let i = 0; i < count; ++i) {
-    result = [...result, ...linesUnit];
-  }
-
-  return result;
+  return Array.from({ length: count }, () => linesUnit).flat();
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cartesian/Line.tsx` around lines 407 - 416, The repeat function lacks an
explicit return type and is O(n²) because it spreads linesUnit into result on
every iteration; add an explicit return type (number[]) to repeat, compute
linesUnit as now (append 0 if odd), then avoid repeated spread by preallocating
or using a single push loop: compute totalLength = linesUnit.length * count and
either create a new Array(totalLength) and fill by indexing with a pointer, or
use a nested for loop that pushes each element of linesUnit into result once per
repetition; ensure you update the named symbols repeat, linesUnit, result,
count, and lines accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/cartesian/Line.animation.spec.tsx`:
- Around line 683-688: Update the stale inline comment that reads "0px hidden"
to "100px hidden" in the Line.animation.spec.tsx test so it matches the
assertion using fullyVisibleLine ('100px 100px'); there are two occurrences of
this stale phrasing (the comment just above the
expect(getLine(container)).toHaveAttribute('stroke-dasharray', '100px 100px')
assertion and the similar comment later in the file), so change both to state
"100px hidden".

---

Nitpick comments:
In `@src/cartesian/Line.tsx`:
- Around line 433-435: The function getStrokeDasharray (params: length,
totalLength, lines) is missing an explicit string return type; update its
signature to declare a return type of : string (e.g., const getStrokeDasharray =
(length: number, totalLength: number, lines: number[]): string => ...) and
ensure the implementation still returns a string value to satisfy the
annotation.
- Around line 407-416: The repeat function lacks an explicit return type and is
O(n²) because it spreads linesUnit into result on every iteration; add an
explicit return type (number[]) to repeat, compute linesUnit as now (append 0 if
odd), then avoid repeated spread by preallocating or using a single push loop:
compute totalLength = linesUnit.length * count and either create a new
Array(totalLength) and fill by indexing with a pointer, or use a nested for loop
that pushes each element of linesUnit into result once per repetition; ensure
you update the named symbols repeat, linesUnit, result, count, and lines
accordingly.

- Add explicit return types to repeat() and getStrokeDasharray()
- Replace O(n²) spread-in-loop in repeat() with preallocated array
- Fix all remaining stale "Xpx hidden" comments in animation tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/cartesian/Line.tsx (1)

431-453: Add an initial value to reduce for defensive correctness.

lines.reduce((pre, next) => pre + next) throws TypeError on an empty array. While callers currently always produce a non-empty lines (via String.prototype.split), the function signature lines: number[] makes no such guarantee, and a future refactor could pass an empty array silently.

🛡️ Suggested defensive fix
-  const lineLength = lines.reduce((pre, next) => pre + next);
+  const lineLength = lines.reduce((pre, next) => pre + next, 0);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cartesian/Line.tsx` around lines 431 - 453, The reduce call in
getStrokeDasharray can throw on an empty lines array; make it defensive by
providing an initial value (0) to lines.reduce so lineLength is 0 for empty
arrays, then keep the rest of the logic unchanged (function: getStrokeDasharray,
variables: lines, lineLength).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/cartesian/Line.tsx`:
- Around line 431-453: The reduce call in getStrokeDasharray can throw on an
empty lines array; make it defensive by providing an initial value (0) to
lines.reduce so lineLength is 0 for empty arrays, then keep the rest of the
logic unchanged (function: getStrokeDasharray, variables: lines, lineLength).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/cartesian/Line.tsx (2)

407-453: ⚠️ Potential issue | 🟠 Major

Odd-count strokeDasharray patterns animate incorrectly — 0-padding diverges from the SVG spec's duplication rule.

If an odd number of values are given, the entire value will be repeated in order to set an even number of values. Padding with 0 instead produces a visually different cycle:

User prop SVG spec effective cycle repeat with 0-padding
"4" 4 4 (dash 4 → gap 4) 4 0 (dash 4 → gap 0 = solid line)
"7 3 2" 7 3 2 7 3 2 7 3 2 0 (merges 2-dash and next 7-dash)

If a single value is set, both the dash length and gap length take that value and repeat the pattern. If two values are set, the first sets the dash and the second sets the gap. So strokeDasharray="4" must animate with gaps equal to the dash length, not zero.

There is a second, compounding issue: getStrokeDasharray computes lineLength from the original lines rather than the normalized (doubled) pattern. For lines=[4], lineLength=4 while the true SVG cycle is 8. This causes count to be double what's needed, so the animated pattern overlaps on itself.

The complete fix is to normalize lines in getStrokeDasharray before computing lineLength, after which repeat can drop its special-case:

🐛 Proposed fix
 function repeat(lines: number[], count: number): number[] {
-  const linesUnit = lines.length % 2 !== 0 ? [...lines, 0] : lines;
   const result: number[] = [];
   for (let i = 0; i < count; ++i) {
-    result.push(...linesUnit);
+    result.push(...lines);
   }
   return result;
 }
 const getStrokeDasharray = (length: number, totalLength: number, lines: number[]): string => {
-  const lineLength = lines.reduce((pre, next) => pre + next, 0);
+  // Per SVG spec, an odd-count list is duplicated to yield an even-count cycle
+  // e.g. "4" → [4, 4] (dash=4, gap=4), not [4, 0]
+  const normalizedLines = lines.length % 2 !== 0 ? [...lines, ...lines] : lines;
+  const lineLength = normalizedLines.reduce((pre, next) => pre + next, 0);

   if (!lineLength) {
     return generateSimpleStrokeDasharray(totalLength, length);
   }

   const count = Math.floor(length / lineLength);
   const remainLength = length % lineLength;
   let remainLines: number[] = [];
-  for (let i = 0, sum = 0; i < lines.length; sum += lines[i] ?? 0, ++i) {
-    const lineValue = lines[i];
+  for (let i = 0, sum = 0; i < normalizedLines.length; sum += normalizedLines[i] ?? 0, ++i) {
+    const lineValue = normalizedLines[i];
     if (lineValue != null && sum + lineValue > remainLength) {
-      remainLines = [...lines.slice(0, i), remainLength - sum];
+      remainLines = [...normalizedLines.slice(0, i), remainLength - sum];
       break;
     }
   }

   const emptyLines = remainLines.length % 2 === 0 ? [0, totalLength] : [totalLength];
-  return [...repeat(lines, count), ...remainLines, ...emptyLines].map(line => `${line}px`).join(', ');
+  return [...repeat(normalizedLines, count), ...remainLines, ...emptyLines].map(line => `${line}px`).join(', ');
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cartesian/Line.tsx` around lines 407 - 453, Normalize the dash pattern to
an even-length sequence before any length math: in getStrokeDasharray, create a
normalizedLines = lines.length % 2 !== 0 ? [...lines, ...lines] : lines, use
normalizedLines (not the original lines) to compute lineLength and to drive the
loop that builds remainLines, and pass normalizedLines into repeat; then
simplify repeat(lines, count) to always repeat the provided array without
injecting a 0 for odd lengths (i.e., remove the zero-padding special-case),
keeping the rest of getStrokeDasharray logic (remainLines and emptyLines)
unchanged.

407-453: ⚠️ Potential issue | 🟠 Major

Odd-count strokeDasharray patterns animate incorrectly due to 0-padding instead of SVG-spec duplication.

The SVG spec states that if stroke-dasharray contains an odd number of values, the list is duplicated to make it even. The current code pads with 0 instead, violating the spec:

Input SVG spec effective cycle Current code (linesUnit)
"4" 4 4 (dash=4, gap=4) 4 0 (dash=4, gap=0 → solid line)
"7 3 2" 7 3 2 7 3 2 7 3 2 0 (merges 2 and 7 dashes)

Critically, lineLength in getStrokeDasharray is computed from the original lines, not the normalized linesUnit. For lines=[4], lineLength=4 while the correct SVG cycle is 8, causing count to double and the pattern to render as a continuous solid block during animation before snapping to the dashed pattern on completion.

Fix by normalizing lines before computing lineLength:

🐛 Proposed fix
 function repeat(lines: number[], count: number): number[] {
-  const linesUnit = lines.length % 2 !== 0 ? [...lines, 0] : lines;
   const result: number[] = [];
   for (let i = 0; i < count; ++i) {
-    result.push(...linesUnit);
+    result.push(...lines);
   }
   return result;
 }
 const getStrokeDasharray = (length: number, totalLength: number, lines: number[]): string => {
-  const lineLength = lines.reduce((pre, next) => pre + next, 0);
+  // Per SVG spec, odd-count dasharray is duplicated to make an even-count cycle
+  const normalizedLines = lines.length % 2 !== 0 ? [...lines, ...lines] : lines;
+  const lineLength = normalizedLines.reduce((pre, next) => pre + next, 0);

   if (!lineLength) {
     return generateSimpleStrokeDasharray(totalLength, length);
   }

   const count = Math.floor(length / lineLength);
   const remainLength = length % lineLength;
   let remainLines: number[] = [];
-  for (let i = 0, sum = 0; i < lines.length; sum += lines[i] ?? 0, ++i) {
-    const lineValue = lines[i];
+  for (let i = 0, sum = 0; i < normalizedLines.length; sum += normalizedLines[i] ?? 0, ++i) {
+    const lineValue = normalizedLines[i];
     if (lineValue != null && sum + lineValue > remainLength) {
-      remainLines = [...lines.slice(0, i), remainLength - sum];
+      remainLines = [...normalizedLines.slice(0, i), remainLength - sum];
       break;
     }
   }

   const emptyLines = remainLines.length % 2 === 0 ? [0, totalLength] : [totalLength];

-  return [...repeat(lines, count), ...remainLines, ...emptyLines].map(line => `${line}px`).join(', ');
+  return [...repeat(normalizedLines, count), ...remainLines, ...emptyLines].map(line => `${line}px`).join(', ');
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cartesian/Line.tsx` around lines 407 - 453, The odd-length dash handling
is wrong: normalize the input pattern by duplicating the array when its length
is odd (replace linesUnit = [...lines, 0] with linesUnit = lines.length % 2 !==
0 ? [...lines, ...lines] : lines) and then use that normalized array everywhere
in getStrokeDasharray (compute lineLength from the normalized array, use
normalized array for count, remainLines loop and for repeat), ensuring
repeat(linesUnit, count) and subsequent logic reference the duplicated pattern
instead of the original lines so the SVG-spec cycle length is correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/cartesian/Line.tsx`:
- Around line 407-453: Normalize the dash pattern to an even-length sequence
before any length math: in getStrokeDasharray, create a normalizedLines =
lines.length % 2 !== 0 ? [...lines, ...lines] : lines, use normalizedLines (not
the original lines) to compute lineLength and to drive the loop that builds
remainLines, and pass normalizedLines into repeat; then simplify repeat(lines,
count) to always repeat the provided array without injecting a 0 for odd lengths
(i.e., remove the zero-padding special-case), keeping the rest of
getStrokeDasharray logic (remainLines and emptyLines) unchanged.
- Around line 407-453: The odd-length dash handling is wrong: normalize the
input pattern by duplicating the array when its length is odd (replace linesUnit
= [...lines, 0] with linesUnit = lines.length % 2 !== 0 ? [...lines, ...lines] :
lines) and then use that normalized array everywhere in getStrokeDasharray
(compute lineLength from the normalized array, use normalized array for count,
remainLines loop and for repeat), ensuring repeat(linesUnit, count) and
subsequent logic reference the duplicated pattern instead of the original lines
so the SVG-spec cycle length is correct.

@roy7
Copy link
Contributor Author

roy7 commented Feb 18, 2026

From Claude:

Interesting — CodeRabbit flagged the 0-padding in repeat() as incorrect per SVG spec. It says odd-count dasharray values should be duplicated (e.g. "4" → [4, 4]), not padded with zero ([4, 0]).
However, this is pre-existing code — we didn't write it. The repeat function with 0-padding existed before our PR. Our change only added a docstring and replaced the spread-in-loop. This is outside our fix's scope.

@codecov
Copy link

codecov bot commented Feb 18, 2026

Bundle Report

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

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.26MB 1.94kB (0.15%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Line.js 1.9kB 28.36kB 7.17% ⚠️
shape/Rectangle.js 23 bytes 12.34kB 0.19%
shape/Trapezoid.js 23 bytes 7.87kB 0.29%

@codecov
Copy link

codecov bot commented Feb 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.12%. Comparing base (c3b308c) to head (5186f90).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7022      +/-   ##
==========================================
- Coverage   90.12%   90.12%   -0.01%     
==========================================
  Files         526      526              
  Lines       39183    39182       -1     
  Branches     5423     5423              
==========================================
- Hits        35312    35311       -1     
  Misses       3862     3862              
  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.

@ckifer ckifer merged commit f47a6eb into recharts:main Feb 20, 2026
42 checks passed
@roy7 roy7 deleted the fix/animated-line-linecap-flicker branch February 20, 2026 16:54
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.

Animated Line component flickers with round or square strokeLinecap

3 participants