Skip to content

A modern, type-safe Swift router for SwiftUI navigation with a clean declarative API.

License

Notifications You must be signed in to change notification settings

DubonYaar/SnazzyRouter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SnazzyRouter ✨

A modern, type-safe router for SwiftUI with a clean declarative API

πŸ“¦ Installation

Swift Package Manager

Add SnazzyRouter to your project through Xcode:

  1. File β†’ Add Package Dependencies...
  2. Enter the package URL: https://github.com/DubonYaar/SnazzyRouter.git
  3. Click Add Package

Or add it to your Package.swift:

dependencies: [
    .package(url: "https://github.com/DubonYaar/SnazzyRouter.git", from: "1.0.1")
]

πŸš€ Quick Start

1. Define Your Routes

import SnazzyRouter
import SwiftUI

enum AppRoute: Routable {
    case home
    case profile(userId: String)
    case settings
    case detail(item: String)
  
    @ViewBuilder
    var view: some View {
        switch self {
        case .home:
            HomeView()
        case .profile(let userId):
            ProfileView(userId: userId)
        case .settings:
            SettingsView()
        case .detail(let item):
            DetailView(item: item)
        }
    }
}

2. Set Up Your Router

import SnazzyRouter
import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Router(AppRoute.self) { router in
                VStack {
                    Text("Welcome to SnazzyRouter!")
                        .font(.largeTitle)

                    Button("Go to Profile") {
                        router.push(.profile(userId: "123"))
                    }
                }
                .padding()
            }
        }
    }
}

3. Navigate from Child Views

import SnazzyRouter
import SwiftUI

struct ProfileView: View {
    let userId: String
    @Environment(RouterState<AppRoute>.self) var router
  
    var body: some View {
        VStack {
            Text("Profile: \(userId)")
        
            Button("Go to Settings") {
                router.push(.settings)
            }
        
            Button("Back") {
                router.pop()
            }
        
            Button("Back to Home") {
                router.popToRoot()
            }
        }
    }
}

πŸ“± Modal Presentations

SnazzyRouter supports all SwiftUI modal types:

import SnazzyRouter
import SwiftUI

struct HomeView: View {
    @Environment(RouterState<AppRoute>.self) var router
  
    var body: some View {
        VStack(spacing: 20) {
            // Sheet
            Button("Show Settings Sheet") {
                router.sheet = RouterModalItem(
                    destination: .settings,
                    dismiss: {
                        print("Settings dismissed")
                    }
                )
            }
        
            // Full Screen Cover
            Button("Show Full Screen") {
                router.fullScreenCover = RouterModalItem(
                    destination: .detail(item: "Important")
                )
            }
        
            // Popover (iPad)
            Button("Show Popover") {
                router.popover = RouterModalItem(
                    destination: .profile(userId: "popover")
                )
            }
        }
    }
}

πŸ”” Alerts & Confirmation Dialogs

Built-in support for alerts and confirmation dialogs:

import SnazzyRouter
import SwiftUI

struct SettingsView: View {
    @Environment(RouterState<AppRoute>.self) var router
  
    var body: some View {
        VStack(spacing: 20) {
            // Simple Alert
            Button("Show Alert") {
                router.showAlert(
                    Alert(
                        title: Text("Hello!"),
                        message: Text("This is a snazzy alert"),
                        dismissButton: .default(Text("OK"))
                    )
                )
            }
        
            // Confirmation Dialog
            Button("Show Options") {
                router.showConfirmationDialog(
                    title: "Choose an Action",
                    message: "What would you like to do?",
                    actions: [
                        DialogAction(title: "Edit") {
                            router.push(.profile(userId: "edit"))
                        },
                        DialogAction(title: "Delete", role: .destructive) {
                            print("Delete tapped")
                        },
                        DialogAction(title: "Cancel", role: .cancel) {
                            print("Cancelled")
                        }
                    ]
                )
            }
        }
    }
}

πŸ”— Programmatic Navigation

Access the router state directly for complex navigation logic:

import SnazzyRouter
import SwiftUI

struct DeepLinkHandler: View {
    @Environment(RouterState<AppRoute>.self) private var router
    
    var body: some View {
        Color.clear
            .onOpenURL { url in
                handleDeepLink(url: url)
            }
    }
    
    private func handleDeepLink(url: URL) {
        // Parse URL and navigate
        router.popToRoot()
        router.push(.profile(userId: "deep-link-user"))
    }
}

🎯 Advanced Usage

Custom Router State

You can create and manage your own router state:

import SnazzyRouter
import SwiftUI

@State private var routerState = RouterState<AppRoute>()

var body: some View {
    Router(AppRoute.self, provider: routerState) { router in
        // Your content
    }
}

πŸ“š Documentation

Core Types

  • Routable - Protocol for defining navigable destinations (requires Hashable, Identifiable, Equatable)
  • RouterState<D> - Observable state container for navigation
  • Router<D, Content> - Main view component for routing
  • RouterModalItem<D> - Modal presentation configuration
  • DialogAction - Action for confirmation dialogs
  • PopToMatch - Enum for specifying first or last occurrence (.first, .last)

Navigation Methods

  • push(_:) - Navigate to a destination
  • pop() - Go back one level
  • popToRoot() - Return to root view
  • popTo(_:match:) - Pop to a specific destination in the stack
  • showAlert(_:) - Display an alert
  • showConfirmationDialog(title:message:actions:) - Show confirmation dialog

Pop to Specific Destination

Use popTo(_:match:) to navigate back to a specific route in the navigation stack:

@Environment(RouterState<AppRoute>.self) var router

// Pop to the last occurrence of .settings (default)
router.popTo(.settings)

// Pop to the first occurrence of .settings
router.popTo(.settings, match: .first)

The match parameter accepts:

  • .last (default) - Pops to the most recent occurrence of the destination
  • .first - Pops to the earliest occurrence of the destination

If the destination is not found in the navigation stack, no action is taken.

Direct Path Access

You can directly access and manipulate the navigation path:

@Environment(RouterState<AppRoute>.self) var router

// Read the current navigation path
let currentPath = router.path

// Get the count of destinations in the stack
let stackDepth = router.path.count

// Check if a specific route is in the path
let hasSettings = router.path.contains(.settings)

// Manually set the entire path
router.path = [.home, .profile(userId: "123"), .settings]

// Remove specific items from the path
router.path.removeAll { $0 == .settings }

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

SnazzyRouter is available under the MIT license. See the LICENSE file for more info.

πŸ™ Acknowledgments

Built with ❀️ using SwiftUI and the power of snazziness.


Make your navigation snazzy!

About

A modern, type-safe Swift router for SwiftUI navigation with a clean declarative API.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages