@expo/ui 's SwiftUI Text can show a self-updating date only through timerInterval ( Text(timerInterval:countsDown:) ) or date + dateStyle ( .timer , .relative , .offset ). In a Live Activity rendered by expo-widgets , every one of these either shows seconds or carries a sign. Measured 42 m 30 s before a date, read 1 to 2 minutes later (unlocked in Notification Center / on the locked Lock Screen): timerInterval + countsDown : 40:39 / 41:-- dateStyle="timer" : 40:38 / 41 minutes dateStyle="relative" : 40 min, 38 sec (compact Dynamic Island: 40 min, 49… ) / 41 min dateStyle="offset" : −40 minutes / −41 minutes ProgressView timerInterval (its value label): 40:39 / 41:-- So once the phone is unlocked (Face ID on the Lock Screen, Notification Center, the Dynamic Island), every option shows seconds except offset , which always carries a minus sign and offers no control over the sign or the fields. iOS 18 added live-updating system formats that WidgetKit and ActivityKit render without timeline reloads or pushes: Text(_ source: TimeDataSource<Date>, format: some DiscreteFormatStyle) with SystemFormatStyle.DateOffset , .DateReference , .Timer and .Stopwatch . Apple introduced them at WWDC24 ("What's new in SwiftUI") for widgets and Live Activities. With allowedFields: [.hour, .minute] they never show seconds, for example 2 hr, 15 min or 42 min . With .textVariant(.sizeDependent) they also narrow to 2h 15m / 42m in a compact Dynamic Island. Neither @expo/ui 58.0.28 nor expo-widgets 58.0.28 exposes them. And because expo-widgets renders a closed set of @expo/ui views in the extension ( ios/Widgets/ViewRenderer.swift ), an app can't add its own SwiftUI view to fill the gap. The same gap shows on ProgressView(timerInterval:countsDown:) . @expo/ui uses the label: initializer, which shows SwiftUI's default current-value label ( 42:30 , with seconds), and there's no prop to hide it. Repro An SDK 58 app with @expo/ui@58.0.28 and expo-widgets@58.0.28 (no patches), and this Live Activity: ```tsx import { HStack, Image, ProgressView, Text, VStack } from '@expo/ui/swift-ui'; import { createLiveActivity } from 'expo-widgets'; const Countdown = createLiveActivity<{ fromMs: number; atMs: number }>('Countdown', (props) => { 'widget'; const from = new Date(props.fromMs); const at = new Date(props.atMs); return { banner: ( <VStack alignment="leading"> <HStack><Text>timerInterval</Text><Text timerInterval={{ lower: from, upper: at }} countsDown /></HStack> <HStack><Text>dateStyle timer</Text><Text date={at} dateStyle="timer" /></HStack> <HStack><Text>dateStyle relative</Text><Text date={at} dateStyle="relative" /></HStack> <HStack><Text>dateStyle offset</Text><Text date={at} dateStyle="offset" /></HStack> <ProgressView timerInterval={{ lower: from, upper: at }} countsDown /> </VStack> ), compactLeading: <Image systemName="timer" />, compactTrailing: <Text date={at} dateStyle="relative" />, minimal: <Image systemName="timer" />, }; }); const fromMs = Date.now (); Countdown.start({ fromMs, atMs: fromMs + 42.5 * 60_000 }); Look at the Lock Screen while locked, then unlocked (Notification Center), and at the compact Dynamic Island from the Home Screen. You get the readings above. There's no way, through either package, to read `42 min` (or `2h 15m`) and keep counting without a push per minute. **Proposed API** On `Text` (iOS 18+; below 18 it falls back to the existing `date` / `dateStyle` / `timerInterval` props, so a layout can pass both): ```ts type TextLiveFormat = | { kind: 'offset'; to: Date; allowedFields?: ('hour' | 'minute' | 'second')[]; sign?: 'automatic' | 'never' | 'always' } | { kind: 'reference'; to: Date; allowedFields?: ('day' | 'hour' | 'minute' | 'second')[]; maxFieldCount?: number } | { kind: 'timer'; countingDownIn: { lower: Date; upper: Date }; maxPrecisionSeconds?: number }; <Text liveFormat={{ kind: 'offset', to: start, allowedFields: ['hour', 'minute'], sign: 'never' }} /> Plus a textVariant modifier ( 'sizeDependent' | 'preferredFormat' ), mapping to .textVariant(_:) . On ProgressView : hidesCurrentValueLabel?: boolean , mapping to init(timerInterval:countsDown:label:currentValueLabel: { EmptyView() }) . Swift side, in TextView.swift 's buildText : ```swift if #available(iOS 18.0, *), let live = props.liveFormat { switch live.kind { case "offset": return Text(.currentDate, format: .offset(to: live.to , allowedFields: live.fields, sign: live.sign)) case "timer": return Text(.currentDate, format: .timer(countingDownIn: live.lower..<live.upper, maxPrecision: .seconds(live.precision))) // reference, ... } } ``` One detail from doing it: .textVariant(_:) is declared on Text and returns some View , so it has to be applied to the Text before the view-modifier array (which erases to a View), while buildText stays a Text for nested-Text concatenation. We carry the offset arm (with sizeDependent ) and the hidden ProgressView label as a patch-package patch today, across ios/TextView.swift , ios/ProgressView.swift and the two TS components. We'd gladly open the PR if the shape is welcome. Why Event and travel apps show "starts in" countdowns on the lock screen, where seconds are noise. On a locked iPhone the system replaces them with dashes ( 42:-- ), which reads as broken. Apple's own guidance for Live Activities is to update rarely and let the system tick. The iOS 18 formats are exactly that, and today they're unreachable from Expo. Environment Expo SDK 58 (expo 58.0.22), @expo/ui 58.0.28, expo-widgets 58.0.28 (both unpatched), Xcode 27.1, iPhone 17 simulator on iOS 27.