My note screen has two states:
-
View mode
The note is open, but not being edited.
A compact bottom toolbar is shown with 3 actions. -
Edit mode
When the user taps into the text editor and the keyboard appears, the toolbar:
-
moves up together with the keyboard
-
smoothly expands horizontally
-
reveals additional actions
-
looks like a transformation of the same toolbar, not a disappearance + replacement
I attached frame-by-frame screenshots of the transition.
What I want to achieve:
-
in view mode: small floating toolbar near the bottom
-
in edit mode: toolbar attached above keyboard, wider, with more items
-
smooth animated transition between these two layouts
My main question:
What is the correct SwiftUI approach to implement this kind of toolbar morphing animation?
I’m especially interested in:
-
whether this should be built as one toolbar view that changes layout, or as two separate toolbars with matchedGeometryEffect
-
how to correctly sync the animation with keyboard appearance
-
whether toolbar / safeAreaInset / keyboard toolbar APIs are enough for this, or if a custom overlay is the better approach
-
how to avoid jumpy layout updates when switching between states
A simplified version of the logic is:
struct NoteView: View {
@State private var isEditing = false
@State private var text = "Hello world"
var body: some View {
ZStack(alignment: .bottom) {
TextEditor(text: $text)
.onTapGesture {
isEditing = true
}
if isEditing {
ExpandedToolbar()
} else {
CompactToolbar()
}
}
.animation(.smooth, value: isEditing)
}
}
The problem is that a naive switch between two views does not produce the same effect as in Notes. It feels like a replacement, while I need a continuous morph:
Has anyone implemented something similar in pure SwiftUI?
What would be the cleanest architecture for this on iOS 26?
If needed, I can also share a minimal reproducible example.