diff --git a/documentation/ui/transitions.md b/documentation/ui/transitions.md
index 9ca6a9507..05745bc3d 100644
--- a/documentation/ui/transitions.md
+++ b/documentation/ui/transitions.md
@@ -1,7 +1,7 @@
# Transitions
-
+
You can have arbitrary visualisations and transitions for any [NavModel](../navmodel/index.md). For example, all of these are different representations of the same [Back stack](../navmodel/backstack.md):
@@ -9,13 +9,185 @@ You can have arbitrary visualisations and transitions for any [NavModel](../navm
-Below you can find the different options how to visualise `NavModel` state changes.
+Below you can find the different options how to visualise `NavModel` state changes.
## No transitions
-Using the provided [Child-related composables](children-view.md) you'll see no transitions as a default – UI changes resulting from the NavModel's state update will be rendered instantly.
+Using the provided [Child-related composables](children-view.md) you'll see no transitions as a default – UI changes resulting from the NavModel's state update will be rendered instantly.
+
+
+## Shared element transitions
+
+To support shared element transition between two Child Nodes you need:
+
+1. Use the `sharedElement` Modifier with the same key on the composable you want to connect.
+2. On the `Children` composable, set `withSharedElementTransition` to true and use either fader or
+ no transition handler at all. Using a slider will make the shared element slide away with the
+ rest of of the content.
+3. When operation is performed on the NavModel, the shared element will be animated between the two
+ Child Nodes. For instance, in the example below backStack currently has NavTarget.Child1 as the
+ active element. Performing a push operation with NavTarget.Child2 will animate the shared element
+ between NodeOne and NodeTwo. Popping back to NavTarget.Child1 will animate the shared element back.
+
+```kotlin
+class NodeOne(
+ buildContext: BuildContext
+) : Node(
+ buildContext = buildContext
+) {
+
+ @Composable
+ override fun View(modifier: Modifier) {
+ Box(
+ modifier = Modifier
+ // make sure you specify the size before using sharedElement modifier
+ .fillMaxSize()
+ .sharedElement(key = "sharedContainer")
+ ) { /** ... */ }
+ }
+}
+
+class NodeTwo(
+ buildContext: BuildContext
+) : Node(
+ buildContext = buildContext
+) {
+
+ @Composable
+ override fun View(modifier: Modifier) {
+ Box(
+ modifier = Modifier
+ // make sure you specify the size before using sharedElement modifier
+ .requiredSize(64.dp)
+ .sharedElement(key = "sharedContainer")
+ ) { /** ... */ }
+ }
+}
+
+class ParentNode(
+ buildContext: BuildContext,
+ backStack: BackStack = BackStack(
+ initialElement = NavTarget.Child1,
+ savedStateMap = buildContext.savedStateMap
+ )
+) : ParentNode(
+ buildContext = buildContext,
+ navModel = backStack,
+) {
+
+ override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node =
+ when (navTarget) {
+ NavTarget.Child1 -> NodeOne(buildContext)
+ NavTarget.Child2 -> NodeTwo(buildContext)
+ }
+
+ @Composable
+ override fun View(modifier: Modifier) {
+ Children(
+ // or any other NavModel
+ navModel = backStack,
+ // or no transitionHandler at all. Using a slider will make the shared element slide away
+ // with the rest of of the content.
+ transitionHandler = rememberBackStackFader(),
+ withSharedElementTransition = true
+ )
+ }
+}
+
+```
+
+## Transitions with movable content
+
+You can move composable content between two Child Nodes without losing its state. You can only move
+content from a Node that is currently visible and transitioning to invisible state to a Node that
+is currently invisible and transitioning to visible state as movable content is intended to be
+composed once design and is moved from one part of the composition to another.
+
+To move content between two Child Nodes you need to use `localMovableContentWithTargetVisibility`
+composable function with the correct key to retrieve existing content if it exists or put content
+for this key if it doesn't exist. In addition to that, on Parent's `Children` composable you need to
+set `withMovableContent` to true.
+In the example below when a NodeOne is being replaced with NodeTwo in a BackStack or Spotlight NavModel
+`CustomMovableContent("movableContentKey")` will be moved from NodeOne to NodeTwo without losing its
+state.
+
+
+```kotlin
+@Composable
+fun CustomMovableContent(key: Any) {
+ localMovableContentWithTargetVisibility(key = key) {
+ // implement movable content here
+ var counter by remember(pageId) { mutableIntStateOf(0) }
+ LaunchedEffect(Unit) {
+ while (true) {
+ delay(1000)
+ counter++
+ }
+ }
+ Text(text = "$counter")
+ }?.invoke()
+}
+
+
+class NodeOne(
+ buildContext: BuildContext
+) : Node(
+ buildContext = buildContext
+) {
+
+ @Composable
+ override fun View(modifier: Modifier) {
+ CustomMovableContent("movableContentKey")
+ }
+
+}
+
+class NodeTwo(
+ buildContext: BuildContext
+) : Node(
+ buildContext = buildContext
+) {
+
+ @Composable
+ override fun View(modifier: Modifier) {
+ CustomMovableContent("movableContentKey")
+ }
+}
+
+class ParentNode(
+ buildContext: BuildContext,
+ backStack: BackStack = BackStack(
+ initialElement = NavTarget.Child1,
+ savedStateMap = buildContext.savedStateMap
+ )
+) : ParentNode(
+ buildContext = buildContext,
+ navModel = backStack,
+) {
+
+ override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node =
+ when (navTarget) {
+ NavTarget.Child1 -> NodeOne(buildContext)
+ NavTarget.Child2 -> NodeTwo(buildContext)
+ }
+
+ @Composable
+ override fun View(modifier: Modifier) {
+ Children(
+ // or any other NavModel
+ navModel = backStack,
+ // or no transitionHandler at all. Using a slider will make the shared element slide away
+ // with the rest of of the content.
+ transitionHandler = rememberBackStackFader(),
+ withMovableContent = true,
+ withSharedElementTransition = true
+ )
+ }
+}
+
+```
## Jetpack Compose default animations
@@ -40,7 +212,7 @@ All the [child composables](children-view.md) provided by Appyx accept an option
The benefit of using transition handlers is you can represent any custom state of elements defined by your NavModel with Compose `Modifiers`.
-The example below is taken from [custom navigation models](../navmodel/custom.md). It matches custom transition states to different scaling values, and returns a `scale` `Modifier`.
+The example below is taken from [custom navigation models](../navmodel/custom.md). It matches custom transition states to different scaling values, and returns a `scale` `Modifier`.
```kotlin
class FooTransitionHandler(
@@ -83,4 +255,4 @@ fun rememberFooTransitionHandler(
1. You can find more complex examples in the implementations of other NavModels, such as the [Promoter carousel](../navmodel/promoter.md)
2. You can find [Codelabs tutorials](../how-to-use-appyx/codelabs.md) that help you master custom transitions
-3. You can find [Coding challenges](../how-to-use-appyx/coding-challenges.md) related to custom transitions
+3. You can find [Coding challenges](../how-to-use-appyx/coding-challenges.md) related to custom transitions
\ No newline at end of file