Features
Timelines and transitions
A widget can change on its own, without the app running: the config carries layouts for later times, and every platform switches to the right one right before drawing.
Scheduled states (entries)
From at (Unix ms) on, an entry's small / medium / large replace the base ones. The
last entry with at <= now wins; families an entry omits keep the base layout.
const start = Date.parse("2026-11-14T09:00:00Z");
await setWidgetConfig({
small: { type: "text", content: "Meeting at 9:00" },
entries: [
{ at: start, small: { type: "text", content: "Meeting now" } },
{ at: start + 3_600_000, small: { type: "text", content: "No meetings" } },
],
}, undefined, "agenda");
| Platform | How the switch happens |
|---|---|
| iOS / macOS | WidgetKit timeline: one entry per at (up to 30 ahead) |
| Android | Inexact RTC alarm redraws the widget — it does not wake the device and runs once it is awake (late in Doze) |
| Desktop window | Renderer timer |
| Windows Widgets Board | Host rebuilds the card while the app runs |
Transitions (transition)
A hint for how content changes between timeline entries and redraws, on the config (the whole widget) or on any element:
{ "type": "text", "content": "{{data.temp}}°", "transition": "numeric" }
| Value | Effect |
|---|---|
numeric | digits roll (contentTransition(.numericText()) on Apple) |
opacity | cross-fade |
slide | the new content pushes in from the bottom |
none | no animation |
iOS / macOS and desktop windows animate (desktop: when the element's content differs from the previous draw). Android and the Windows Widgets Board ignore it.