TechnologiesSwiftUI

WidgetConfiguration protocol

iOSmacOStvOSwatchOSvisionOS✓ renders

A type that describes a widget's content.

How it works

WidgetConfiguration is the protocol that describes a widget's behavior and presentation — it tells WidgetKit what content a widget shows, what triggers updates, and which contexts and families the widget supports. You return a value conforming to it from the body of your Widget, pairing a kind identifier and a provider with the SwiftUI view that draws each entry, such as the step-count layout built here from Label, Text, and a RoundedRectangle background. Reach for it whenever you define a home-screen, lock-screen, or StandBy widget and need to wire timeline data to a view. You rarely conform to it directly; instead you compose one of the concrete configuration types and refine it with the protocol's modifiers.

  1. Return a WidgetConfiguration from the widget's body

    A type conforming to Widget produces exactly one WidgetConfiguration from its body property, declared as some WidgetConfiguration. That returned value bundles together the widget's identity, its data source, and the view to render — the view here being WidgetConfigurationDemo, whose VStack of Label and Text is the content WidgetKit places in each timeline entry.

  2. Choose a concrete configuration type

    You don't implement WidgetConfiguration yourself; you instantiate one of its conforming types. StaticConfiguration drives a widget from a timeline provider alone, while AppIntentConfiguration adds user-editable parameters. Both take a kind string and a provider, and return your content view — the same body shown in WidgetConfigurationDemo.

  3. Restrict supported families with supportedFamilies(_:)

    The supportedFamilies(_:) modifier narrows which WidgetFamily sizes the system may offer, such as .systemSmall or .accessoryRectangular. Because the demo content is laid out in a fixed frame(width: 150, height: 150), you would constrain the configuration to a small family so the system never asks it to fill a size its layout can't accommodate.

  4. Add chrome and metadata modifiers

    WidgetConfiguration exposes modifiers that adjust the surrounding container rather than the entry view: configurationDisplayName(_:) and description(_:) label the widget in the gallery, and containerBackgroundRemovable(_:) and contentMarginsDisabled() control padding and the system background. These wrap the configuration value, leaving the inner .background(.quaternary, in: RoundedRectangle(cornerRadius: 22)) of WidgetConfigurationDemo untouched.

  5. Compose configurations with WidgetBundle

    Each WidgetConfiguration represents a single widget kind. To ship several widgets from one extension, you list multiple configurations inside a WidgetBundle, where every entry is its own configuration paired with a view like WidgetConfigurationDemo.

Try it — Wrap the demo's content in a StaticConfiguration and chain .supportedFamilies([.systemSmall, .systemMedium]), then remove .systemMedium to watch the system stop offering the wider size for this widget.

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.

WidgetConfiguration.swift
struct WidgetConfigurationDemo: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Label("Steps", systemImage: "figure.walk")
                .font(.caption)
                .foregroundStyle(.secondary)
            Text("8,420")
                .font(.title.bold())
            Text("Goal: 10,000")
                .font(.caption2)
                .foregroundStyle(.tint)
        }
        .frame(width: 150, height: 150, alignment: .topLeading)
        .padding()
        .background(.quaternary, in: RoundedRectangle(cornerRadius: 22))
        .padding()
    }
}
Live preview
Steps 8,420 Goal: 10,000
Steps 8,420 Goal: 10,000
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →