Giter Site home page Giter Site logo

mijick / popupview Goto Github PK

View Code? Open in Web Editor NEW
873.0 10.0 36.0 94 KB

Popups presentation made simple (SwiftUI)

License: MIT License

Swift 98.67% Ruby 1.33%
popup swift swift-package-manager swift5 swiftui swiftui-components swiftui-framework alert popups toast ios ios-swift swift-library swift-package cocoapods ios-sdk swift-5 mobile

popupview's Introduction


PopupView Logo

Popups presentation made simple

Create beautiful and fully customisable popups in no time. Keep your code clean

Try demo we prepared


SwiftUI logo Platforms: iOS, iPadOS, macOS, tvOS Current Version License: MIT

Made in Kraków Follow us on X Let's work together Stargazers

Popup Examples Popup Examples Popup Examples


PopupView is a free and open-source library dedicated for SwiftUI that makes the process of presenting popups easier and much cleaner.

  • Improves code quality. Show your popup using the showAndStack() or showAndReplace() method.
    Hide the selected one with dismiss(). Simple as never.
  • Create any popup. We know how important customisation is; that's why we give you the opportunity to design your popup in any way you like.
  • Designed for SwiftUI. While developing the library, we have used the power of SwiftUI to give you powerful tool to speed up your implementation process.

Getting Started

✋ Requirements

Platforms Minimum Swift Version
iOS 14+ 5.0
iPadOS 14+ 5.0
macOS 12+ 5.0
tvOS 15+ 5.0

⏳ Installation

Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the Swift compiler.

Once you have your Swift package set up, adding PopupView as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
    .package(url: "https://github.com/Mijick/PopupView.git", branch(“main”))
]

Cocoapods is a dependency manager for Swift and Objective-C Cocoa projects that helps to scale them elegantly.

Installation steps:

    pod init
  • Add CocoaPods dependency into your Podfile
    pod 'MijickPopupView'
  • Install dependency and generate .xcworkspace file
    pod install
  • Use new XCode project file .xcworkspace

Usage

1. Setup library

Inside your @main structure call the implementPopupView method. It takes the optional argument - config, that can be used to configure some modifiers for all popups in the application.

  var body: some Scene {
        WindowGroup(content: ContentView().implementPopupView)
  }

2. Declare a structure of your popup

The library provides an ability to present your custom view in three predefinied places - Top, Centre and Bottom.
In order to present it, it is necessary to confirm to one of the protocols during your view declaration:

  • TopPopup - presents popup view from the top
  • CentrePopup - presents popup view from the center
  • BottomPopup - presents popup view from the bottom

So that an example view you want to present will have the following declaration:

struct BottomCustomPopup: BottomPopup {
    ...
}

3. Implement createContent() method

The function above is used instead of the body property, and declares the design of the popup view.

struct BottomCustomPopup: BottomPopup {    
    func createContent() -> some View {
        HStack(spacing: 0) {
            Text("Witaj okrutny świecie")
            Spacer()
            Button(action: dismiss) { Text("Dismiss") } 
        }
        .padding(.vertical, 20)
        .padding(.leading, 24)
        .padding(.trailing, 16)
    }
    ...
}

4. Implement configurePopup(popup: Config) -> Config method

Declaring this step is optional - if you wish, you can skip this step and leave the UI configuration to us.
Each protocol has its own set of methods that can be used to create a unique appearance for every popup.

struct BottomCustomPopup: BottomPopup {    
    func createContent() -> some View {
        HStack(spacing: 0) {
            Text("Witaj okrutny świecie")
            Spacer()
            Button(action: dismiss) { Text("Dismiss") } 
        }
        .padding(.vertical, 20)
        .padding(.leading, 24)
        .padding(.trailing, 16)
    }
    func configurePopup(popup: BottomPopupConfig) -> BottomPopupConfig {
        popup
            .horizontalPadding(20)
            .bottomPadding(42)
            .cornerRadius(16)
    }
    ...
}

5. Present your popup from any place you want!

Just call BottomCustomPopup().showAndStack() from the selected place. Popup can be closed automatically by adding the dismissAfter modifier.

struct SettingsViewModel {
    ...
    func saveSettings() {
        ...
        BottomCustomPopup()
            .showAndStack()
            .dismissAfter(5)
        ...
    }
    ...
}

