Skip to content

Custom Styles

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

Custom Styles

Create reusable looks by conforming to DialogStyle — the same idea as ButtonStyle / LabelStyle.

Example: gradient banner

struct GradientDialogStyle: DialogStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.passedContent
            .frame(maxWidth: 450, minHeight: 64)
            .background {
                RoundedRectangle(cornerRadius: 24)
                    .fill(
                        LinearGradient(
                            colors: [.blue, .purple],
                            startPoint: .leading,
                            endPoint: .trailing
                        )
                    )
            }
            .shadow(color: .blue.opacity(0.3), radius: 10, x: 0, y: 5)
    }
}

Expose a static member so it reads like the built-ins:

extension DialogStyle where Self == GradientDialogStyle {
    static var gradient: Self { GradientDialogStyle() }
}
.peekDialog(isPresented: $showDialog) {
    Text("Looks fancy")
        .foregroundStyle(.white)
        .padding()
        .dialogStyle(.gradient)
}

Example: style with a dismiss button

struct DismissableDialogStyle: DialogStyle {
    func makeBody(configuration: Configuration) -> some View {
        HStack {
            configuration.passedContent
            Spacer(minLength: 8)
            Button {
                configuration.onDismiss?()
            } label: {
                Image(systemName: "xmark.circle.fill")
                    .foregroundStyle(.secondary)
            }
            .buttonStyle(.plain)
        }
        .padding()
        .background {
            RoundedRectangle(cornerRadius: 20)
                .fill(.regularMaterial)
        }
    }
}

Tips

  • Prefer decorating passedContent rather than ignoring it — callers still pass their own text / icons.
  • Keep layout flexible: your style is shared; content height varies.
  • Apply .dialogStyle(...) inside the peekDialog closure. Outside does nothing — Common Mistakes.
  • For one-off looks, .dialogStyle(.plain) + modifiers on the content is often enough. Reach for a custom DialogStyle when you reuse the same chrome in several places.

← Back to Styling

Clone this wiki locally