11package com.getcode.ui.components.text
22
33import androidx.compose.animation.AnimatedContent
4+ import androidx.compose.animation.EnterExitState
5+ import androidx.compose.animation.EnterTransition
6+ import androidx.compose.animation.ExitTransition
7+ import androidx.compose.animation.SizeTransform
8+ import androidx.compose.animation.core.animateFloat
49import androidx.compose.animation.core.tween
10+ import androidx.compose.animation.expandVertically
511import androidx.compose.animation.fadeIn
612import androidx.compose.animation.fadeOut
13+ import androidx.compose.animation.shrinkVertically
714import androidx.compose.animation.slideInVertically
815import androidx.compose.animation.slideOutVertically
916import androidx.compose.animation.togetherWith
@@ -18,12 +25,15 @@ import androidx.compose.runtime.getValue
1825import androidx.compose.runtime.mutableStateOf
1926import androidx.compose.runtime.remember
2027import androidx.compose.runtime.setValue
28+ import androidx.compose.ui.Alignment
2129import androidx.compose.ui.Modifier
30+ import androidx.compose.ui.draw.blur
2231import androidx.compose.ui.draw.clipToBounds
2332import androidx.compose.ui.graphics.Color
2433import androidx.compose.ui.platform.LocalDensity
2534import androidx.compose.ui.text.TextStyle
2635import androidx.compose.ui.text.rememberTextMeasurer
36+ import androidx.compose.ui.unit.dp
2737import com.getcode.ui.components.text.animated.defaultDigitEnter
2838import com.getcode.ui.components.text.animated.defaultDigitExit
2939
@@ -78,12 +88,37 @@ private fun AnimatedDigit(
7888 AnimatedContent (
7989 targetState = char,
8090 transitionSpec = {
81- defaultDigitEnter(- height) togetherWith defaultDigitExit(- height)
91+ if (targetState != initialState) {
92+ // Enter: slide in from bottom (increasing) or top (decreasing) + fade
93+ val enter = slideInVertically { height ->
94+ if (direction > 0 ) height else - height
95+ } + fadeIn()
96+
97+ // Exit: just fade/blur in place - no slide
98+ val exit = fadeOut()
99+
100+ enter togetherWith exit using SizeTransform ()
101+ } else {
102+ EnterTransition .None togetherWith ExitTransition .None
103+ }
82104 },
83- label = " digitRoll" ,
84- ) { digit ->
105+ label = " digit"
106+ ) { char ->
107+ // Apply blur during exit transition
108+ val blurRadius by transition.animateFloat(
109+ transitionSpec = { tween(150 ) },
110+ label = " blur"
111+ ) { state ->
112+ when (state) {
113+ EnterExitState .PreEnter -> 12f
114+ EnterExitState .Visible -> 0f
115+ EnterExitState .PostExit -> 12f
116+ }
117+ }
118+
85119 Text (
86- text = digit.toString(),
120+ modifier = Modifier .blur(blurRadius.dp),
121+ text = char.toString(),
87122 style = style,
88123 color = color,
89124 )
0 commit comments