6. Closing popups

There are two methods to do so:

  • By calling one of the methods dismiss, dismiss(_ popup: Popup.Type), dismissAll(upTo: Popup.Type), dismissAll inside the popup you created
struct BottomCustomPopup: BottomPopup {
    ...
    func createButton() -> some View {
        Button(action: dismiss) { Text("Tap to close") } 
    }
    ...
}
  • By calling one of three static methods of PopupManager:
    • PopupManager.dismiss()
    • PopupManager.dismiss(_ popup: Popup.Type) where popup is the popup you want to close
    • PopupManager.dismissAll(upTo popup: Popup.Type) where popup is the popup up to which you want to close the popups on the stack
    • PopupManager.dismissAll()

Try our demo

See for yourself how does it work by cloning project we created

License

PopupView is released under the MIT license. See LICENSE for details.



Our other open source SwiftUI libraries

Navigattie - Easier and cleaner way of navigating through your app
CalendarView - Create your own calendar object in no time
GridView - Lay out your data with no effort
Timer - Modern API for Timer

popupview's People

Contributors

fulcrumone avatar jay-jay-lama avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

popupview's Issues

Pod not update the latest code

pod 'Mijick_PopupView'

After pod install
I have to change
import PopView to Mijick_PopupView

but I got this error. please look that issue

Screenshot 2023-08-29 at 14 10 59

Why is viewModel not deiniting with a PopupView?

I use popupView for a popup that confirms the user is leaving that screen. But the ViewModel cannot be denied when combined
with the popupView, so in the long run it will lead to memory leaks.
Screenshot 2024-03-01 at 01 09 18

PopupView size not updated after screen rotation.

Steps to reproduce:
1, Start the app when the phone is in portrait mode.
2, Rotate the phone to landscape mode.
3, Open the bottom PopupView.

The bottom PopupView doesn't span the full screen width. Instead, it displays a shadow strip in the center of the screen with full height.

Automatically falling back to Main Thread rendering engine...

Hi, thanks for this amazing library. When I present popup view, I get below log in Xcode.
Automatically falling back to Main Thread rendering engine. This fallback comes with some additional performance
overhead, which can be reduced by manually specifying that this animation should always use the Main Thread engine.

Problem with scrollable content

If in popup view there is scrollable content and it's value bigger than screen's height - we can't scroll it to the bottom
Problem cam be solved with setting view's configuration to
contentFillsWholeHeigh(true) or contentFillsEntireScreen(true)

BottomPopup placed under sheet

Hi, very nice work!

I only have one issue, the BottomPopup is placed under other sheets.

So if I show a sheet, then present a BottomPopup, I have to dismiss the sheet for the BottomPopup to be visible.

Cant used GeometryReader

When I wrap using GeometryReader ,I got results like below image

Code Snippet

'struct BottomPopup_NoCornerRadius: BottomPopup {
    func configurePopup(popup: BottomPopupConfig) -> BottomPopupConfig { popup.cornerRadius(0) }
    func createContent() -> some View {
        GeometryReader{ geo in
            VStack(alignment: .leading, spacing: 0) {
                Text("Test")
                createTitle()
                Spacer.height(16)
                createDescription()
                Spacer.height(36)
                createButtons()
            }
            .padding(.top, 32)
            .padding(.bottom, 12)
            .padding(.horizontal, 28)
        }
        }
      
}
@FulcrumOne 

Demo:
Simulator Screenshot - iPhone 15 - 2023-12-29 at 01 55 09

Bug with custom center two popups

Issue Description

When attempting to .showAndStack() two separate center popups with custom views at the same time, the background view always adopts a gray color. This behavior occurs despite different configurations intended for the popups. Additionally, an issue with tap gestures is present when a bottom sheet with a TabView is used; the button tap does not work upon the first appearance.

Steps to Reproduce

  1. Implement .showAndStack() with two separate center popups with custom views.
  2. Observe that the background view is gray for both popups.
  3. Implement a bottom sheet with a TabView.
  4. Notice that the button within the TabView does not work on the first appearance.

Expected Behavior

The background view should not default to gray when stacking popups, and all user interactions, such as tap gestures on buttons within a TabView, should be responsive upon the first appearance.

