Last active
July 14, 2025 02:37
-
-
Save khcrysalis/c9b9246a72282df0339c412ec3b49180 to your computer and use it in GitHub Desktop.
Fancy Onboarding SwiftUI View for iOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| // MARK: - View | |
| struct OnboardingView: View { | |
| @AppStorage("Feather.onboarding") private var _onboardingFinished: Bool = false | |
| @State private var _page: Int = 0 | |
| private var _pageLimit: Int = 2 | |
| // MARK: Body | |
| var body: some View { | |
| VStack(alignment: .center) { | |
| ZStack { | |
| if _page == 0 { | |
| _largeTitle() | |
| .compatBlurTransition() | |
| } else if _page == 1 { | |
| _details( | |
| "Inspect Package Files", | |
| "Feather is an on-device application inspector and manager designed for self-developed apps, mainly viewing on how iOS apps function and work as a whole." | |
| ) | |
| .compatBlurTransition() | |
| } else if _page == 2 { | |
| _details( | |
| "Pairing File", | |
| "Feather requires a VPN and a pairing file to operate." | |
| ) | |
| .compatBlurTransition() | |
| } | |
| } | |
| } | |
| .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) | |
| .background( | |
| ZStack { | |
| if _page == 0 { | |
| LinearGradient( | |
| colors: [ | |
| Color(hex: "46365f"), | |
| Color(hex: "413258"), | |
| Color(hex: "4a3963") | |
| ], | |
| startPoint: .top, | |
| endPoint: .bottom | |
| ) | |
| .transition(.opacity) | |
| } else { | |
| Color(.systemBackground) | |
| .transition(.opacity) | |
| } | |
| } | |
| .ignoresSafeArea(.all) | |
| ) | |
| .safeAreaInset(edge: .bottom) { | |
| HStack(spacing: 12) { | |
| if _page != 0 { | |
| _button("Back", action: _backward) | |
| .compatBlurTransition() | |
| _button("Continue", action: _forward) | |
| .compatBlurTransition() | |
| } else { | |
| _button("Continue", action: _forward) | |
| .compatBlurTransition() | |
| } | |
| } | |
| .padding() | |
| .padding(.horizontal, 24) | |
| } | |
| .animation(.default, value: _page) | |
| } | |
| @ViewBuilder | |
| private func _largeTitle() -> some View { | |
| VStack(alignment: .center) { | |
| Text("Welcome to") | |
| .foregroundStyle(.white) | |
| Text(Bundle.main.name) | |
| .foregroundStyle(.accent) | |
| } | |
| .font(.system(size: 45)) | |
| .fontWeight(.heavy) | |
| .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) | |
| } | |
| @ViewBuilder | |
| private func _details(_ title: String, _ desc: String) -> some View { | |
| VStack(alignment: .leading, spacing: 12) { | |
| Text(title) | |
| .font(.title) | |
| .bold() | |
| Text(desc) | |
| } | |
| .padding() | |
| .padding(.horizontal, 24) | |
| .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) | |
| } | |
| @ViewBuilder | |
| private func _button(_ title: String, action: @escaping () -> Void) -> some View { | |
| Button(action: { | |
| action() | |
| }) { | |
| Text(title) | |
| .frame(maxWidth: .infinity, maxHeight: .infinity) | |
| .background( | |
| LinearGradient( | |
| colors: [ | |
| .white, | |
| _page == 0 ? Color(hex: "776A89") : .secondary | |
| ], | |
| startPoint: .top, | |
| endPoint: .bottom | |
| ) | |
| ) | |
| .foregroundColor(.init(hex: "413258")) | |
| .clipShape( | |
| RoundedRectangle(cornerRadius: 12, style: .continuous) | |
| ) | |
| .bold() | |
| } | |
| .frame(height: 50) | |
| .shadow(color: .black.opacity(0.4), radius: 15, x: 0, y: 8) | |
| } | |
| private func _forward() { | |
| if _page != _pageLimit { | |
| _page += 1 | |
| } | |
| if _page == _pageLimit { | |
| // _onboardingFinished = true | |
| } | |
| } | |
| private func _backward() { | |
| if _page != 0 { | |
| _page -= 1 | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment