Programming language: Swift
Tags: UI     Alert & Action Sheet    
Latest version: v1.0.0

Sheet alternatives and similar libraries

Based on the "Alert & Action Sheet" category.
Alternatively, view Sheet alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of Sheet or a related project?

Add another 'Alert & Action Sheet' Library


Portrait Landscape Preview
1 2 3

The above UI is built in a storyboard. It was lifted from Silver and required zero code changes to work as an action sheet.


final class ViewController: UIViewController {

    private let sheetManager = Sheet(animation: .slideLeft)

    private var observer: NSObjectProtocol?

    override func viewDidLoad() {
        observer = NotificationCenter.default.addObserver(
            forName: .dismiss, 
            object: nil, 
            queue: nil) { [weak self] _ in
                self?.dismiss(animated: true)
        sheetManager.chromeTapped = { [unowned self] in
            self.dismiss(animated: true)
        let action = #selector(tapGestureRecognized(_:))
        let tapGesture = UITapGestureRecognizer(target: self, action: action)

    @objc func tapGestureRecognized(_ sender: UITapGestureRecognizer) {
        let storyboard = UIStoryboard(name: "WelcomeSheet", bundle: nil)
        let viewController = storyboard.instantiateInitialViewController()!
        sheetManager.show(viewController, above: self)

The notification name dismiss is created the typical way. You may create any name you like.

extension Notification.Name {
    static let dismiss = Notification.Name(rawValue: "Dismiss")

Observed: by the controller that presents the action sheet. Posted: by the last controller in the action sheet sequence (or didEnterBackground for example).

Here are a sequence of two actions sheets WelcomeSheetViewController being the 1st and CompleteSheetViewController being the last.

class BaseViewController: UIViewController {

    override func viewDidLayoutSubviews() {
        view.clipsToBounds = true
        view.layer.cornerRadius = view.bounds.width * 0.1

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent

    override var prefersHomeIndicatorAutoHidden: Bool {
        return true

final class WelcomeSheetViewController: BaseViewController {

    @IBAction func startButtonPressed(_ sender: UIButton) {
        let storyboard = UIStoryboard(name: "CompleteSheet", bundle: nil)
        let viewController = storyboard.instantiateInitialViewController()!
        show(viewController, sender: self)

final class CompleteSheetViewController: BaseViewController {

    @IBAction func finishButtonPressed(_ sender: UIButton) {
        NotificationCenter.default.post(name: .dismiss, object: nil)

You may create a network of storyboard segue's, each segue pushing via show in storyboard or by calling UIKit's show show(:sender:) in code.

// iconImageView is an IBOutlet property to a UIImageView embedded in a stack view. 

override func viewWillAppear(_ animated: Bool) {
    iconImageView.isHidden = (traitCollection.verticalSizeClass == .compact)

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    super.willTransition(to: newCollection, with: coordinator)
    iconImageView.isHidden = (newCollection.verticalSizeClass == .compact)
    coordinator.animate(alongsideTransition: { [unowned self] _ in
    }, completion: nil)

As per UIKit rules, each UIViewController subclass is responsible for it's views. So make sure your layout works in all environments. The above preview shows a paper plan icon which is hidden in compact height environments.

If you would like to use custom transition animations, instantiate Sheet with .custom and sublcass StoryboardSegue.

final class FlipFromLeftSegue: StoryboardSegue {

    override func executeTransition(_ completion: @escaping () -> Void) {
            from: source.view!,
            to: destination.view!,
            duration: 0.3,
            options: [.transitionFlipFromLeft]) { (_) in

final class DropSegue: StoryboardSegue {

    override func executeTransition(_ completion: @escaping () -> Void) {
        destination.view.transform = CGAffineTransform(translationX: 0, y: destination.view.bounds.height)
        let height = source.view.bounds.height
        UIView.animate(withDuration: 0.3, animations: {
            self.source.view.transform = CGAffineTransform(translationX: 0, y: height)
            self.destination.view.transform = CGAffineTransform.identity
        }) { _ in


Tap the following image to launch Appetize.