Screenshots

  • iPhone 15 Example:
    iPhone 15 Example

  • iPhone 15 Pro Example:
    iPhone 15 Pro Example

  • Screenshot of Issue:
    Issue Screenshot

Code Snippet

struct BreakDownBottomSheetView: BottomPopup {

    func configurePopup(popup: BottomPopupConfig) -> BottomPopupConfig {
        popup
            .tapOutsideToDismiss(true)
            .dragGestureEnabled(true)
            .contentIgnoresSafeArea(true)
    }

    func createContent() -> some View {
        VStack(spacing: 15){
            TabView(selection: $index) {
                ForEach(yourDataArray, id: \.self) { item in
                    Button(action: {
                        // Button action here
                        // Doesn't work on first appearance
                    }) {
                        Text("Button for \(item)")
                    }
                    .tabItem {
                        Image(systemName: "some-system-image")
                        Text("Tab \(item)")
                    }
                    .tag(item)
                }
            }
            .tabViewStyle(.page(indexDisplayMode: .never))
            .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .never))
        }
    }
}

BreakDownBottomSheetView()
    .showAndStack()

Popup Displays Underneath Open Sheet Instead of On Top

Hello, I've been using your excellent library, and it works very well. However, I've encountered an issue: when I am in a sheet and try to display a Popup, it opens underneath the currently open sheet, whereas I would like it to appear on top. I hope you can find a solution to this problem.

Shift up the screen when the keyboard is opened.

If I have a TextEditor on the bottom popup, and the TextEditor is focused, the keyboard doesn't open. I think this is because the bottom PopupView doesn't shift up. Can we make the screen shift up when the keyboard is opened? Thanks.

TopPopup White Safe Area (See Screenshot)

I created the following "alert" popup, and when it displays, the safe area at the top is white, despite my background being dark. I would expect any background to be using .clear by default. As a work around, I have implemented my own PopupConfig.

Screenshot 2023-06-01 at 8 08 44 AM

no animation on dismiss

There is no animation when dismissing a popup, which is a bit of shame as the animation on insert is great

UIScreen.main.bounds doesn't work for iPad and Mac

Manually computing the screen width limits the usage of the library only for the iPhone and it's not the ideal way for SwiftUI. On iPad, in split screen or with stage manager, UIScreen.main.bounds gives the width of the entire screen, not the width of the app's window.

Simulator Screenshot - iPad Pro (12 9-inch) (6th generation) - 2023-05-22 at 12 59 38

The fix is actually quite simple, mostly removing some .frame modifiers, like in this example

Screenshot 2023-05-22 at 13 00 24

And now it looks good everywhere.

Simulator Screenshot - iPad Pro (12 9-inch) (6th generation) - 2023-05-22 at 13 00 18

The background view has the same problem, more apparent on the Mac.

Screenshot 2023-05-22 at 13 27 51

But this too can be fixed quite easily

Screenshot 2023-05-22 at 13 28 10
Screenshot 2023-05-22 at 13 28 16

I can open a pull request with these changes if that's ok for you

DismissAfter should be tied to a specific popup

I am setting dismiss after 4 seconds for example. if the user manually dismisses the first notification and a second one is triggered, the first dismiss after 4 that was set on a previous notification seems to dismiss the current notification

PopupView seems to follow the component with the biggest width in the view?

Popup seems to follow the component with the biggest width in the view?

Screenshot 2024-01-23 at 23 25 59

it works as expected when content overflows to the next line

Screenshot 2024-01-23 at 23 27 16

Code:

`
import MijickPopupView
import SwiftUI

  struct BottomCustomPopup: BottomPopup {
      func createContent() -> some View {
          HStack(spacing: 0) {
              Text("Witaj okrutny świecie")
              Spacer()
              Button(action: dismiss) { Text("Dismiss") }
          }
          .padding(.vertical, 20)
          .padding(.leading, 24)
          .padding(.trailing, 16)
      }
      func configurePopup(popup: BottomPopupConfig) -> BottomPopupConfig {
          popup
              .horizontalPadding(20)
              .bottomPadding(42)
              .cornerRadius(16)
              .tapOutsideToDismiss(true)
              .dragGestureEnabled(true)
              .contentIgnoresSafeArea(true)
      }
  }

`

Dismiss on touching outside?

Congratulations on this awesome library! The only thing missing is to dismiss the popup when touching outside. Would be great if this feature can be added.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.