How to Recreate the Dynamic Toolbar from Apple's Messages App in iOS 26
Your toolbar no longer has to be static... Add menus, change the top and bottom toolbar buttons on demand!
If you’re using the iOS 26 Beta on your iPhone, you might have noticed that the toolbar (both top and bottom) can become super dynamic. The best way to learn about the new UI is to check out Apple’s own apps and try to recreate them. So in this blog post, this is exactly what I try to do for the Messages app. Here is the fun result:
Let’s build it!
Keeping State
I won’t go into the exact implementation of how the messages list view will change based on state as this goes beyond the scope of the toolbar focus, but given the complexity of all the menu items and what should be shown to the user, etc, the first step is to create some way to store the state of the view.
I’m trying to use less ViewModels in SwiftUI, but this is one case where it would be a good idea as you dynamically have to track which state the app is in so that the right components are shown.
Since I didn’t implement the full functionality of the Messages app and simply focused on the toolbar items, I kept the state variables in the ContentView
:
Once again - I would pull this out into a ViewModel or a “Presenter” object that is observable where the logic can be managed more clearly.
Arranging the Toolbar by Position
When creating a ToolbarItem
, you can specify the placement. For example:
So it makes a lot of sense to organize your ToolbarItems by placement. Here is the full View with the toolbars arranged:
The Edit Button
Watch the Edit button in this recording:
When the Messages are in normal state, it says Edit. Then when the user clicks on Edit, they see a Menu. Once they select the “Select Messages” or “Edit Pins” menu item, the Edit button turns into a Checkmark done button.
Note that the final Edit option to select "Set Up Name & Photo” brings up another view as a full screen cover (without changing the Edit button), so I didn’t include it in here for the demo. That menu option would simply trigger the presentation of the new view.
So how do we manage this? Simply by presenting the correct leading button based on the EditState
of our view:
In normal EditState
, we can show an Edit button that is tied to the edit menu:
The resulting menu looks like this:
Clicking on each button option will simply reset the EditState
, which will trigger the appropriate UI changes. Note that withAnimation
is used to make the UI state transitions more smooth.
That’s it! The Edit button is simply a Menu with 3 buttons which trigger the observed view state changes.
Once the EditState
changes to .editing
or .editingPins
, the Done (checkmark) button will be displayed:
Note that it’s important to change the .buttonStyle
to .glassProminent
to get the default blue color. Otherwise, you can add a tint for a different color:
If the button style is not changed, the button would just be the normal transparent one with a glass effect.
The Filter Button
In the navigationBarTrailing
placement, we have the filter button. However, this button disappears when the view is in .editing
or .editingPins
EditState
:
Just like the Edit button, the filter button is also a menu of options, although it is a bit more custom:
It looks like this:
As the user clicks each button, the selectedFilter
state variable is changed, and the view updates based on the filtering.
The Bottom Bar
Just as we dynamically change the top navigation bar toolbar items based on EditState
, we can do the same for the bottom bar:
The normal tool bar is a search button with an edit button:
It looks like this:
However, when the user is in editing mode, then the editing-specific toolbar items are shown:
Which looks like this:
That’s it!
Conclusion
Making dynamically changing toolbar items - both on the top and bottom of your view is super simple. Simply include a way to track the state of your view and display the appropriate items depending on the state.
The bigger question is whether the constantly changing UI of different toolbar buttons will be confusing to the user… Given that Apple is adapting it so much in the Messages app and their other default apps, the users will be trained for this inside your app!
Awesome, pure and only native controls!