diff --git a/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretNavHost.kt b/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretNavHost.kt index 6195f95..3c8e4b1 100644 --- a/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretNavHost.kt +++ b/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretNavHost.kt @@ -1,5 +1,10 @@ package de.jeanlucmakiola.floret.ui.navigation +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideOutHorizontally import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier @@ -28,11 +33,20 @@ import de.jeanlucmakiola.floret.ui.tasklist.TaskListViewModel @Composable fun FloretNavHost(modifier: Modifier = Modifier) { val nav = rememberNavController() + val slide = rememberNavSlideSpec() NavHost( navController = nav, startDestination = Dest.LISTS, modifier = modifier, + // Only the screen on top moves; the background is always held static. + // Forward is a plain fade-in over the held screen — calm, not a slide. + // Back (and the predictive-back drag, which drives popExit) is the snappy + // slide-out to the right, revealing the held screen unmoved. + enterTransition = { fadeIn() }, + exitTransition = { ExitTransition.None }, + popEnterTransition = { EnterTransition.None }, + popExitTransition = { slideOutHorizontally(slide) { it } + fadeOut() }, ) { composable(Dest.LISTS) { ListsScreen( diff --git a/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretTransitions.kt b/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretTransitions.kt new file mode 100644 index 0000000..1b327e9 --- /dev/null +++ b/app/src/main/java/de/jeanlucmakiola/floret/ui/navigation/FloretTransitions.kt @@ -0,0 +1,21 @@ +package de.jeanlucmakiola.floret.ui.navigation + +import androidx.compose.animation.core.FiniteAnimationSpec +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.IntOffset + +/** + * The horizontal slide spec for screen-to-screen navigation: the *fast* + * spring-physics spec from the active motion scheme — snappy with a subtle + * springy settle, rather than a fixed easing curve. Same choice as Calendula's + * calendar slide, so the two apps move the same way. + * + * Read in composable scope so the non-composable `NavHost` transition lambdas + * can capture it. + */ +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun rememberNavSlideSpec(): FiniteAnimationSpec = + MaterialTheme.motionScheme.fastSpatialSpec()