---
title: "SharedTransitionScope"
description: "[SharedTransitionScope] provides a coordinator space in which shared elements/ shared bounds
(when matched) will transform their bounds from one to another. Their position animation is
always relative to the origin defined by where [SharedTransitionScope] is in the tree.

[SharedTransitionScope] also creates an overlay, in which all shared elements and shared bounds
are rendered by default, so that they are not subject to their parent's fading or clipping, and
can therefore transform the bounds without alpha jumps or being unintentionally clipped.

It is also [SharedTransitionScope]'s responsibility to do the [SharedContentState] key match for
all the [sharedElement] or [sharedBounds] defined in this scope. Note: key match will not work
for [SharedContentState] created in different [SharedTransitionScope]s.

[SharedTransitionScope] oversees all the animations in its scope. When any of the animations is
active, [isTransitionActive] will be true. Once a bounds transform starts, by default the shared
element or shared bounds will render the content in the overlay. The rendering will remain in the
overlay until all other animations in the [SharedTransitionScope] are finished (i.e. when
[isTransitionActive] == false)."
type: "interface"
---

<div class='type'>Interface</div>


<a id='references'></a>

<div class='sourceset sourceset-common'>Common</div>



```kotlin
public interface SharedTransitionScope : LookaheadScope
```


`SharedTransitionScope` provides a coordinator space in which shared elements/ shared bounds
(when matched) will transform their bounds from one to another. Their position animation is
always relative to the origin defined by where `SharedTransitionScope` is in the tree.

`SharedTransitionScope` also creates an overlay, in which all shared elements and shared bounds
are rendered by default, so that they are not subject to their parent's fading or clipping, and
can therefore transform the bounds without alpha jumps or being unintentionally clipped.

It is also `SharedTransitionScope`'s responsibility to do the `SharedContentState` key match for
all the `sharedElement` or `sharedBounds` defined in this scope. Note: key match will not work
for `SharedContentState` created in different `SharedTransitionScope`s.

`SharedTransitionScope` oversees all the animations in its scope. When any of the animations is
active, `isTransitionActive` will be true. Once a bounds transform starts, by default the shared
element or shared bounds will render the content in the overlay. The rendering will remain in the
overlay until all other animations in the `SharedTransitionScope` are finished (i.e. when
`isTransitionActive` == false).


## Functions

```kotlin
public fun Modifier.skipToLookaheadSize(
        enabled: () -> Boolean = { isTransitionActive }
    ): Modifier
```


`skipToLookaheadSize` enables a layout to measure its child with the lookahead constraints,
therefore laying out the child as if the transition has finished. This is particularly
helpful for layouts where re-flowing content based on animated constraints is undesirable,
such as texts.

In the sample below, try remove the `skipToLookaheadSize` modifier and observe the
difference:

#### Parameters

| | |
| --- | --- |
| enabled | A lambda that determines when the modifier should be active. Defaults to `{ isTransitionActive }`, which enables the modifier only during active shared element transitions |



```kotlin
public fun Modifier.skipToLookaheadPosition(
        enabled: () -> Boolean = { isTransitionActive }
    ): Modifier
```


A modifier that anchors a layout at the target position obtained from the lookahead pass
during shared element transitions.

This modifier ensures that a layout maintains its target position determined by the lookahead
layout pass, preventing it from being influenced by layout changes in the tree during shared
element transitions. This is particularly useful for preventing unwanted movement or
repositioning of elements during animated transitions.

**Important**: `skipToLookaheadPosition` anchors the layout at the lookahead position
**relative to** the `SharedTransitionLayout`. It does NOT necessarily anchor the layout
within the window. More specifically, if a `SharedTransitionLayout` re-positions itself, any
child layout using `skipToLookaheadPosition` will move along with it. If it is desirable to
anchor a layout relative to a window, it's recommended to set up `SharedTransitionLayout` in
a way that it does not change position in the window.

