Skip to content

fix(shared): preserve decimal precision in string interpolator#2469

Merged
joshuaellis merged 1 commit into
nextfrom
fix/1461-string-precision
May 22, 2026
Merged

fix(shared): preserve decimal precision in string interpolator#2469
joshuaellis merged 1 commit into
nextfrom
fix/1461-string-precision

Conversation

@joshuaellis

@joshuaellis joshuaellis commented May 22, 2026

Copy link
Copy Markdown
Member

Summary

Closes #1461. Stringified floats lost their precision through useSpring'0.00' rendered as '0', '1.50' settled at '1.5', and mid-tween values flickered raw IEEE-754 noise. Springs should respect the text the user wrote.

Fix

In createStringInterpolator: return each keyframe verbatim when input lands on it (preserves all formatting at start and goal), and pad mid-animation results to the keyframes' shared decimal count when every keyframe opts in to fractional digits. Padding is gated on a non-zero shared count so whole-number keyframes (notably the alpha channel in rgba(…, 0)rgba(…, 1)) keep their natural sub-frame precision.

Out of scope

#1660's + sign case has a different root cause (AnimatedString lifecycle). Locale separators like '1.500 kr' mid-tween require .to(formatter)numberRegex can't disambiguate them.

Closes #1461. The string interpolator used `output[0]` as both the
value at `input = range[0]` and the template for every other input,
so trailing zeros (`'0.00'`), explicit signs, and any other format
information on later keyframes were dropped on the round-trip through
`numberRegex`. As a result, `useSpring({ from: '0.00', to: '1.50' })`
rendered `'0'` at rest and `'1.5'` at the goal.

Two-part fix:

1. When `input` lands exactly on a `range` value, return that
   keyframe's `output[k]` verbatim — fixes initial render and at-rest
   goal for all formats (decimals, signs, locale separators).
2. Per number-position, when every keyframe shares the same non-zero
   fractional-digit count, `toFixed(n)` the mid-animation result.
   Gated on `> 0` so whole-number keyframes (e.g. `rgba(…, 0)` →
   `rgba(…, 1)`) keep their natural sub-frame precision.
@vercel

vercel Bot commented May 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-spring Ready Ready Preview May 22, 2026 6:56am

Request Review

@changeset-bot

changeset-bot Bot commented May 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 290788c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@react-spring/shared Patch
@react-spring/animated Patch
@react-spring/core Patch
@react-spring/mock-raf Patch
@react-spring/parallax Patch
@react-spring/rafz Patch
@react-spring/types Patch
@react-spring/konva Patch
@react-spring/native Patch
@react-spring/three Patch
@react-spring/web Patch
@react-spring/zdog Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@joshuaellis
joshuaellis merged commit f9a1857 into next May 22, 2026
18 checks passed
@joshuaellis
joshuaellis deleted the fix/1461-string-precision branch May 22, 2026 07:20
This was referenced May 22, 2026
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.

Floats can be cast to integers with useSpring

1 participant