Skip to content

Commit 2eec5bc

Browse files
authored
feat(ui): expose animationSpec's for PullToReveal; add spring to ContactList (#1024)
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 3afd071 commit 2eec5bc

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

  • apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens
  • ui/components/src/main/kotlin/com/getcode/ui/components

apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactListScreen.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package com.flipcash.app.directsend.internal.screens
22

3+
import androidx.compose.animation.core.Spring
4+
import androidx.compose.animation.core.spring
5+
import androidx.compose.animation.expandVertically
6+
import androidx.compose.animation.fadeIn
7+
import androidx.compose.animation.fadeOut
8+
import androidx.compose.animation.shrinkVertically
39
import androidx.compose.foundation.layout.PaddingValues
410
import androidx.compose.foundation.layout.Row
511
import androidx.compose.foundation.layout.padding
@@ -114,6 +120,26 @@ internal fun ContactListScreen() {
114120
state = pullToRevealState,
115121
modifier = Modifier.padding(innerPadding),
116122
onSuppressDismissChange = { suppress -> setSheetGesturesEnabled(!suppress) },
123+
// Telegram (iOS)-style reveal: a soft, low-stiffness spring that springs
124+
// down and settles with a single gentle overshoot — the bit of bounce
125+
// that makes it feel alive. Fade is synced so it moves in lockstep.
126+
enter = fadeIn(
127+
animationSpec = spring(stiffness = Spring.StiffnessLow),
128+
) + expandVertically(
129+
animationSpec = spring(
130+
dampingRatio = Spring.DampingRatioMediumBouncy,
131+
stiffness = Spring.StiffnessLow,
132+
),
133+
),
134+
// Collapse quickly and cleanly with no bounce.
135+
exit = fadeOut(
136+
animationSpec = spring(stiffness = Spring.StiffnessMedium),
137+
) + shrinkVertically(
138+
animationSpec = spring(
139+
dampingRatio = Spring.DampingRatioNoBouncy,
140+
stiffness = Spring.StiffnessMedium,
141+
),
142+
),
117143
revealContent = {
118144
Row(
119145
modifier = Modifier

ui/components/src/main/kotlin/com/getcode/ui/components/PullToReveal.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package com.getcode.ui.components
22

33
import androidx.compose.animation.AnimatedVisibility
4+
import androidx.compose.animation.EnterTransition
5+
import androidx.compose.animation.ExitTransition
6+
import androidx.compose.animation.expandVertically
7+
import androidx.compose.animation.fadeIn
8+
import androidx.compose.animation.fadeOut
9+
import androidx.compose.animation.shrinkVertically
410
import androidx.compose.foundation.layout.Column
511
import androidx.compose.runtime.Composable
612
import androidx.compose.runtime.LaunchedEffect
@@ -80,6 +86,12 @@ fun rememberPullToRevealState(initiallyRevealed: Boolean = false): PullToRevealS
8086
object PullToRevealDefaults {
8187
/** Default pull distance required before the reveal slot is shown. */
8288
val Threshold: Dp = 56.dp
89+
90+
/** Default transition used to animate the reveal slot in (expand + fade). */
91+
val Enter: EnterTransition = fadeIn() + expandVertically()
92+
93+
/** Default transition used to animate the reveal slot out (shrink + fade). */
94+
val Exit: ExitTransition = fadeOut() + shrinkVertically()
8395
}
8496

8597
/**
@@ -98,6 +110,9 @@ object PullToRevealDefaults {
98110
* sheet's drag-to-dismiss) should be disabled so the pull reveals instead of
99111
* dismissing; the value stays `true` for the whole reveal gesture — not just while
100112
* hidden — so a single hard pull cannot reveal and then dismiss in one motion.
113+
* @param enter transition applied when [revealContent] animates in. Override (e.g.
114+
* with a spring-backed `expandVertically`) to tune the reveal motion.
115+
* @param exit transition applied when [revealContent] animates out.
101116
*/
102117
@Composable
103118
fun PullToReveal(
@@ -107,6 +122,8 @@ fun PullToReveal(
107122
threshold: Dp = PullToRevealDefaults.Threshold,
108123
enabled: Boolean = true,
109124
onSuppressDismissChange: ((Boolean) -> Unit)? = null,
125+
enter: EnterTransition = PullToRevealDefaults.Enter,
126+
exit: ExitTransition = PullToRevealDefaults.Exit,
110127
content: @Composable () -> Unit,
111128
) {
112129
val thresholdPx = with(LocalDensity.current) { threshold.toPx() }
@@ -167,7 +184,7 @@ fun PullToReveal(
167184
}
168185

169186
Column(modifier = modifier.nestedScroll(connection)) {
170-
AnimatedVisibility(visible = state.isRevealed) {
187+
AnimatedVisibility(visible = state.isRevealed, enter = enter, exit = exit) {
171188
revealContent()
172189
}
173190
content()

0 commit comments

Comments
 (0)