Note: `skipToLookaheadPosition` by default is only enabled via `enabled` lambda during a
shared transition. It is recommended to enable it only when necessary. When active, it
counteracts its ancestor layout's movement, which can incur extra placement pass costs if the
parent layout frequently moves (e.g., during scrolling or animation).

#### Parameters

| | |
| --- | --- |
| enabled | A lambda that determines when the modifier should be active. Defaults to `{ isTransitionActive }`, which enables the modifier only during active shared element transitions |



```kotlin
public fun Modifier.renderInSharedTransitionScopeOverlay(
        zIndexInOverlay: Float = 0f,
        renderInOverlay: () -> Boolean = { isTransitionActive },
    ): Modifier
```


Renders the content in the `SharedTransitionScope`'s overlay, where shared content (i.e.
shared elements and shared bounds) is rendered by default. This is useful for rendering
content that is not shared on top of shared content to preserve a specific spatial
relationship.

`renderInOverlay` dynamically controls whether the content should be rendered in the
`SharedTransitionScope`'s overlay. By default, it returns the same value as
`SharedTransitionScope.isTransitionActive`. This means the default behavior is to render the
child layout of this modifier in the overlay only when the transition is active.

**IMPORTANT:** When elevating layouts into the overlay, the layout is no longer subjected
to 1) its parent's clipping, and 2) parent's layer transform (e.g. alpha, scale, etc).
Therefore, it is recommended to create an enter/exit animation (e.g. using
`AnimatedVisibilityScope.animateEnterExit`) for the child layout to avoid any abrupt visual
changes.

#### Parameters

| | |
| --- | --- |
| renderInOverlay | `renderInOverlay` determines when the content should be rendered in the overlay. Defaults to { `isTransitionActive` }, which renders the content in the overlay only when the transition is active. |
| zIndexInOverlay | The zIndex of the content in the overlay. Defaults to 0f. |



```kotlin
public fun Modifier.sharedElement(
        sharedContentState: SharedContentState,
        animatedVisibilityScope: AnimatedVisibilityScope,
        boundsTransform: BoundsTransform = SharedTransitionDefaults.BoundsTransform,
        placeholderSize: PlaceholderSize = ContentSize,
        renderInOverlayDuringTransition: Boolean = true,
        zIndexInOverlay: Float = 0f,
        clipInOverlayDuringTransition: OverlayClip = ParentClip,
    ): Modifier
```


`sharedElement` is a modifier that tags a layout with a `SharedContentState.key`, such that
entering and exiting shared elements of the same key share the animated and continuously
changing bounds during the layout change. The bounds will be animated from the initial bounds
defined by the exiting shared element to the target bounds calculated based on the incoming
shared element. The animation for the bounds can be customized using `boundsTransform`.
During the bounds transform, `sharedElement` will re-measure and relayout its child layout
using fixed constraints derived from its animated size, similar to `RemeasureToBounds`
resizeMode in `sharedBounds`.

In contrast to `sharedBounds`, `sharedElement` is designed for shared content that has the
exact match in terms of visual content and layout when the measure constraints are the same.
Such examples include image assets, icons,
`MovableContent` etc. Only the shared element that
is becoming visible will be rendered during the transition. The bounds for shared element are
determined by the bounds of the shared element becoming visible based on the target state of
`animatedVisibilityScope`.

**Important**: When a shared element finds its match and starts a transition, it will be
rendered into the overlay of the `SharedTransitionScope` in order to avoid being faded in/out
along with its parents or clipped by its parent as it transforms to the target size and
position. This also means that any clipping or fading for the shared elements will need to be
applied _explicitly_ as the child of `sharedElement` (i.e. after `sharedElement` modifier in
the modifier chain). For example: `Modifier.sharedElement(...).clip(shape =
RoundedCornerShape(20.dp)).animateEnterExit(...)`

