feat: integrate NumberFlow for smooth animated number display
- Replace react-spring value animation with NumberFlow component - Add smooth digit-by-digit rolling animations for value changes - Maintain consistent styling with inherit properties - Improve user experience with professional number transitions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState, useCallback, useMemo, useEffect, useRef } from 'react'
|
||||
import { useSpring, animated } from '@react-spring/web'
|
||||
import NumberFlow from '@number-flow/react'
|
||||
import { css } from '../../styled-system/css'
|
||||
import { TypstSoroban } from './TypstSoroban'
|
||||
|
||||
@@ -27,11 +28,7 @@ export function InteractiveAbacus({
|
||||
const [previousValue, setPreviousValue] = useState(initialValue)
|
||||
const svgRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
// Animated value display
|
||||
const valueSpring = useSpring({
|
||||
value: currentValue,
|
||||
config: { tension: 300, friction: 26 }
|
||||
})
|
||||
// Remove the old spring animation since we're using NumberFlow now
|
||||
|
||||
// Container animation for feedback
|
||||
const containerSpring = useSpring({
|
||||
@@ -249,7 +246,7 @@ export function InteractiveAbacus({
|
||||
|
||||
{/* Value Display */}
|
||||
{showValue && (
|
||||
<animated.div
|
||||
<div
|
||||
className={css({
|
||||
fontSize: '3xl',
|
||||
fontWeight: 'bold',
|
||||
@@ -265,8 +262,15 @@ export function InteractiveAbacus({
|
||||
boxShadow: '0 4px 12px rgba(59, 130, 246, 0.15)'
|
||||
})}
|
||||
>
|
||||
{valueSpring.value.to(val => Math.round(val))}
|
||||
</animated.div>
|
||||
<NumberFlow
|
||||
value={currentValue}
|
||||
style={{
|
||||
fontSize: 'inherit',
|
||||
fontWeight: 'inherit',
|
||||
color: 'inherit'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Controls */}
|
||||
|
||||
@@ -855,18 +855,6 @@
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
|
||||
.\[\@media_\(max-width\:_768px\)\]\:gap_10px {
|
||||
gap: 10px
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
|
||||
.\[\@media_\(max-width\:_480px\)\]\:gap_8px {
|
||||
gap: 8px
|
||||
}
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
|
||||
.\[\@media_\(max-width\:_768px\)\]\:h_130px {
|
||||
height: 130px
|
||||
}
|
||||
@@ -899,18 +887,6 @@
|
||||
min-width: 90px
|
||||
}
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
|
||||
.\[\@media_\(max-width\:_768px\)\]\:fs_40px {
|
||||
font-size: 40px
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
|
||||
.\[\@media_\(max-width\:_480px\)\]\:fs_32px {
|
||||
font-size: 32px
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 48em) {
|
||||
.md\:px_4 {
|
||||
@@ -933,6 +909,9 @@
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.\[\@media_\(max-width\:_768px\)\]\:gap_10px {
|
||||
gap: 10px
|
||||
}
|
||||
.\[\@media_\(max-width\:_768px\)\]\:h_130px {
|
||||
height: 130px
|
||||
}
|
||||
@@ -940,6 +919,9 @@
|
||||
.\[\@media_\(max-width\:_768px\)\]\:min-w_100px {
|
||||
min-width: 100px
|
||||
}
|
||||
.\[\@media_\(max-width\:_768px\)\]\:fs_40px {
|
||||
font-size: 40px
|
||||
}
|
||||
|
||||
.\[\@media_\(max-width\:_768px\)\]\:gap_10px {
|
||||
gap: 10px
|
||||
@@ -959,6 +941,9 @@
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.\[\@media_\(max-width\:_480px\)\]\:gap_8px {
|
||||
gap: 8px
|
||||
}
|
||||
.\[\@media_\(max-width\:_480px\)\]\:h_120px {
|
||||
height: 120px
|
||||
}
|
||||
@@ -966,6 +951,9 @@
|
||||
.\[\@media_\(max-width\:_480px\)\]\:min-w_90px {
|
||||
min-width: 90px
|
||||
}
|
||||
.\[\@media_\(max-width\:_480px\)\]\:fs_32px {
|
||||
font-size: 32px
|
||||
}
|
||||
|
||||
.\[\@media_\(max-width\:_480px\)\]\:gap_8px {
|
||||
gap: 8px
|
||||
|
||||
Reference in New Issue
Block a user