Extra Live Activities

Show a second active activity beside the current compact live activity.

Overview

Extra Live Activity, or ELA, is the small side capsule DynamicLake shows when another live activity is available while a compact live activity is already visible.

Use ELA for a tiny secondary status. Most ELA content should be one element, usually one SF Symbol. Add a duration or count value only when the activity cannot be understood from the symbol alone.

DynamicLake owns the capsule background, clipping, placement, hover behavior, and tap-to-open behavior. Your extension only renders the capsule content.

When To Use ELA

Use an ELA when the activity is still useful while another activity is currently occupying the main compact surface.

Good ELA content:

Avoid ELA content that needs reading time, multi-line labels, nested controls, or the same left/right layout as the compact live activity. Put readable detail in the sneak peek instead.

Add The Scene

Add DynamicLakeExtraLiveActivity to the same ExtensionKit entry point as your compact live activity.

import DynamicLakeKit
import SwiftUI

@main
struct ClockDynamicLakeExtension: DynamicLakeExtension {
    var body: some DynamicLakeExtensionScene {
        DynamicLakeLiveActivity {
            ClockLiveActivityView()
        }

        DynamicLakeExtraLiveActivity {
            ClockExtraLiveActivityView()
                .allowsHitTesting(false)
        }
    }
}

Use .allowsHitTesting(false) for passive ELA UI. DynamicLake handles hover, click, right-click, swipe, and opening the activity from the capsule.

Build The View

Design the view for a very small capsule. Prefer one centered SF Symbol and let DynamicLake provide the capsule background.

import DynamicLakeKit
import SwiftUI

struct ClockExtraLiveActivityView: View {
    var body: some View {
        Image(systemName: "clock.fill")
            .font(.system(size: 12, weight: .semibold))
            .foregroundStyle(.white.opacity(0.9))
            .frame(width: 16, height: 16)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

Use a value only when it is the point of the ELA, such as a timer or count:

struct TimerExtraLiveActivityView: View {
    let valueText: String

    var body: some View {
        Text(valueText)
            .font(.system(size: 11, weight: .semibold, design: .rounded))
            .lineLimit(1)
            .minimumScaleFactor(0.75)
            .foregroundStyle(.white.opacity(0.86))
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .padding(.horizontal, 7)
    }
}

Use a symbol plus a value only when both are necessary and still fit without crowding:

struct CountExtraLiveActivityView: View {
    let countText: String

    var body: some View {
        HStack(spacing: 4) {
            Image(systemName: "tray.full.fill")
                .font(.system(size: 10, weight: .semibold))

            Text(countText)
                .font(.system(size: 10, weight: .semibold, design: .rounded))
                .lineLimit(1)
                .minimumScaleFactor(0.75)
        }
        .foregroundStyle(.white.opacity(0.86))
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .padding(.horizontal, 6)
    }
}

Do not draw a custom background, capsule, shadow, or outer padding. The host sizes and clips the ELA.

Layout Guidelines

State Guidelines

ELA scenes do not receive a DynamicLakeLiveActivityContext. If the ELA needs current state, keep that state in the same shared model or app group storage used by the companion app and compact scene.

For most activities, keep ELA state minimal:

Avoid putting heavy polling, networking, or file scanning directly in the ELA view. The companion app should compute state and publish it.

Preview ELA

Use DynamicLakeLiveActivitySimulator with mode: .all or .extraLiveActivity and pass the ELA view through the extraLiveActivity closure.

DynamicLakeLiveActivitySimulator(
    provider: ClockLiveActivityProvider(),
    state: DynamicLakeEmptyLiveActivityState(),
    mode: .all
) {
    ClockExtraLiveActivityView()
}

For ELA-only preview:

DynamicLakeExtraLiveActivitySimulator(
    configuration: ClockLiveActivityProvider().configuration
) {
    ClockExtraLiveActivityView()
}

Test ELA beside compact live activity, sneak peek, notch, and pill shapes. The ELA should stay readable without feeling like a second full live activity.

Common Mistakes

| Mistake | Result | Better Approach | | --- | --- | --- | | Reusing the full compact live activity view | The ELA feels crowded and duplicates the main surface. | Build a separate tiny capsule view. | | Adding a custom capsule background | The view fights DynamicLake's clipping and visual style. | Render content only. | | Using two elements by default | The capsule feels too busy beside the main activity. | Start with one SF Symbol and add a value only if the symbol is unclear. | | Showing long labels or two lines | Text clips or becomes unreadable. | Show one symbol or a timer or count value and move detail to sneak peek. | | Adding controls inside ELA | Small hit targets conflict with DynamicLake gestures. | Let tapping the ELA open the main activity. | | Doing heavy work in the ELA view | The capsule can lag or crash the extension UI. | Publish simple state from the companion app. |

Topics

Entry Point

Preview