By default, the `sharedElement` is clipped by the `clipInOverlayDuringTransition` of its
parent `sharedBounds`. If the `sharedElement` has no parent `sharedBounds` or if the parent
`sharedBounds` has no clipping defined, it'll not be clipped. If additional clipping is
desired to ensure `sharedElement` doesn't move outside of a visual bounds,
`clipInOverlayDuringTransition` can be used to specify the clipping for when the shared
element is going through an active transition towards a new target bounds.

While the shared elements are rendered in overlay during the transition, its
`zIndexInOverlay` can be specified to allow shared elements to render in a different order
than their placement/zOrder when not in the overlay. For example, the title of a page is
typically placed and rendered before the content below. During the transition, it may be
desired to animate the title over on top of the other shared elements on that page to
indicate significance or a point of interest. `zIndexInOverlay` can be used to facilitate
such use cases. `zIndexInOverlay` is 0f by default.

`renderInOverlayDuringTransition` is true by default. In some rare use cases, there may be no
clipping or layer transform (fade, scale, etc) in the application that prevents shared
elements from transitioning from one bounds to another without any clipping or sudden alpha
change. In such cases, `renderInOverlayDuringTransition` could be specified to false.

During a shared element transition, the space that was occupied by the exiting shared element
and the space that the entering shared element will take up are considered placeholders.
Their sizes during the shared element transition can be configured through `placeholderSize`.
By default, it will be the same as the content size of the respective shared element. It can
also be set to `AnimatedSize` or any other `PlaceholderSize` to report to their parent layout
an animated size to create a visual effect where the parent layout dynamically adjusts the
layout to accommodate the animated size of the shared elements.

Below is an example of using shared elements in a transition from a list to a details page.
For a more complex example using `sharedElement` along with `sharedBounds`, see the API
documentation for `SharedTransitionLayout`.

#### Parameters

| | |
| --- | --- |
| sharedContentState | The `SharedContentState` of the shared element. This defines the key used for matching shared elements. |
| animatedVisibilityScope | The `AnimatedVisibilityScope` in which the shared element is declared. This helps the system determine if the shared element is incoming or outgoing. |
| boundsTransform | A `BoundsTransform` to customize the animation specification based on the shared element's initial and target bounds during the transition. |
| placeholderSize | A `PlaceholderSize` that defines the size the transforming layout reports to the layout system during the transition. By default, this is the shared element's content size (without any scaling or transformation). |
| renderInOverlayDuringTransition | Whether the shared element should be rendered in the overlay during the transition. Defaults to `true`. |
| zIndexInOverlay | The `zIndex` of the shared element within the overlay, enabling custom z-ordering for multiple shared elements. |
| clipInOverlayDuringTransition | The clipping path of the shared element in the overlay. By default, it uses the resolved clip path from its parent `sharedBounds` (if applicable). |



```kotlin
public fun Modifier.sharedBounds(
        sharedContentState: SharedContentState,
        animatedVisibilityScope: AnimatedVisibilityScope,
        enter: EnterTransition = fadeIn(),
        exit: ExitTransition = fadeOut(),
        boundsTransform: BoundsTransform = SharedTransitionDefaults.BoundsTransform,
        resizeMode: ResizeMode = scaleToBounds(ContentScale.FillWidth, Center),
        placeholderSize: PlaceholderSize = ContentSize,
        renderInOverlayDuringTransition: Boolean = true,
        zIndexInOverlay: Float = 0f,
        clipInOverlayDuringTransition: OverlayClip = ParentClip,
    ): Modifier
```


`sharedBounds` is a modifier that tags a layout with a `SharedContentState.key`, such that
entering and exiting shared bounds of the same key share the animated and continuously
changing bounds during the layout change. The bounds will be animated from the initial bounds
defined by the exiting shared bounds to the target bounds calculated based on the incoming
shared shared bounds. The animation for the bounds can be customized using `boundsTransform`.
The target bounds for `sharedBounds` are determined by the bounds of the `sharedBounds`
becoming visible based on the target state of `animatedVisibilityScope`.

