TechnologiesSwiftUI

ToolbarContent protocol

iOSmacOStvOSwatchOSvisionOSiOS 14.0+✓ renders

Conforming types represent items that can be placed in various locations

How it works

ToolbarContent is the protocol you conform to when you want to define a reusable, self-contained group of toolbar items as its own type, rather than inlining them in a .toolbar closure. It plays the same role for toolbars that View plays for ordinary interface: a type that conforms to ToolbarContent declares a body built from toolbar primitives, which SwiftUI then composes into the bar. Reach for it when a toolbar grows beyond a couple of buttons, when you want to share the same set of controls across screens, or when you simply want to lift bar configuration out of a busy view body. In the example, MyToolbar is a standalone ToolbarContent type that the NavigationStack adopts by passing it to .toolbar.

  1. Conform a type to ToolbarContent

    Declaring struct MyToolbar: ToolbarContent creates a dedicated value whose sole job is to describe toolbar items. Unlike a View, this type does not draw a region of the screen; it contributes entries to a host's toolbar. Because it is an ordinary struct, it can hold stored properties, take initializer parameters, and be reused anywhere a toolbar is accepted.

  2. Provide a body of associated type ToolbarContent

    The protocol requires a single computed property, var body: some ToolbarContent. This mirrors View's body but its return type is toolbar content rather than a view. Inside it you list the items the type provides; here the body returns two ToolbarItem values that SwiftUI assembles into the finished bar.

  3. Populate the body with ToolbarItem

    ToolbarItem is the building block you place inside a ToolbarContent body, each wrapping a single control. In MyToolbar, one ToolbarItem holds a Button("Edit") and another holds a Button containing an Image(systemName: "square.and.pencil"). The view builder that produces the control runs inside the item's trailing closure.

  4. Position items with the placement parameter

    Each ToolbarItem(placement:) tells SwiftUI where in the bar the control belongs, letting the same ToolbarContent type adapt to different platforms and bar regions. The example sends the Edit button to .navigationBarLeading and the compose button to .primaryAction, so the system decides their concrete position within the navigation bar.

  5. Attach the type with the toolbar modifier

    A ToolbarContent type is installed by passing it to a view's .toolbar modifier, which is where the symbol plugs into the rest of the interface. Here .toolbar { MyToolbar() } hangs the items off the NavigationStack, so they render in the navigation bar alongside the .navigationTitle("Mail").

Try it — Change the second item's placement: .primaryAction to placement: .navigationBarLeading and watch the compose button jump to the leading edge next to Edit, showing how a ToolbarContent type's layout is driven entirely by each item's placement.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

ToolbarContent.swift
struct ToolbarContentDemo: View {
    var body: some View {
        NavigationStack {
            Text("Inbox")
                .padding()
                .navigationTitle("Mail")
                .toolbar {
                    MyToolbar()
                }
        }
    }
}

struct MyToolbar: ToolbarContent {
    var body: some ToolbarContent {
        ToolbarItem(placement: .navigationBarLeading) {
            Button("Edit") {}
        }
        ToolbarItem(placement: .primaryAction) {
            Button(action: {}) {
                Image(systemName: "square.and.pencil")
            }
        }
    }
}
Live preview
Inb… 9:41 Mail
Inb… 9:41 Mail
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →