Animate basket price and item changes
Reflow remaining basket lines with framer-motion when an item is removed, slide the per-line price when it changes, and tween the basket total up/down to its new amount instead of snapping to it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@ import styles from './AnimatedNumber.module.scss'
|
||||
|
||||
type AnimatedNumberProps = {
|
||||
value: number
|
||||
format?: (value: number) => string
|
||||
align?: 'center' | 'start'
|
||||
className?: string
|
||||
}
|
||||
|
||||
@@ -23,7 +25,12 @@ const variants = {
|
||||
// in the render body — mutating a ref here would already reflect the new
|
||||
// value by the time `exit`'s "custom" is resolved for the outgoing digit,
|
||||
// so every transition — increment or decrement — read as "forward".
|
||||
export const AnimatedNumber = ({ value, className }: AnimatedNumberProps) => {
|
||||
export const AnimatedNumber = ({
|
||||
value,
|
||||
format = String,
|
||||
align = 'center',
|
||||
className,
|
||||
}: AnimatedNumberProps) => {
|
||||
const reduceMotion = useReducedMotion()
|
||||
const [previousValue, setPreviousValue] = useState(value)
|
||||
const [direction, setDirection] = useState(1)
|
||||
@@ -34,11 +41,14 @@ export const AnimatedNumber = ({ value, className }: AnimatedNumberProps) => {
|
||||
}
|
||||
|
||||
if (reduceMotion) {
|
||||
return <span className={className}>{value}</span>
|
||||
return <span className={className}>{format(value)}</span>
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={`${styles.wrapper} ${className ?? ''}`}>
|
||||
<span
|
||||
className={`${styles.wrapper} ${className ?? ''}`}
|
||||
style={{ justifyItems: align }}
|
||||
>
|
||||
<AnimatePresence mode="popLayout" initial={false} custom={direction}>
|
||||
<motion.span
|
||||
key={value}
|
||||
@@ -50,7 +60,7 @@ export const AnimatedNumber = ({ value, className }: AnimatedNumberProps) => {
|
||||
transition={{ duration: 0.15, ease: 'easeOut' }}
|
||||
className={styles.digit}
|
||||
>
|
||||
{value}
|
||||
{format(value)}
|
||||
</motion.span>
|
||||
</AnimatePresence>
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user