In contrast to `sharedElement`, `sharedBounds` is designed for shared content that has the
visually different content. While the `sharedBounds` keeps the continuity of the bounds, the
incoming and outgoing content within the `sharedBounds` will enter and exit in an enter/exit
transition using `enter`/`exit`. By default, `fadeIn` and `fadeOut` are used to fade the
content in or out.

`resizeMode` defines how the child layout of `sharedBounds` should be resized during
`boundsTransform`. By default, `scaleToBounds` will be used to measure the child content with
lookahead constraints to arrive at the stable layout. Then the stable layout will be scaled
to fit or fill (depending on the content scale used) the transforming bounds of
`sharedBounds`. If there's a need to relayout content (rather than scaling) based on the
animated bounds size (e.g. dynamically resizing a Row), it's recommended to use
`RemeasureToBounds` as the `resizeMode`.

**Important**: When a shared bounds finds its match and starts a transition, it will be
rendered into the overlay of the `SharedTransitionScope` in order to avoid being faded in/out
along with its parents or clipped by its parent as it transforms to the target size and
position. This also means that any clipping or fading for the shared elements will need to be
applied _explicitly_ as the child of `sharedBounds` (i.e. after `sharedBounds` modifier in
the modifier chain). For example: `Modifier.sharedBounds(...).clip(shape =
RoundedCornerShape(20.dp))`

By default, the `sharedBounds` is clipped by the `clipInOverlayDuringTransition` of its
parent `sharedBounds` in the layout tree. If the `sharedBounds` has no parent `sharedBounds`
or if the parent `sharedBounds` has no clipping defined, it'll not be clipped. If additional
clipping is desired to ensure child `sharedBounds` or child `sharedElement` don't move
outside of the this `sharedBounds`'s visual bounds in the overlay,
`clipInOverlayDuringTransition` can be used to specify the clipping.

While the shared bounds are rendered in overlay during the transition, its `zIndexInOverlay`
can be specified to allow them to render in a different order than their placement/zOrder
when not in the overlay. For example, the title of a page is typically placed and rendered
before the content below. During the transition, it may be desired to animate the title over
on top of the other shared elements on that page to indicate significance or a point of
interest. `zIndexInOverlay` can be used to facilitate such use cases. `zIndexInOverlay` is 0f
by default.

`renderInOverlayDuringTransition` is true by default. In some rare use cases, there may be no
clipping or layer transform (fade, scale, etc) in the application that prevents shared
elements from transitioning from one bounds to another without any clipping or sudden alpha
change. In such cases, `renderInOverlayDuringTransition` could be specified to false.

During a shared bounds transition, the space that was occupied by the exiting shared bounds
and the space that the entering shared bounds will take up are considered placeholders. Their
sizes during the shared element transition can be configured through `placeholderSize`. By
default, it will be the same as the content size of the respective shared bounds. It can also
be set to `AnimatedSize` or any other `PlaceholderSize` to report to their parent layout an
animated size to create a visual effect where the parent layout dynamically adjusts the
layout to accommodate the animated size of the shared elements.


Since `sharedBounds` show both incoming and outgoing content in its bounds, it affords
opportunities to do interesting transitions where additional `sharedElement` and
`sharedBounds` can be nested in a parent `sharedBounds`. See the sample code below for a more
complex example with nested shared bounds/elements.

#### Parameters

| | |
| --- | --- |
| sharedContentState | The `SharedContentState` of the shared element. This defines the key used for matching shared elements. |
| animatedVisibilityScope | The `AnimatedVisibilityScope` in which the shared element is declared. This helps the system determine if the shared element is incoming or outgoing. |
| enter | The enter transition used for incoming content while it's displayed within the transforming bounds. This defaults to a fade-in. |
| exit | The exit transition used for outgoing content while it's displayed within the transforming bounds. This defaults to a fade-out. |
| boundsTransform | A `BoundsTransform` to customize the animation specification based on the shared element's initial and target bounds for the transition. |
| resizeMode | A `ResizeMode` that defines how the child layout of `sharedBounds` should be resized during `boundsTransform`. By default, `scaleToBounds` is used to scale the child content to fit the transforming bounds. |
| placeholderSize | A `PlaceholderSize` that defines the size the transforming layout reports to the layout system during the transition. By default, this is the shared bounds' content size (without any scaling or transformation). |
| renderInOverlayDuringTransition | Whether the shared bounds should be rendered in the overlay during the transition. Defaults to `true`. |
| zIndexInOverlay | The `zIndex` of the shared bounds within the overlay, enabling custom z-ordering for multiple shared bounds or elements. |
| clipInOverlayDuringTransition | The clipping path of the shared bounds in the overlay. By default, it uses the resolved clip path from its parent `sharedBounds` (if applicable). |



