Screen · Productivity

Focus SwiftUI Screen

A focus session with a dial you drag to set minutes and a ring that drains as you work.

A focus timer: drag the dial to set minutes with haptic detents, Start morphs it into a draining ring on a date-anchored clock, with pause and resume, session dots and a success pulse.

  • SwiftUI
  • iOS 17.0+
  • focus-timer
Get SwiftPieces Pro

$199 once, every piece included. See how installing works · Sign in

01

What's included

SwiftUI source you own, built on Apple frameworks only.

  • Drag the dial to set minutes, with haptic detents
  • Start morphs the dial into a ring on a date-anchored clock
  • Pause, resume, session dots and a success pulse
  • The Focus screen from the preview: task, sessions and ambient sound

In the Build Kit

Graphic (style), Productivity (brief). Your agent builds around this screen in the same design.

Used in

Productivity App (template)

02

Implementation notes

How it behaves, what it handles, and the decisions behind it.

Drag anywhere on the dial and the arc follows the finger, snapping to one-minute detents with a light tick and a heavier one every five. Start fades the ticks, thickens the arc into a ring and shrinks the knob away; the digits in the center count down with numericText while the ring drains. Pause holds the remaining time, Resume re-anchors it, and reaching zero pulses the ring with a success haptic and fills the next session dot.

Notes

  • The running clock is an end Date, not a counter: TimelineView derives the remaining time from it, a .task(id:) sleeps until the end date to fire completion, and a scene-phase check catches sessions that finished while the app was in the background.
  • The dial ignores the wrap across 12 o'clock so a drag never jumps from the maximum to the minimum. The full turn is the upper bound of range (at least 60), so a 90-minute range reads as a 90-minute dial.
  • Haptics: light impact per minute, heavy impact on multiples of five, success on completion.
  • The dial is an adjustable VoiceOver element ("Duration, 25 minutes") while setting and reads the remaining time while running; the dots report sessions complete.
  • Reduce Motion drops the completion pulse, steps the ring once per second and replaces springs with ease-outs.
  • FocusTimerExample at the end of FocusTimer.swift is the screen shown in the preview; copy it as a starting point.