Morphing Sheets Out of Buttons in SwiftUI

Updated on March 8th, 2026

⏱ Reading Time: 4 mins

WWDC 2025 brought many advancements in the UI with the new Liquid Glass design. Among them, there’s a brand new feature, a transition in particular, that would be easy to overlook in that huge load of novelties. This new built-in transition comes to add a new way to present sheets, as it allows to morph a sheet out of the button that initiates its appearance, instead of sliding up from the bottom edge. In plain words, the button is transformed into a sheet and the opposite, creating a beautiful visual effect.

Using the right view modifiers to the right places is mainly what it takes to achieve that transition. The best way to explore everything is through a simple example, so let’s get to know what it takes to morph a sheet out of a button.

A sample project

We’ll set the ground with a really simple demo. We present a selected date in a Text view, which is contained into a navigation stack. The latter is necessary in order to show a toolbar, and place a button at the bottom bar. This button triggers the appearance of the sheet, which displays a date picker:

A few notes here:

  • We keep things as simple as possible with a Text view. Obviously, we can have any other view instead of that.
  • The placement of the button is intentionally at the bottom, so things look more natural in the beginning and be in accordance with the WWDC presentation. Soon we’ll see that this is not a requirement for the final transition.
  • Sheet content could be a different view, but for simplicity once again, it’s a @ViewBuilder method inside the same view. The date picker updates the value of the date state property whenever a different date is selected.

Running the app does nothing more than what we’re expecting; the button at the bottom bar makes the sheet appear, sliding from the bottom as we’ve known so far.

Enabling morphing

To enable the morphing effect, the first step is to declare a namespace.

A namespace allows SwiftUI to match a source view with a destination view during a transition, which, in our case, these are the toolbar button and the sheet. This matching is achieved with a unique identifier (we’ll see that right next), so SwiftUI can relate the two views and perform the Liquid Glass effect we’re asking for.

That said, we add the following at the top of the view:

Next, we apply the matchedTransitionSource(id:in:) modifier to the toolbar item that contains the button:

It’s really important to remember that the id argument has to be a unique value that identifies the transition. You can provide any value you want as long as it’s unique, but choosing something that describes the purpose of the effect would be probably a wise decision.

The second argument in the above modifier is the namespace that SwiftUI will use to match the transitioning views; the one we previously declared.

There’s one last step, to relate the sheet’s appearance with a navigation transition and the transition source we added in the previous step:

The zoom transition is built-in, and it’s given as argument to navigationTransition modifier. The zoom transition gets two arguments, the exact two we passed to the matchedTransitionSource; the same unique identifier, and the namespace.

These three additions that include declaring a namespace, applying the matchedTransitionSource modifier to the toolbar item and the navigationTransition with the zoom effect to the sheet’s content is all we need to enable the morphing effect.

Running the app again, we’ll see that the button is transformed into a sheet now. The opposite animation is performed on sheet dismissal:

Initiating animation from other places

Having a toolbar button at the bottom bar is not mandatory to make the morph effect work. In fact, the source button can be in the top bar too. For instance, let’s change the toolbar item placement from bottomBar to confirmationAction, keeping the rest of the setup unchanged:

When the button is tapped, the animation remains exactly the same:

The morph effect works even when originating from normal buttons that are not part of any toolbar. Let’s replace the simple Text view in our demo with a VStack that contains the Text view and a button the shows the date picker sheet:

See that the button is transformed into a sheet and back again:

Wrapping up

The morph effect is an eye-catching transition that does not require much effort to achieve. Declare a namespace, specify the transition source with a unique identifier, and set the navigation transition to the sheet’s content. Also, the source button does not have to be part of the bottom bar; we can place it whenever it makes sense for our app. However, be mindful with this effect. Sometimes, the old, traditional way to present sheets might serves the user experience better. It’s up to you to decide. Thanks for reading!

Stay Up To Date

Subscribe to my newsletter and get notifiied instantly when I post something new on SerialCoder.dev.

    We respect your privacy. Unsubscribe at any time.