```kotlin
public fun Modifier.sharedElementWithCallerManagedVisibility(
        sharedContentState: SharedContentState,
        visible: Boolean,
        boundsTransform: BoundsTransform = SharedTransitionDefaults.BoundsTransform,
        placeholderSize: PlaceholderSize = ContentSize,
        renderInOverlayDuringTransition: Boolean = true,
        zIndexInOverlay: Float = 0f,
        clipInOverlayDuringTransition: OverlayClip = ParentClip,
    ): Modifier
```


`sharedElementWithCallerManagedVisibility` is a modifier that tags a layout with a
`SharedContentState.key`, such that entering and exiting shared elements of the same key
share the animated and continuously changing bounds during the layout change. The bounds will
be animated from the initial bounds defined by the exiting shared element to the target
bounds calculated based on the incoming shared element. The animation for the bounds can be
customized using `boundsTransform`.

Compared to `sharedElement`, `sharedElementWithCallerManagedVisibility` is designed for
shared element transitions where the shared element is not a part of the content that is
being animated out by `AnimatedVisibility`. Therefore, it is the caller's responsibility to
explicitly remove the exiting shared element (i.e. shared elements where `visible` == false)
from the tree as appropriate. Typically this is when the transition is finished (i.e.
`SharedTransitionScope.isTransitionActive` == false). The target bounds is derived from the
`sharedElementWithCallerManagedVisibility` with `visible` being true.

In contrast to `sharedBounds`, this modifier is intended for shared content that has the
exact match in terms of visual content and layout when the measure constraints are the same.
Such examples include image assets, icons,
`MovableContent` etc. Only the shared element that
is becoming visible will be rendered during the transition.

**Important**: When a shared element finds its match and starts a transition, it will be
rendered into the overlay of the `SharedTransitionScope` in order to avoid being faded in/out
along with its parents or clipped by its parent as it transforms to the target size and
position. This also means that any clipping or fading for the shared elements will need to be
applied _explicitly_ as the child of `sharedElementWithCallerManagedVisibility` (i.e. after
`sharedElementWithCallerManagedVisibility` modifier in the modifier chain). For example:
```
Modifier.sharedElementWithCallerManagedVisibility(...)       .clip(shape = RoundedCornerShape(20.dp))
```

By default, the `sharedElementWithCallerManagedVisibility` is clipped by the
`clipInOverlayDuringTransition` of its parent `sharedBounds`. If the
`sharedElementWithCallerManagedVisibility` has no parent `sharedBounds` or if the parent
`sharedBounds` has no clipping defined, it'll not be clipped. If additional clipping is
desired to ensure `sharedElementWithCallerManagedVisibility` doesn't move outside of a visual
bounds, `clipInOverlayDuringTransition` can be used to specify the clipping for when the
shared element is going through an active transition towards a new target bounds.

While the shared elements are rendered in overlay during the transition, its
`zIndexInOverlay` can be specified to allow shared elements to render in a different order
than their placement/zOrder when not in the overlay. For example, the title of a page is
typically placed and rendered before the content below. During the transition, it may be
desired to animate the title over on top of the other shared elements on that page to
indicate significance or a point of interest. `zIndexInOverlay` can be used to facilitate
such use cases. `zIndexInOverlay` is 0f by default.

