Skip to content

wiedem/fullscreen-cover

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FullScreenCover

Swift 6.1 iOS 16.4+ Swift Package Manager MIT License

FullScreenCover presents full-screen modal views in SwiftUI, building on .fullScreenCover and adding what's missing:

  • Use any SwiftUI transition instead of the fixed slide-up animation
  • await present() and await dismiss() to safely chain sequential operations without callback workarounds

Custom Transition Demo     Async Coordination Demo

Usage

Add import FullScreenCover to your source code. Wrap your view with a PresentationCoordinator and pass its proxy to the fullScreenCover(presentation:animation:content:) modifier.

Custom Transition Animations

Use any SwiftUI transition:

import FullScreenCover
import SwiftUI

struct DemoView: View {
    var body: some View {
        PresentationCoordinator { proxy in
            Button("Present Modal") {
                Task { try await proxy.present() }
            }
            .fullScreenCover(presentation: proxy, animation: .spring(duration: 0.5)) {
                ZStack {
                    Color.black.opacity(0.5)
                        .ignoresSafeArea()

                    VStack(spacing: 16) {
                        Text("Custom modal content")
                            .font(.title)

                        Button("Dismiss") {
                            Task { try await proxy.dismiss() }
                        }
                    }
                }
                .transition(.scale(scale: 0.8).combined(with: .opacity))
            }
        }
    }
}

Use the transition(_:) modifier on your modal content to define your custom animation. The animation parameter on fullScreenCover controls the timing.

The presentation background is automatically set to transparent so that custom transitions render correctly. You can override it by applying .presentationBackground(_:) to your modal content.

Async Coordination

Both present() and dismiss() are async and return only after the transition has completed. This makes it safe to chain sequential operations:

Button("Show Confirmation") {
    Task {
        // present() returns once the modal content has appeared.
        try await proxy.present()

        // Do some work while the modal is visible...
        try await performNetworkRequest()

        // dismiss() returns after the dismiss animation finishes.
        try await proxy.dismiss()

        // Safe to continue, e.g. navigate or show another modal.
        navigateToNextScreen()
    }
}

Both methods throw CancellationError if the calling task is cancelled. The transition itself continues unaffected - only the caller stops waiting.

Presentation Phase

The proxy exposes a phase property of type PresentationPhase that tracks the current lifecycle state: idle, presenting, presented, or dismissing. Use it to adapt your UI during transitions:

PresentationCoordinator { proxy in
    Button("Present") {
        Task { try await proxy.present() }
    }
    .disabled(proxy.phase != .idle)
}

Accessing the Proxy in Child Views

The PresentationProxy is automatically injected as an EnvironmentObject. Child views can access it without passing it through manually:

struct DismissButton: View {
    @EnvironmentObject private var proxy: PresentationProxy

    var body: some View {
        Button("Close") {
            Task { try await proxy.dismiss() }
        }
    }
}

Installation

Add the package to the dependencies in your Package.swift file:

.package(url: "https://github.com/wiedem/fullscreen-cover", .upToNextMajor(from: "2.0.0")),

Then include "FullScreenCover" as a dependency for your target:

dependencies: [
    .product(name: "FullScreenCover", package: "fullscreen-cover"),
]

Requirements

  • iOS 16.4+
  • Swift 6.1+
  • Xcode 16.3+

Contributing

Contributions are welcome! Please feel free to:

  • Report bugs or request features via GitHub Issues
  • Submit pull requests with improvements
  • Improve documentation or add examples
  • Share feedback on API design

License

FullScreenCover is available under the MIT License. See LICENSE.txt for more information.

About

Custom full-screen modal transitions for SwiftUI with async present/dismiss coordination

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages