{"id":"7d68c4cc-fe7e-478e-868e-6da69980b910","shortId":"nZBCqD","kind":"skill","title":"widgetkit","tagline":"Implement, review, or improve widgets, Live Activities, and controls using WidgetKit and ActivityKit. Use when building home screen, Lock Screen, or StandBy widgets with timeline providers; when creating interactive widgets with Button/Toggle and AppIntent actions; when adding Li","description":"# WidgetKit and ActivityKit\n\nBuild home screen widgets, Lock Screen widgets, Live Activities, Dynamic Island\npresentations, Control Center controls, and StandBy surfaces for iOS 26+.\n\nSee [references/widgetkit-advanced.md](references/widgetkit-advanced.md) for timeline strategies, push-based\nupdates, Xcode setup, and advanced patterns.\n\n## Contents\n\n- [Workflow](#workflow)\n- [Widget Protocol and WidgetBundle](#widget-protocol-and-widgetbundle)\n- [Configuration Types](#configuration-types)\n- [TimelineProvider](#timelineprovider)\n- [AppIntentTimelineProvider](#appintenttimelineprovider)\n- [Widget Families](#widget-families)\n- [Interactive Widgets (iOS 17+)](#interactive-widgets-ios-17)\n- [Live Activities and Dynamic Island](#live-activities-and-dynamic-island)\n- [Control Center Widgets (iOS 18+)](#control-center-widgets-ios-18)\n- [Lock Screen Widgets](#lock-screen-widgets)\n- [StandBy Mode](#standby-mode)\n- [Design Patterns](#design-patterns)\n- [iOS 26 Additions](#ios-26-additions)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Workflow\n\n### 1. Create a new widget\n\n1. Add a Widget Extension target in Xcode (File > New > Target > Widget Extension).\n2. Enable App Groups for shared data between the app and widget extension.\n3. Define a `TimelineEntry` struct with a `date` property and display data.\n4. Implement a `TimelineProvider` (static) or `AppIntentTimelineProvider` (configurable).\n5. Build the widget view using SwiftUI, adapting layout per `WidgetFamily`.\n6. Declare the `Widget` conforming struct with a configuration and supported families.\n7. Register all widgets in a `WidgetBundle` annotated with `@main`.\n\n### 2. Add a Live Activity\n\n1. Define an `ActivityAttributes` struct with a nested `ContentState`.\n2. Add `NSSupportsLiveActivities = YES` to the app's Info.plist.\n3. Create an `ActivityConfiguration` in the widget bundle with Lock Screen content\n   and Dynamic Island closures.\n4. Start the activity with `Activity.request(attributes:content:pushType:)`.\n5. Update with `activity.update(_:)` and end with `activity.end(_:dismissalPolicy:)`.\n\n### 3. Add a Control Center control\n\n1. Define an `AppIntent` for the action.\n2. Create a `ControlWidgetButton` or `ControlWidgetToggle` in the widget bundle.\n3. Use `StaticControlConfiguration` or `AppIntentControlConfiguration`.\n\n### 4. Review existing widget code\n\nRun through the Review Checklist at the end of this document.\n\n## Widget Protocol and WidgetBundle\n\n### Widget\n\nEvery widget conforms to the `Widget` protocol and returns a `WidgetConfiguration`\nfrom its `body`.\n\n```swift\nstruct OrderStatusWidget: Widget {\n    let kind: String = \"OrderStatusWidget\"\n\n    var body: some WidgetConfiguration {\n        StaticConfiguration(kind: kind, provider: OrderProvider()) { entry in\n            OrderWidgetView(entry: entry)\n        }\n        .configurationDisplayName(\"Order Status\")\n        .description(\"Track your current order.\")\n        .supportedFamilies([.systemSmall, .systemMedium])\n    }\n}\n```\n\n### WidgetBundle\n\nUse `WidgetBundle` to expose multiple widgets from a single extension.\n\n```swift\n@main\nstruct MyAppWidgets: WidgetBundle {\n    var body: some Widget {\n        OrderStatusWidget()\n        FavoritesWidget()\n        DeliveryActivityWidget()   // Live Activity\n        QuickActionControl()       // Control Center\n    }\n}\n```\n\n## Configuration Types\n\nUse `StaticConfiguration` for non-configurable widgets. Use `AppIntentConfiguration`\n(recommended) for configurable widgets paired with `AppIntentTimelineProvider`.\n\n```swift\n// Static\nStaticConfiguration(kind: \"MyWidget\", provider: MyProvider()) { entry in\n    MyWidgetView(entry: entry)\n}\n// Configurable\nAppIntentConfiguration(kind: \"ConfigWidget\", intent: SelectCategoryIntent.self,\n                       provider: CategoryProvider()) { entry in\n    CategoryWidgetView(entry: entry)\n}\n```\n\n### Shared Modifiers\n\n| Modifier | Purpose |\n|---|---|\n| `.configurationDisplayName(_:)` | Name shown in the widget gallery |\n| `.description(_:)` | Description shown in the widget gallery |\n| `.supportedFamilies(_:)` | Array of `WidgetFamily` values |\n| `.supplementalActivityFamilies(_:)` | Live Activity sizes (`.small`, `.medium`) |\n\n## TimelineProvider\n\nFor static (non-configurable) widgets. Uses completion handlers. Three required methods:\n\n```swift\nstruct WeatherProvider: TimelineProvider {\n    typealias Entry = WeatherEntry\n\n    func placeholder(in context: Context) -> WeatherEntry {\n        WeatherEntry(date: .now, temperature: 72, condition: \"Sunny\")\n    }\n\n    func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> Void) {\n        let entry = context.isPreview\n            ? placeholder(in: context)\n            : WeatherEntry(date: .now, temperature: currentTemp, condition: currentCondition)\n        completion(entry)\n    }\n\n    func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> Void) {\n        Task {\n            let weather = await WeatherService.shared.fetch()\n            let entry = WeatherEntry(date: .now, temperature: weather.temp, condition: weather.condition)\n            let nextUpdate = Calendar.current.date(byAdding: .hour, value: 1, to: .now)!\n            completion(Timeline(entries: [entry], policy: .after(nextUpdate)))\n        }\n    }\n}\n```\n\n## AppIntentTimelineProvider\n\nFor configurable widgets. Uses async/await natively. Receives user intent configuration.\n\n```swift\nstruct CategoryProvider: AppIntentTimelineProvider {\n    typealias Entry = CategoryEntry\n    typealias Intent = SelectCategoryIntent\n\n    func placeholder(in context: Context) -> CategoryEntry {\n        CategoryEntry(date: .now, categoryName: \"Sample\", items: [])\n    }\n\n    func snapshot(for config: SelectCategoryIntent, in context: Context) async -> CategoryEntry {\n        let items = await DataStore.shared.items(for: config.category)\n        return CategoryEntry(date: .now, categoryName: config.category.name, items: items)\n    }\n\n    func timeline(for config: SelectCategoryIntent, in context: Context) async -> Timeline<CategoryEntry> {\n        let items = await DataStore.shared.items(for: config.category)\n        let entry = CategoryEntry(date: .now, categoryName: config.category.name, items: items)\n        return Timeline(entries: [entry], policy: .atEnd)\n    }\n}\n```\n\n## Widget Families\n\n| Family | Platform |\n|---|---|\n| `.systemSmall` | iOS, iPadOS, macOS, CarPlay (iOS 26+) |\n| `.systemMedium` | iOS, iPadOS, macOS |\n| `.systemLarge` | iOS, iPadOS, macOS |\n| `.systemExtraLarge` | iPadOS only |\n| `.accessoryCircular` | iOS, watchOS |\n| `.accessoryRectangular` | iOS, watchOS |\n| `.accessoryInline` | iOS, watchOS |\n| `.accessoryCorner` | watchOS only |\n\nAdapt layout per family using `@Environment(\\.widgetFamily)`:\n\n```swift\n@Environment(\\.widgetFamily) var family\n\nvar body: some View {\n    switch family {\n    case .systemSmall: CompactView(entry: entry)\n    case .systemMedium: DetailedView(entry: entry)\n    case .accessoryCircular: CircularView(entry: entry)\n    default: FullView(entry: entry)\n    }\n}\n```\n\n## Interactive Widgets (iOS 17+)\n\nUse `Button` and `Toggle` with `AppIntent` conforming types to perform actions\ndirectly from a widget without launching the app.\n\n```swift\nstruct ToggleFavoriteIntent: AppIntent {\n    static var title: LocalizedStringResource = \"Toggle Favorite\"\n    @Parameter(title: \"Item ID\") var itemID: String\n\n    func perform() async throws -> some IntentResult {\n        await DataStore.shared.toggleFavorite(itemID)\n        return .result()\n    }\n}\n\nstruct InteractiveWidgetView: View {\n    let entry: FavoriteEntry\n    var body: some View {\n        HStack {\n            Text(entry.itemName)\n            Spacer()\n            Button(intent: ToggleFavoriteIntent(itemID: entry.itemID)) {\n                Image(systemName: entry.isFavorite ? \"star.fill\" : \"star\")\n            }\n        }\n        .padding()\n    }\n}\n```\n\n## Live Activities and Dynamic Island\n\n### ActivityAttributes\n\nDefine the static and dynamic data model.\n\n```swift\nstruct DeliveryAttributes: ActivityAttributes {\n    struct ContentState: Codable, Hashable {\n        var driverName: String\n        var estimatedDeliveryTime: ClosedRange<Date>\n        var currentStep: DeliveryStep\n    }\n\n    var orderNumber: Int\n    var restaurantName: String\n}\n```\n\n### ActivityConfiguration\n\nProvide Lock Screen content and Dynamic Island closures in the widget bundle.\n\n```swift\nstruct DeliveryActivityWidget: Widget {\n    var body: some WidgetConfiguration {\n        ActivityConfiguration(for: DeliveryAttributes.self) { context in\n            VStack(alignment: .leading) {\n                Text(context.attributes.restaurantName).font(.headline)\n                HStack {\n                    Text(\"Driver: \\(context.state.driverName)\")\n                    Spacer()\n                    Text(timerInterval: context.state.estimatedDeliveryTime, countsDown: true)\n                }\n            }\n            .padding()\n        } dynamicIsland: { context in\n            DynamicIsland {\n                DynamicIslandExpandedRegion(.leading) {\n                    Image(systemName: \"box.truck.fill\").font(.title2)\n                }\n                DynamicIslandExpandedRegion(.trailing) {\n                    Text(timerInterval: context.state.estimatedDeliveryTime, countsDown: true)\n                        .font(.caption)\n                }\n                DynamicIslandExpandedRegion(.center) {\n                    Text(context.attributes.restaurantName).font(.headline)\n                }\n                DynamicIslandExpandedRegion(.bottom) {\n                    HStack {\n                        ForEach(DeliveryStep.allCases, id: \\.self) { step in\n                            Image(systemName: step.icon)\n                                .foregroundStyle(step <= context.state.currentStep ? .primary : .tertiary)\n                        }\n                    }\n                }\n            } compactLeading: {\n                Image(systemName: \"box.truck.fill\")\n            } compactTrailing: {\n                Text(timerInterval: context.state.estimatedDeliveryTime, countsDown: true)\n                    .frame(width: 40).monospacedDigit()\n            } minimal: {\n                Image(systemName: \"box.truck.fill\")\n            }\n        }\n    }\n}\n```\n\n### Dynamic Island Regions\n\n| Region | Position |\n|---|---|\n| `.leading` | Left of the TrueDepth camera; wraps below |\n| `.trailing` | Right of the TrueDepth camera; wraps below |\n| `.center` | Directly below the camera |\n| `.bottom` | Below all other regions |\n\n### Starting, Updating, and Ending\n\n```swift\nlet attributes = DeliveryAttributes(orderNumber: 123, restaurantName: \"Pizza Place\")\nlet state = DeliveryAttributes.ContentState(\n    driverName: \"Alex\",\n    estimatedDeliveryTime: Date()...Date().addingTimeInterval(1800),\n    currentStep: .preparing\n)\nlet content = ActivityContent(state: state, staleDate: nil, relevanceScore: 75)\nlet activity = try Activity.request(attributes: attributes, content: content, pushType: .token)\n\nlet updated = ActivityContent(state: newState, staleDate: nil, relevanceScore: 90)\nawait activity.update(updated)\n\nlet final = ActivityContent(state: finalState, staleDate: nil, relevanceScore: 0)\nawait activity.end(final, dismissalPolicy: .after(.now.addingTimeInterval(3600)))\n```\n\n## Control Center Widgets (iOS 18+)\n\n```swift\n// Button control\nstruct OpenCameraControl: ControlWidget {\n    var body: some ControlWidgetConfiguration {\n        StaticControlConfiguration(kind: \"OpenCamera\") {\n            ControlWidgetButton(action: OpenCameraIntent()) {\n                Label(\"Camera\", systemImage: \"camera.fill\")\n            }\n        }\n        .displayName(\"Open Camera\")\n    }\n}\n\n// Toggle control with value provider\nstruct FlashlightControl: ControlWidget {\n    var body: some ControlWidgetConfiguration {\n        StaticControlConfiguration(kind: \"Flashlight\", provider: FlashlightValueProvider()) { value in\n            ControlWidgetToggle(isOn: value, action: ToggleFlashlightIntent()) {\n                Label(\"Flashlight\", systemImage: value ? \"flashlight.on.fill\" : \"flashlight.off.fill\")\n            }\n        }\n        .displayName(\"Flashlight\")\n    }\n}\n```\n\n## Lock Screen Widgets\n\nUse accessory families and `AccessoryWidgetBackground`.\n\n```swift\nstruct StepsWidget: Widget {\n    let kind = \"StepsWidget\"\n    var body: some WidgetConfiguration {\n        StaticConfiguration(kind: kind, provider: StepsProvider()) { entry in\n            ZStack {\n                AccessoryWidgetBackground()\n                VStack {\n                    Image(systemName: \"figure.walk\")\n                    Text(\"\\(entry.stepCount)\").font(.headline)\n                }\n            }\n        }\n        .supportedFamilies([.accessoryCircular, .accessoryRectangular, .accessoryInline])\n    }\n}\n```\n\n## StandBy Mode\n\n`.systemSmall` widgets automatically appear in StandBy (iPhone on charger in\nlandscape). Use `@Environment(\\.widgetLocation)` for conditional rendering:\n\n```swift\n@Environment(\\.widgetLocation) var location\n// location == .standBy, .homeScreen, .lockScreen, .carPlay, etc.\n```\n\n## Design Patterns\n\n- **Prefer `Gauge` over manual arcs.** Use `.gaugeStyle(.accessoryCircular)` for\n  Lock Screen circular widgets and `.linearCapacity` for home screen capacity bars.\n  The system handles styling, accessibility, and rendering-mode adaptation.\n- **Use `.containerBackground(_:for: .widget)`** (iOS 17+) for widget backgrounds\n  instead of padding and background modifiers.\n- **Use `Canvas` for dense visualizations** like sparklines or mini bar charts.\n  The lack of per-element accessibility is acceptable since the entire widget\n  surface is a single tap target.\n- **Match timeline refresh to data granularity.** Apple budgets\n  [40–70 refreshes per day](https://sosumi.ai/documentation/widgetkit/keeping-a-widget-up-to-date)\n  with entries at least 5 minutes apart. Use `Text(timerInterval:countsDown:)`\n  for live countdowns instead of burning timeline entries.\n\nSee [references/widgetkit-advanced.md](references/widgetkit-advanced.md) for\ncode examples and detailed guidance on each pattern.\n\n## iOS 26 Additions\n\n### Liquid Glass Support\n\nAdapt widgets to the Liquid Glass visual style using `WidgetAccentedRenderingMode`.\n\n| Mode | Description |\n|---|---|\n| `.accented` | Accented rendering for Liquid Glass |\n| `.accentedDesaturated` | Accented with desaturation |\n| `.desaturated` | Fully desaturated |\n| `.fullColor` | Full-color rendering |\n\n### WidgetPushHandler\n\nEnable push-based timeline reloads without scheduled polling.\n\n```swift\nstruct MyWidgetPushHandler: WidgetPushHandler {\n    func pushTokenDidChange(_ pushInfo: WidgetPushInfo, widgets: [WidgetInfo]) {\n        let tokenString = pushInfo.token.map { String(format: \"%02x\", $0) }.joined()\n        // Send tokenString to your server\n    }\n}\n```\n\n### CarPlay Widgets\n\n`.systemSmall` widgets render in CarPlay on iOS 26+. Ensure small widget layouts\nare legible at a glance for driver safety.\n\n## Common Mistakes\n\n1. **Using IntentTimelineProvider instead of AppIntentTimelineProvider.**\n   `IntentTimelineProvider` is the older SiriKit Intents-based provider. Prefer\n   `AppIntentTimelineProvider` with the App Intents framework for new widgets.\n\n2. **Exceeding the refresh budget.** Widgets have a daily refresh limit. Do not\n   call `WidgetCenter.shared.reloadTimelines(ofKind:)` on every minor data change.\n   Batch updates and use appropriate `TimelineReloadPolicy` values.\n\n3. **Forgetting App Groups for shared data.** The widget extension runs in a\n   separate process. Use `UserDefaults(suiteName:)` or a shared App Group\n   container for data the widget reads.\n\n4. **Performing network calls in placeholder().** `placeholder(in:)` must return\n   synchronously with sample data. Use `getTimeline` or `timeline(for:in:)` for\n   async work.\n\n5. **Missing NSSupportsLiveActivities Info.plist key.** Live Activities will not\n   start without `NSSupportsLiveActivities = YES` in the host app's Info.plist.\n\n6. **Using the deprecated contentState API.** Use `ActivityContent` for all\n   `Activity.request`, `update`, and `end` calls. The `contentState`-based\n   methods are deprecated.\n\n7. **Not handling the stale state.** Check `context.isStale` in Live Activity\n   views and show a fallback (e.g., \"Updating...\") when content is outdated.\n\n8. **Putting heavy logic in the widget view.** Widget views are rendered in a\n   size-limited process. Pre-compute data in the timeline provider and pass\n   display-ready values through the entry.\n\n9. **Ignoring accessory rendering modes.** Lock Screen widgets render in\n   `.vibrant` or `.accented` mode, not `.fullColor`. Test with\n   `@Environment(\\.widgetRenderingMode)` and avoid relying on color alone.\n\n10. **Not testing on device.** Dynamic Island and StandBy behavior differ\n    significantly from Simulator. Always verify on physical hardware.\n\n## Review Checklist\n\n- [ ] Widget extension target has App Groups entitlement matching the main app\n- [ ] `@main` is on the `WidgetBundle`, not on individual widgets\n- [ ] `placeholder(in:)` returns synchronously; `getSnapshot`/`snapshot(for:in:)` fast when `isPreview`\n- [ ] Timeline reload policy matches update frequency; `reloadTimelines(ofKind:)` only on data change\n- [ ] Layout adapts per `WidgetFamily`; accessory widgets tested in `.vibrant` mode\n- [ ] Interactive widgets use `AppIntent` with `Button`/`Toggle` only\n- [ ] Live Activity: `NSSupportsLiveActivities = YES`; `ActivityContent` used; Dynamic Island closures implemented\n- [ ] `activity.end(_:dismissalPolicy:)` called; controls use `StaticControlConfiguration`/`AppIntentControlConfiguration`\n- [ ] Timeline entries and Intent types are Sendable; tested on device\n\n## References\n\n- Advanced guide: [references/widgetkit-advanced.md](references/widgetkit-advanced.md)\n- Apple docs: [WidgetKit](https://sosumi.ai/documentation/widgetkit) | [ActivityKit](https://sosumi.ai/documentation/activitykit) | [Keeping a widget up to date](https://sosumi.ai/documentation/widgetkit/keeping-a-widget-up-to-date)","tags":["widgetkit","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-widgetkit","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/widgetkit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 599 github stars · SKILL.md body (18,132 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:46.644Z","embedding":null,"createdAt":"2026-04-18T20:33:35.318Z","updatedAt":"2026-05-18T18:53:46.644Z","lastSeenAt":"2026-05-18T18:53:46.644Z","tsv":"'-26':157 '/documentation/activitykit)':1782 '/documentation/widgetkit)':1778 '/documentation/widgetkit/keeping-a-widget-up-to-date)':1306,1791 '0':1076,1400 '02x':1399 '1':172,177,261,319,595,1431 '10':1659 '123':1021 '17':108,113,767,1251 '18':129,135,1088 '1800':1034 '2':190,256,270,326,1456 '26':63,154,703,1339,1416 '3':203,279,313,336,1484 '3600':1083 '4':215,295,341,1513 '40':975,1299 '5':223,304,1311,1536 '6':234,1555 '7':246,1576 '70':1300 '72':539 '75':1045 '8':1598 '9':1633 '90':1064 'accent':1356,1357,1363,1645 'accenteddesatur':1362 'accept':1280 'access':1240,1278 'accessori':1148,1635,1727 'accessorycircular':715,756,1181,1223 'accessorycorn':724 'accessoryinlin':721,1183 'accessoryrectangular':718,1182 'accessorywidgetbackground':1151,1171 'action':36,325,778,1103,1134 'activ':8,51,115,121,260,298,433,505,841,1047,1542,1586,1742 'activity.end':311,1078,1751 'activity.request':300,1049,1565 'activity.update':307,1066 'activityattribut':264,845,856 'activityconfigur':282,876,897 'activitycont':1039,1058,1070,1562,1745 'activitykit':14,42,1779 'ad':38 'adapt':230,727,1245,1344,1724 'add':178,257,271,314 'addingtimeinterv':1033 'addit':155,158,1340 'advanc':77,1769 'alex':1029 'align':903 'alon':1658 'alway':1673 'annot':253 'apart':1313 'api':1560 'app':192,199,276,786,1450,1486,1505,1552,1684,1690 'appear':1189 'appint':35,322,773,790,1736 'appintentconfigur':447,468 'appintentcontrolconfigur':340,1757 'appintenttimelineprovid':98,99,221,454,605,619,1436,1447 'appl':1297,1773 'appropri':1481 'arc':1220 'array':499 'async':646,670,806,1534 'async/await':610 'atend':692 'attribut':301,1018,1050,1051 'automat':1188 'avoid':1654 'await':578,650,674,810,1065,1077 'background':1254,1259 'bar':1235,1270 'base':72,1378,1444,1572 'batch':1477 'behavior':1668 'bodi':375,385,426,740,822,894,1096,1121,1160 'bottom':947,1007 'box.truck.fill':928,966,980 'budget':1298,1460 'build':17,43,224 'bundl':286,335,888 'burn':1323 'button':769,829,1090,1738 'button/toggle':33 'byad':592 'calendar.current.date':591 'call':1469,1516,1569,1753 'camera':991,999,1006,1106,1111 'camera.fill':1108 'canva':1262 'capac':1234 'caption':939 'carplay':701,1212,1407,1413 'case':745,750,755 'categoryentri':622,631,632,647,655,680 'categorynam':635,658,683 'categoryprovid':474,618 'categorywidgetview':477 'center':56,126,132,317,436,941,1002,1085 'chang':1476,1722 'charger':1194 'chart':1271 'check':1582 'checklist':165,168,350,1679 'circular':1227 'circularview':757 'closedrang':866 'closur':294,884,1749 'codabl':859 'code':345,1330 'color':1372,1657 'common':159,162,1429 'common-mistak':161 'compactlead':963 'compacttrail':967 'compactview':747 'complet':517,547,564,571,598 'comput':1618 'condit':540,562,587,1201 'config':641,665 'config.category':653,677 'config.category.name':659,684 'configur':91,94,222,242,437,444,450,467,514,607,615 'configuration-typ':93 'configurationdisplaynam':398,484 'configwidget':470 'conform':238,364,774 'contain':1507 'containerbackground':1247 'content':79,290,302,880,1038,1052,1053,1595 'contentst':269,858,1559,1571 'context':532,533,545,546,556,569,570,629,630,644,645,668,669,900,921 'context.attributes.restaurantname':906,943 'context.ispreview':553 'context.isstale':1583 'context.state.currentstep':960 'context.state.drivername':912 'context.state.estimateddeliverytime':916,935,970 'control':10,55,57,125,131,316,318,435,1084,1091,1113,1754 'control-center-widgets-io':130 'controlwidget':1094,1119 'controlwidgetbutton':329,1102 'controlwidgetconfigur':1098,1123 'controlwidgettoggl':331,1131 'countdown':1320 'countsdown':917,936,971,1317 'creat':29,173,280,327 'current':404 'currentcondit':563 'currentstep':868,1035 'currenttemp':561 'daili':1464 'data':196,214,851,1295,1475,1490,1509,1526,1619,1721 'datastore.shared.items':651,675 'datastore.shared.togglefavorite':811 'date':210,536,558,583,633,656,681,1031,1032,1788 'day':1303 'declar':235 'default':760 'defin':204,262,320,846 'deliveryactivitywidget':431,891 'deliveryattribut':855,1019 'deliveryattributes.contentstate':1027 'deliveryattributes.self':899 'deliverystep':869 'deliverystep.allcases':950 'dens':1264 'deprec':1558,1575 'desatur':1365,1366,1368 'descript':401,491,492,1355 'design':148,151,1214 'design-pattern':150 'detail':1333 'detailedview':752 'devic':1663,1767 'differ':1669 'direct':779,1003 'dismissalpolici':312,1080,1752 'display':213,1627 'display-readi':1626 'displaynam':1109,1142 'doc':1774 'document':356 'driver':911,1427 'drivernam':862,1028 'dynam':52,117,123,292,843,850,882,981,1664,1747 'dynamicisland':920,923 'dynamicislandexpandedregion':924,931,940,946 'e.g':1592 'element':1277 'enabl':191,1375 'end':309,353,1015,1568 'ensur':1417 'entir':1283 'entitl':1686 'entri':393,396,397,462,465,466,475,478,479,527,552,565,581,600,601,621,679,689,690,748,749,753,754,758,759,762,763,819,1168,1308,1325,1632,1759 'entry.isfavorite':836 'entry.itemid':833 'entry.itemname':827 'entry.stepcount':1177 'environ':732,735,1198,1204,1651 'escap':548,572 'estimateddeliverytim':865,1030 'etc':1213 'everi':362,1473 'exampl':1331 'exceed':1457 'exist':343 'expos':413 'extens':181,189,202,419,1493,1681 'fallback':1591 'famili':101,104,245,694,695,730,738,744,1149 'fast':1708 'favorit':796 'favoriteentri':820 'favoriteswidget':430 'figure.walk':1175 'file':185 'final':1069,1079 'finalst':1072 'flashlight':1126,1137,1143 'flashlight.off.fill':1141 'flashlight.on.fill':1140 'flashlightcontrol':1118 'flashlightvalueprovid':1128 'font':907,929,938,944,1178 'foreach':949 'foregroundstyl':958 'forget':1485 'format':1398 'frame':973 'framework':1452 'frequenc':1716 'full':1371 'full-color':1370 'fullcolor':1369,1648 'fulli':1367 'fullview':761 'func':529,542,566,626,638,662,804,1388 'galleri':490,497 'gaug':1217 'gaugestyl':1222 'getsnapshot':543,1704 'gettimelin':567,1528 'glanc':1425 'glass':1342,1349,1361 'granular':1296 'group':193,1487,1506,1685 'guid':1770 'guidanc':1334 'handl':1238,1578 'handler':518 'hardwar':1677 'hashabl':860 'headlin':908,945,1179 'heavi':1600 'home':18,44,1232 'homescreen':1210 'host':1551 'hour':593 'hstack':825,909,948 'id':800,951 'ignor':1634 'imag':834,926,955,964,978,1173 'implement':2,216,1750 'improv':5 'individu':1698 'info.plist':278,1539,1554 'instead':1255,1321,1434 'int':872 'intent':471,614,624,830,1443,1451,1761 'intentresult':809 'intents-bas':1442 'intenttimelineprovid':1433,1437 'interact':30,105,110,764,1733 'interactive-widgets-io':109 'interactivewidgetview':816 'io':62,107,112,128,134,153,156,698,702,705,709,716,719,722,766,1087,1250,1338,1415 'ipado':699,706,710,713 'iphon':1192 'island':53,118,124,293,844,883,982,1665,1748 'ison':1132 'ispreview':1710 'item':637,649,660,661,673,685,686,799 'itemid':802,812,832 'join':1401 'keep':1783 'key':1540 'kind':381,389,390,458,469,1100,1125,1157,1164,1165 'label':1105,1136 'lack':1273 'landscap':1196 'launch':784 'layout':231,728,1420,1723 'lead':904,925,986 'least':1310 'left':987 'legibl':1422 'let':380,551,576,580,589,648,672,678,818,1017,1025,1037,1046,1056,1068,1156,1394 'li':39 'like':1266 'limit':1466,1614 'linearcapac':1230 'liquid':1341,1348,1360 'live':7,50,114,120,259,432,504,840,1319,1541,1585,1741 'live-activities-and-dynamic-island':119 'localizedstringresourc':794 'locat':1207,1208 'lock':20,47,136,140,288,878,1144,1225,1638 'lock-screen-widget':139 'lockscreen':1211 'logic':1601 'maco':700,707,711 'main':255,421,1689,1691 'manual':1219 'match':1291,1687,1714 'medium':508 'method':521,1573 'mini':1269 'minim':977 'minor':1474 'minut':1312 'miss':1537 'mistak':160,163,1430 'mode':144,147,1185,1244,1354,1637,1646,1732 'model':852 'modifi':481,482,1260 'monospaceddigit':976 'multipl':414 'must':1521 'myappwidget':423 'myprovid':461 'mywidget':459 'mywidgetpushhandl':1386 'mywidgetview':464 'name':485 'nativ':611 'nest':268 'network':1515 'new':175,186,1454 'newstat':1060 'nextupd':590,604 'nil':1043,1062,1074 'non':443,513 'non-configur':442,512 'now.addingtimeinterval':1082 'nssupportsliveact':272,1538,1547,1743 'ofkind':1471,1718 'older':1440 'open':1110 'opencamera':1101 'opencameracontrol':1093 'opencameraint':1104 'order':399,405 'ordernumb':871,1020 'orderprovid':392 'orderstatuswidget':378,383,429 'orderwidgetview':395 'outdat':1597 'pad':839,919,1257 'pair':452 'paramet':797 'pass':1625 'pattern':78,149,152,1215,1337 'per':232,729,1276,1302,1725 'per-el':1275 'perform':777,805,1514 'physic':1676 'pizza':1023 'place':1024 'placehold':530,554,627,1518,1519,1700 'platform':696 'polici':602,691,1713 'poll':1383 'posit':985 'pre':1617 'pre-comput':1616 'prefer':1216,1446 'prepar':1036 'present':54 'primari':961 'process':1498,1615 'properti':211 'protocol':83,88,358,368 'provid':27,391,460,473,877,1116,1127,1166,1445,1623 'purpos':483 'push':71,1377 'push-bas':70,1376 'pushinfo':1390 'pushinfo.token.map':1396 'pushtokendidchang':1389 'pushtyp':303,1054 'put':1599 'quickactioncontrol':434 'read':1512 'readi':1628 'receiv':612 'recommend':448 'refer':169,170,1768 'references/widgetkit-advanced.md':65,66,1327,1328,1771,1772 'refresh':1293,1301,1459,1465 'region':983,984,1011 'regist':247 'relevancescor':1044,1063,1075 'reli':1655 'reload':1380,1712 'reloadtimelin':1717 'render':1202,1243,1358,1373,1411,1609,1636,1641 'rendering-mod':1242 'requir':520 'restaurantnam':874,1022 'result':814 'return':370,654,687,813,1522,1702 'review':3,164,167,342,349,1678 'review-checklist':166 'right':995 'run':346,1494 'safeti':1428 'sampl':636,1525 'schedul':1382 'screen':19,21,45,48,137,141,289,879,1145,1226,1233,1639 'see':64,1326 'selectcategoryint':625,642,666 'selectcategoryintent.self':472 'self':952 'send':1402 'sendabl':1764 'separ':1497 'server':1406 'setup':75 'share':195,480,1489,1504 'show':1589 'shown':486,493 'signific':1670 'simul':1672 'sinc':1281 'singl':418,1288 'sirikit':1441 'size':506,1613 'size-limit':1612 'skill' 'skill-widgetkit' 'small':507,1418 'snapshot':639,1705 'sosumi.ai':1305,1777,1781,1790 'sosumi.ai/documentation/activitykit)':1780 'sosumi.ai/documentation/widgetkit)':1776 'sosumi.ai/documentation/widgetkit/keeping-a-widget-up-to-date)':1304,1789 'source-dpearson2699' 'spacer':828,913 'sparklin':1267 'stale':1580 'staled':1042,1061,1073 'standbi':23,59,143,146,1184,1191,1209,1667 'standby-mod':145 'star':838 'star.fill':837 'start':296,1012,1545 'state':1026,1040,1041,1059,1071,1581 'static':219,456,511,791,848 'staticconfigur':388,440,457,1163 'staticcontrolconfigur':338,1099,1124,1756 'status':400 'step':953,959 'step.icon':957 'stepsprovid':1167 'stepswidget':1154,1158 'strategi':69 'string':382,803,863,875,1397 'struct':207,239,265,377,422,523,617,788,815,854,857,890,1092,1117,1153,1385 'style':1239,1351 'suitenam':1501 'sunni':541 'supplementalactivityfamili':503 'support':244,1343 'supportedfamili':406,498,1180 'surfac':60,1285 'swift':376,420,455,522,616,734,787,853,889,1016,1089,1152,1203,1384 'swiftui':229 'switch':743 'synchron':1523,1703 'system':1237 'systemextralarg':712 'systemimag':1107,1138 'systemlarg':708 'systemmedium':408,704,751 'systemnam':835,927,956,965,979,1174 'systemsmal':407,697,746,1186,1409 'tap':1289 'target':182,187,1290,1682 'task':575 'temperatur':538,560,585 'tertiari':962 'test':1649,1661,1729,1765 'text':826,905,910,914,933,942,968,1176,1315 'three':519 'throw':807 'timelin':26,68,573,599,663,671,688,1292,1324,1379,1530,1622,1711,1758 'timelineentri':206 'timelineprovid':96,97,218,509,525 'timelinereloadpolici':1482 'timerinterv':915,934,969,1316 'titl':793,798 'title2':930 'toggl':771,795,1112,1739 'togglefavoriteint':789,831 'toggleflashlightint':1135 'token':1055 'tokenstr':1395,1403 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'track':402 'trail':932,994 'tri':1048 'true':918,937,972 'truedepth':990,998 'type':92,95,438,775,1762 'typealia':526,620,623 'updat':73,305,1013,1057,1067,1478,1566,1593,1715 'use':11,15,228,337,410,439,446,516,609,731,768,1147,1197,1221,1246,1261,1314,1352,1432,1480,1499,1527,1556,1561,1735,1746,1755 'user':613 'userdefault':1500 'valu':502,594,1115,1129,1133,1139,1483,1629 'var':384,425,737,739,792,801,821,861,864,867,870,873,893,1095,1120,1159,1206 'verifi':1674 'vibrant':1643,1731 'view':227,742,817,824,1587,1605,1607 'visual':1265,1350 'void':550,574 'vstack':902,1172 'watcho':717,720,723,725 'weather':577 'weather.condition':588 'weather.temp':586 'weatherentri':528,534,535,549,557,582 'weatherprovid':524 'weatherservice.shared.fetch':579 'widget':6,24,31,46,49,82,87,100,103,106,111,127,133,138,142,176,180,188,201,226,237,249,285,334,344,357,361,363,367,379,415,428,445,451,489,496,515,608,693,765,782,887,892,1086,1146,1155,1187,1228,1249,1253,1284,1345,1392,1408,1410,1419,1455,1461,1492,1511,1604,1606,1640,1680,1699,1728,1734,1785 'widget-famili':102 'widget-protocol-and-widgetbundl':86 'widgetaccentedrenderingmod':1353 'widgetbundl':85,90,252,360,409,411,424,1695 'widgetcenter.shared.reloadtimelines':1470 'widgetconfigur':372,387,896,1162 'widgetfamili':233,501,733,736,1726 'widgetinfo':1393 'widgetkit':1,12,40,1775 'widgetloc':1199,1205 'widgetpushhandl':1374,1387 'widgetpushinfo':1391 'widgetrenderingmod':1652 'width':974 'without':783,1381,1546 'work':1535 'workflow':80,81,171 'wrap':992,1000 'xcode':74,184 'yes':273,1548,1744 'zstack':1170","prices":[{"id":"cdc49fbd-5c49-49fe-8087-4dcd8fc58f06","listingId":"7d68c4cc-fe7e-478e-868e-6da69980b910","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:33:35.318Z"}],"sources":[{"listingId":"7d68c4cc-fe7e-478e-868e-6da69980b910","source":"github","sourceId":"dpearson2699/swift-ios-skills/widgetkit","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/widgetkit","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:32.339Z","lastSeenAt":"2026-05-18T18:53:46.644Z"},{"listingId":"7d68c4cc-fe7e-478e-868e-6da69980b910","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/widgetkit","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/widgetkit","isPrimary":true,"firstSeenAt":"2026-04-18T20:33:35.318Z","lastSeenAt":"2026-05-07T22:40:32.487Z"}],"details":{"listingId":"7d68c4cc-fe7e-478e-868e-6da69980b910","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"widgetkit","github":{"repo":"dpearson2699/swift-ios-skills","stars":599,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-26T21:04:17Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"e45fc00a18cece9d54b4cab22c4cbbb79bcbdf1e","skill_md_path":"skills/widgetkit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/widgetkit"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"widgetkit","description":"Implement, review, or improve widgets, Live Activities, and controls using WidgetKit and ActivityKit. Use when building home screen, Lock Screen, or StandBy widgets with timeline providers; when creating interactive widgets with Button/Toggle and AppIntent actions; when adding Live Activities with Dynamic Island layouts (compact, minimal, expanded); when building Control Center widgets with ControlWidgetButton/ControlWidgetToggle; when configuring widget families, refresh budgets, deep links, push-based reloads, or Liquid Glass rendering; or when setting up widget extensions, App Groups, and entitlements."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/widgetkit"},"updatedAt":"2026-05-18T18:53:46.644Z"}}