`renderInOverlayDuringTransition` is true by default. In some rare use cases, there may be no
clipping or layer transform (fade, scale, etc) in the application that prevents shared
elements from transitioning from one bounds to another without any clipping or sudden alpha
change. In such cases, `renderInOverlayDuringTransition` could be specified to false.

During a shared element transition, the space that was occupied by the exiting shared element
and the space that the entering shared element will take up are considered placeholders.
Their sizes during the shared element transition can be configured through `placeholderSize`.
By default, it will be the same as the content size of the respective shared element. It can
also be set to `AnimatedSize` or any other `PlaceholderSize` to report to their parent layout
an animated size to create a visual effect where the parent layout dynamically adjusts the
layout to accommodate the animated size of the shared elements.

#### Parameters

| | |
| --- | --- |
| sharedContentState | The `SharedContentState` of the shared element. This defines the key used for matching shared elements. |
| visible | Whether the shared element is visible. |
| boundsTransform | A `BoundsTransform` to customize the animation specification based on the shared element's initial and target bounds during the transition. |
| placeholderSize | A `PlaceholderSize` that defines the size the transforming layout reports to the layout system during the transition. By default, this is the shared element's content size (without any scaling or transformation). |
| renderInOverlayDuringTransition | Whether the shared element should be rendered in the overlay during the transition. Defaults to `true`. |
| zIndexInOverlay | The `zIndex` of the shared element within the overlay, enabling custom z-ordering for multiple shared elements. |
| clipInOverlayDuringTransition | The clipping path of the shared element in the overlay. By default, it uses the resolved clip path from its parent `sharedBounds` (if applicable). |



```kotlin
public fun OverlayClip(clipShape: Shape): OverlayClip
```


Creates an `OverlayClip` based on a specific `clipShape`.


```kotlin
@Composable
    public fun rememberSharedContentState(key: Any): SharedContentState
```


Creates and remembers a `SharedContentState` with a given `key` and a given
`SharedContentConfig`.

#### Parameters

| | |
| --- | --- |
| key | will be used to match a shared element against others in the same `SharedTransitionScope`. |



```kotlin
@Composable
    public fun rememberSharedContentState(
        key: Any,
        config: SharedContentConfig,
    ): SharedContentState
```


Creates and remembers a `SharedContentState` with a given `key` and a given
`SharedContentConfig`.

`config` defines whether the shared element is enabled or disabled, and the alternative
target bounds if the shared element is disposed amid animation (e.g., scrolled out of the
viewport and subsequently disposed).

#### Parameters

| | |
| --- | --- |
| key | will be used to match a shared element against others in the same `SharedTransitionScope`. |
| config | defines whether the shared element is enabled or disabled, and the alternative target bounds if the shared element is disposed amid animation (e.g., scrolled out of the viewport and subsequently disposed). |



```kotlin
public fun SharedContentConfig(): SharedContentConfig
```


`SharedContentConfig` is a factory method that returns an `SharedContentConfig` object with
default implementations for all the functions and properties defined in the
`SharedContentConfig` interface. More specifically, the returned
`SharedTransitionScope.SharedContentConfig` enables shared elements and bounds, and keeps
them enabled while the animation is in-flight. It also sets the
`SharedContentConfig.alternativeTargetBoundsInTransitionScopeAfterRemoval` to null, ensuring
the shared element transition is canceled immediately if the incoming shared element is
removed during the animation.



## Code Examples

