Skip to content

Stacking

B.Cem edited this page Jul 28, 2026 · 1 revision

Stacking

iOS only. On other platforms use the single-dialog isPresented: / with: modifiers — see Common Mistakes.

Bind an array of Identifiable items and PeekDialog presents them as a queue of stacked notifications.

struct Notification: Identifiable {
    let id = UUID()
    let message: String
}

struct ContentView: View {
    @State private var notifications: [Notification] = []

    var body: some View {
        Button("Add") {
            notifications.append(Notification(message: "New notification"))
        }
        .peekDialog(items: $notifications, dismissDelay: .medium) { notification in
            Text(notification.message)
                .padding()
                .dialogStyle(.plain)
        }
    }
}

Behavior

  • Up to two dialogs are visible at once; the rest wait behind them.
  • Only the front dialog runs its dismissDelay. When it leaves, the next one moves forward and starts its own timer.
  • Appending to the array enqueues a new dialog; removing an item (or letting it auto-dismiss) advances the queue.
  • dismissDelay defaults to .short for the stacked modifier.

Spacing

stackOffset controls the vertical gap between the peeking cards (default 12 points):

.peekDialog(items: $notifications, dismissDelay: .medium, stackOffset: 16) { notification in
    /* ... */
}

Dismissal callback

onDismiss receives each dismissed item:

.peekDialog(items: $notifications, onDismiss: { item in
    print("dismissed \(item.id)")
}) { notification in
    Text(notification.message).padding()
}

Clone this wiki locally