Loading...
Loading...
Writes and reviews SwiftUI WidgetKit code for Home Screen, Lock Screen, StandBy, and watch widgets - timeline providers and reload policies, StaticConfiguration / AppIntentConfiguration, user-configurable widgets, widget families and sizing, accented/tinted rendering modes, interactive widgets and Controls (Control Center), Live Activities and the Dynamic Island, Smart Stack relevance, push-updated widgets, and visionOS / CarPlay / macOS surfaces. Use when building a widget extension, a timeline provider, a Lock Screen or accessory widget, a watch complication, an interactive button/toggle widget, a Control Center control, a Live Activity, or fixing a widget that won't update or render correctly in tinted mode.
npx skill4agent add n0an/widgets-agent-skill widgetsreferences/fundamentals.mdplaceholdersnapshottimelineWidgetCenterreferences/timeline-provider.mdStaticConfigurationAppIntentConfigurationWidgetConfigurationIntentreferences/configuration-and-intents.md.intentdefinitionPreviewProvider#Previewreferences/migration-and-deprecations.mdreferences/data-and-networking.mdWidgetFamilyViewThatFitsreferences/families-and-layout.mdwidgetLabelAccessoryWidgetBackgroundreferences/lock-screen-and-watch.mdwidgetRenderingModewidgetAccentablewidgetAccentedRenderingModereferences/rendering-modes-and-tinting.mdButton(intent:)Toggle(intent:)reloadTimelinesinvalidatableContentreferences/interactive-widgets.mdwidgetURLLinkonOpenURLOpenIntentreferences/deep-linking-and-navigation.mdcontentTransition.transitioninvalidatableContentreferences/animations-and-transitions.mdControlWidgetSetValueIntentControlCenterreferences/controls.mdActivityAttributesActivityConfigurationDynamicIslandsupplementalActivityFamiliesreferences/live-activities.mdTimelineEntryRelevancerelevance()WidgetRelevanceRelevanceConfigurationreferences/relevance-and-smart-stacks.mdconfigurationDisplayNamedescriptionreferences/design-and-gallery.md#Preview(as:)references/previews-and-testing.mdreferences/platforms.mdreferences/anti-patterns.mdreferences/fundamentals.mdreferences/worked-example.mdreferences/timeline-provider.mdTimelineProviderreferences/families-and-layout.mdreferences/previews-and-testing.md#Preview(as:)references/configuration-and-intents.mdAppIntentConfigurationWidgetConfigurationIntentreferences/timeline-provider.mdAppIntentTimelineProviderreferences/lock-screen-and-watch.mdwidgetLabelAccessoryWidgetBackgroundreferences/rendering-modes-and-tinting.mdreferences/rendering-modes-and-tinting.mdwidgetRenderingModewidgetAccentablewidgetAccentedRenderingModereferences/lock-screen-and-watch.mdcontainerBackgroundreferences/interactive-widgets.mdButton(intent:)Toggle(intent:)reloadTimelinesinvalidatableContentreferences/configuration-and-intents.mdisDiscoverable = falsereferences/controls.mdControlWidgetControlWidgetToggleSetValueIntentControlWidgetButtonAppIntentControlCenter.shared.reloadControlsreferences/interactive-widgets.mdreferences/live-activities.mdActivityAttributesContentStateActivityConfigurationDynamicIslandsupplementalActivityFamiliesreferences/interactive-widgets.mdLiveActivityIntentreferences/timeline-provider.mdreferences/relevance-and-smart-stacks.mdWidgetPushHandlerreferences/relevance-and-smart-stacks.mdTimelineEntryRelevancerelevance()WidgetRelevanceRelevanceConfigurationRelevantContextreferences/data-and-networking.mdasyncNSWidgetUsesLocationreferences/timeline-provider.mdreferences/deep-linking-and-navigation.mdwidgetURLLinkonOpenURLOpenIntentreferences/animations-and-transitions.mdcontentTransition(.numericText).transition.idinvalidatableContentreferences/migration-and-deprecations.mdCustomIntentMigratedAppIntent#availablereferences/design-and-gallery.mdreferences/platforms.mdsupportedMountingStyleswidgetTexturelevelOfDetailreferences/previews-and-testing.mdreferences/anti-patterns.mdreferences/anti-patterns.mdNo user configuration, fixed behavior?
-> StaticConfiguration(kind:provider:)
User picks parameters (account, city, repo)?
-> AppIntentConfiguration(kind:intent:provider:) + WidgetConfigurationIntent (iOS 17+)
Migrating an existing iOS 14-16 configurable widget?
-> WidgetConfigurationIntent + CustomIntentMigratedAppIntent (keep intentClassName)
-> or keep IntentConfiguration(kind:intent:provider:) with the legacy INIntent
Appears in the Smart Stack only when relevant (watchOS)?
-> RelevanceConfiguration(kind:provider:) (watchOS 26+)StaticConfiguration?
-> TimelineProvider (placeholder / getSnapshot / getTimeline, completion-based)
AppIntentConfiguration?
-> AppIntentTimelineProvider (placeholder / snapshot(for:in:) / timeline(for:in:), async, intent FIRST)
RelevanceConfiguration (watchOS)?
-> RelevanceEntriesProvider (placeholder / relevance() / entry(configuration:context:), one entry per config)Next update time is known (countdown ends, event starts)?
-> .after(date)
Entries cover a window and the next batch can be computed at the end?
-> .atEnd
Content only changes from interaction / push, never on a schedule?
-> .never (then reload via WidgetCenter from an intent, app, or push)Inside a widget or Live Activity, runs an action?
-> Button(intent:) with an AppIntent (iOS 17+)
Inside a widget, binary on/off?
-> Toggle(isOn:intent:) with an AppIntent (iOS 17+)
Inside a Control Center control, binary on/off?
-> ControlWidgetToggle(action:) with a SetValueIntent
Inside a Control Center control, runs an action / opens the app?
-> ControlWidgetButton(action:) with an AppIntent (or OpenIntent to launch)Glanceable data on a schedule, lives on Home/Lock Screen?
-> Widget (timeline)
Ongoing, time-bound event the user wants to watch live (delivery, game, workout)?
-> Live Activity (ActivityKit) - NOT a fast-reloading widget
A quick action or state toggle from Control Center / Lock Screen / Action button?
-> Control (ControlWidget)UserDefaults(suiteName:)ModelContainerUserDefaults.standardonTapGestureButton(intent:)Toggle(intent:)AppIntentLinkwidgetURL.containerBackground(for: .widget) { ... }ContainerBackgroundPlacement.widgetWidgetBackgroundPlacementplaceholder(in:)getSnapshotgetTimelinesnapshottimeline.redacted(reason: .placeholder)getSnapshotsnapshot(for:in:).after(date).atEnd.after.neverWidgetCenter.shared.reloadAllTimelines()TimelineReloadPolicy.after(_:)DateTimeIntervalWidgetCenter.shared.reloadTimelines(ofKind:)kindkindAppIntentConfigurationWidgetConfigurationIntentAppIntentTimelineProvidersnapshottimelineWidgetConfigurationIntentperform()@ParameterIntentConfigurationINIntent.intentdefinitionIntentTimelineProviderAppIntentConfigurationWidgetConfigurationIntentAppIntentTimelineProvider#availableCustomIntentMigratedAppIntentintentClassNameCLKComplicationWidgetMigrator#Preview(as:)PreviewProviderreferences/migration-and-deprecations.mdAsyncImagereferences/data-and-networking.md@Environment(\.widgetFamily)supportedFamiliesaccessoryCircularaccessoryRectangularaccessoryInlineaccessoryCorner@Environment(\.widgetRenderingMode).fullColor.accented.vibrantWidgetRenderingModeWidgetAccentedRenderingMode.accented.widgetAccentable().widgetAccentedRenderingMode(.desaturated / .accented / .accentedDesaturated / .fullColor).widgetAccentedRenderingMode(.desaturated).luminanceToAlpha().widgetAccentable()references/rendering-modes-and-tinting.md.containerBackground(for: .widget) { }containerBackgroundAppIntentWidgetCenter.shared.reloadTimelines(ofKind:)reloadAllTimelines()ControlCenter.shared.reloadControls(ofKind:)static let isDiscoverable = false.mainstatic var allowedExecutionTargets: ExecutionTargets { .main }.widgetKitExtensionControlWidgetControlWidgetToggleSetValueIntentvalue: BoolControlWidgetButtonAppIntentOpenIntentcontrolWidgetStatus(_:)controlWidgetStatusTextpreviewValuecurrentValueActivityAttributesContentState: Codable, HashableActivityConfigurationDynamicIslandActivity.request/update/endstaleDaterelevanceScoreActivityContent.initNSSupportsLiveActivitiesYESNSSupportsLiveActivitiesFrequentUpdatesActivity.pushToStartTokenPushTypechannelsymbolEffectText(_:style:)widgetAccentedRenderingModeWidgetPushHandlerRelevanceConfigurationsupportedMountingStyleswidgetTexturelevelOfDetailsystemExtraLargePortraitisDynamicIslandLimitedInWidthallowedExecutionTargets#Preview(as:)placeholder(in:)// Before
func placeholder(in context: Context) -> Entry {
Entry(date: .now, drinks: Store.shared.loadAllDrinks()) // blocks the render
}
// After
func placeholder(in context: Context) -> Entry {
Entry(date: .now, drinks: .sample) // synchronous stand-in; real data in getTimeline
}onTapGesture// Before
Image(systemName: "plus.circle").onTapGesture { addDrink() }
// After
Button(intent: AddDrinkIntent()) { Image(systemName: "plus.circle") }
// AddDrinkIntent.perform() writes to the App Group store, then:
// WidgetCenter.shared.reloadTimelines(ofKind: "CaffeineWidget")AppIntentreferences/fundamentals.mdWidgetBundleWidgetcontainerBackgroundkindreferences/timeline-provider.mdTimelineProviderAppIntentTimelineProviderTimelineEntryTimelineWidgetCenterTimelineEntryRelevancereferences/configuration-and-intents.mdStaticConfigurationAppIntentConfigurationWidgetConfigurationIntentrecommendations()references/migration-and-deprecations.md.intentdefinitionIntentConfigurationIntentTimelineProviderAppIntentTimelineProviderPreviewProvider#PreviewCustomIntentMigratedAppIntentreferences/data-and-networking.mdasyncURLSessionreferences/families-and-layout.mdWidgetFamilysupportedFamiliesViewThatFitsContainerRelativeShapereferences/lock-screen-and-watch.mdwidgetLabelAccessoryWidgetBackgroundcontainerBackgroundreferences/rendering-modes-and-tinting.mdwidgetRenderingMode.fullColor.accented.vibrantwidgetAccentablewidgetAccentedRenderingModereferences/interactive-widgets.mdButton(intent:)Toggle(intent:)@ParameterreloadTimelinesToggleStyleinvalidatableContentisDiscoverableallowedExecutionTargetsreferences/deep-linking-and-navigation.mdwidgetURLLinkonOpenURLwidgetURLkeylineTintOpenIntentreferences/animations-and-transitions.mdcontentTransition(.numericText).transition.idToggleinvalidatableContentsymbolEffectreferences/controls.mdControlWidgetStaticControlConfigurationAppIntentControlConfigurationControlWidgetToggleSetValueIntentControlWidgetButtonAppIntentOpenIntentControlCenterreferences/live-activities.mdActivityAttributesContentStateActivityConfigurationDynamicIslandActivity.request/update/endActivityContentsupplementalActivityFamiliesactivityFamilyLiveActivityIntentreferences/relevance-and-smart-stacks.mdTimelineEntryRelevancerelevance()WidgetRelevanceWidgetRelevanceAttributeRelevantContextRelevanceConfigurationRelevanceEntriesProviderWidgetPushHandlerreferences/design-and-gallery.mdconfigurationDisplayNamedescriptionreferences/previews-and-testing.md#Preview(as:)WidgetPreviewContextreferences/platforms.mdsupportedMountingStyleswidgetTexturelevelOfDetailsystemExtraLargePortraitreferences/worked-example.mdsystemMediumLinkMeshGradientcontentMarginsDisabledreferences/anti-patterns.mdContainerBackgroundPlacementpushToStartTokencontrolWidgetStatus