### SharedElementInAnimatedContentSample
```kotlin
@Composable
fun SharedElementInAnimatedContentSample() {
    // This is the Image that we will add shared element modifier on. It's important to make sure
    // modifiers that are not shared between the two shared elements (such as size modifiers if
    // the size changes) are the parents (i.e. on the left side) of Modifier.sharedElement.
    // Meanwhile, the modifiers that are shared between the shared elements (e.g. Modifier.clip
    // in this case) are on the right side of the Modifier.sharedElement.
    @Composable
    fun Cat(modifier: Modifier = Modifier) {
        Image(
            painterResource(id = R.drawable.yt_profile),
            contentDescription = "cute cat",
            contentScale = ContentScale.FillHeight,
            modifier = modifier.clip(shape = RoundedCornerShape(10)),
        )
    }
    // Shared element key is of type `Any`, which means it can be id, string, etc. The only
    // requirement for the key is that it should be the same for shared elements that you intend
    // to match. Here we use the image resource id as the key.
    val sharedElementKey = R.drawable.yt_profile
    var showLargeImage by remember { mutableStateOf(true) }
    // First, we need to create a SharedTransitionLayout, this Layout will provide the coordinator
    // space for shared element position animation, as well as an overlay for shared elements to
    // render in. Children content in this Layout will be able to create shared element transition
    // using the receiver scope: SharedTransitionScope
    SharedTransitionLayout(
        Modifier.clickable { showLargeImage = !showLargeImage }.fillMaxSize().padding(10.dp)
    ) {
        // In the SharedTransitionLayout, we will be able to access the receiver scope (i.e.
        // SharedTransitionScope) in order to create shared element transition.
        AnimatedContent(targetState = showLargeImage) { showLargeImageMode ->
            if (showLargeImageMode) {
                Cat(
                    Modifier.fillMaxSize()
                        .aspectRatio(1f)
                        // Creating a shared element. Note that this modifier is *after*
                        // the size modifier and aspectRatio modifier, because those size specs
                        // are not shared between the two shared elements.
                        .sharedElement(
                            rememberSharedContentState(sharedElementKey),
                            // Using the AnimatedVisibilityScope from the AnimatedContent
                            // defined above.
                            this@AnimatedContent,
                        )
                )
                Text(
                    "Cute Cat YT",
                    fontSize = 40.sp,
                    color = Color.Blue,
                    // Prefer Modifier.sharedBounds for text, unless the texts in both initial
                    // content and target content are exactly the same (i.e. same
                    // size/font/color)
                    modifier =
                        Modifier.fillMaxWidth()
                            // IMPORTANT: Prefer using wrapContentWidth/wrapContentSize over
                            // textAlign
                            // for shared text transition. This allows the layout system sees actual
                            // position and size of the text to facilitate bounds animation.
                            .wrapContentWidth(Alignment.CenterHorizontally)
                            .sharedBounds(
                                rememberSharedContentState(key = "text"),
                                this@AnimatedContent,
                            ),
                )
            } else {
                Column {
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        Cat(
                            Modifier.size(100.dp)
                                // Creating another shared element with the same key.
                                // Note that this modifier is *after* the size modifier,
                                // The size changes between these two shared elements, i.e. the size
                                // is not shared between the two shared elements.
                                .sharedElement(
                                    rememberSharedContentState(sharedElementKey),
                                    this@AnimatedContent,
                                )
                        )
                        Text(
                            "Cute Cat YT",
                            // Change text color & size
                            fontSize = 20.sp,
                            color = Color.DarkGray,
                            // Prefer Modifier.sharedBounds for text, unless the texts in both
                            // initial content and target content are exactly the same (i.e. same
                            // size/font/color)
                            modifier =
                                Modifier
                                    // The modifier that is not a part of the shared content, but
                                    // rather
                                    // for positioning and sizes should be on the *left* side of
                                    // sharedBounds/sharedElement.
                                    .padding(start = 20.dp)
                                    .sharedBounds(
                                        // Here we use a string-based key, in contrast to the key
                                        // above.
                                        rememberSharedContentState(key = "text"),
                                        this@AnimatedContent,
                                    ),
                        )
                    }
                    Box(
                        Modifier.fillMaxWidth()
                            .height(100.dp)
                            .background(Color(0xffffcc5c), RoundedCornerShape(5.dp))
                    )
                    Box(
                        Modifier.fillMaxWidth()
                            .height(100.dp)
                            .background(Color(0xff2a9d84), RoundedCornerShape(5.dp))
                    )
                }
            }
        }
    }
}
```

