---
title: "DroppyCompactClock, DroppyKit"
description: "A clock for compact live-activity content that the host drives (DroppyKit 1.23.0)."
canonical: "https://getdroppy.app/docs/droppykit/api/droppy-compact-clock"
last-updated: "2026-09-09"
---

# DroppyCompactClock

A clock for compact live-activity content that the host drives (DroppyKit 1.23.0).

`@MainActor struct DroppyCompactClock<Content> where Content : View`

Available from DroppyKit 1.23.0.

Droppy's own compact rows (the meeting timer, the calendar ring, the recording waveform) never run a timer of their own. Each draws from a timeline that ticks only while the row is up and at rest, and holds still while the host reveals it, takes it away, moves the notch for a shelf spring or conceals the notch. This is that timeline, for a droplet:

```
public func makeCompactTrailing(context: CompactLiveActivityContext) -> AnyView {
    AnyView(
        DroppyCompactClock { now in
            Text(timer.remaining(at: now))
                .font(.system(size: DroppyLiveActivityMetrics.labelFontSize, weight: .medium))
                .monospacedDigit()
        }
    )
}
```

Use it instead of a `Timer`, a `Timer.publish` sink, a `repeatForever` animation or a `TimelineView(.animation)` in a compact view. Those keep running while nobody can see the row, and the host cannot stop them; this one stops on [`pausesLiveContent`](https://getdroppy.app/docs/droppykit/api/live-activity-presentation-state#pauses-live-content), which the host sets through `EnvironmentValues.dropletCompactPresentation`.

- Ticks land on whole multiples of `interval` (whole seconds by default), so a clock flips its digit when the wall clock does, never up to a second late.
- While paused, `content` keeps the date of the last tick.
- The shortest interval is [`compactClockMinimumInterval`](https://getdroppy.app/docs/droppykit/api/droppy-live-activity-metrics#compact-clock-minimum-interval) (30 a second), and Reduce Motion holds anything faster than a second to one tick a second.
- Outside a compact mount (a settings preview, the harness) nothing pauses it, so it simply ticks.

## Initializers

### init(every:content:)

`@MainActor init(every interval: TimeInterval = 1, @ViewBuilder content: @escaping (Date) -> Content)`

Creates a clock that ticks every `interval` seconds while the compact surface it is in is up and at rest.

## Properties

### body

`@MainActor var body: some View { get }`
