carson-katri / router

Type-safe routing in SwiftUI
23 stars 0 forks source link

Router

Typesafe routing for SwiftUI.

Note: This package is still being designed, so the API may change, and the example below may not match the current API 100%.

First, declare your routes in an enum:

enum AppRoutes: Routes {
  case orders
  case search(query: String, category: SearchCategory) // You can include Codable types
  case orderDetails(orderId: Int, OrderRoutes?) // and subroutes

  static let defaultRoute: Self = .orders // Set a default Route
}

enum OrderRoutes: Routes {
  case overview
  case bill

  static let defaultRoute: Self = .overview
}

enum SearchCategory: Int, Codable {
  case breakfast, lunch, dinner
}

Then use the Router and Route Views to allow for navigation:

struct ContentView: View {
  var body: some View {
    Router(AppRoutes.self) {
      Route(AppRoutes.orders) { OrdersView() }
      Route(AppRoutes.search) { route in
        if case let .search(query, category) = route { SearchView(query, category) }
      }
      // Omit any associated values from the Route definition, and access them from the closure.
      Route(AppRoutes.orderDetails) { route in
        if case let .orderDetails(orderId, _) = route {
          // Declare sub-Routers for deeper navigation.
          Router(OrderRoutes.self) {
            Route(OrderRoutes.overview) { OrderOverview(orderId) }
            Route(OrderRoutes.bill) { OrderBill(orderId) }
          }
        }
      }
    }
  }
}

Then provide RouterLinks to navigate to your new Routes:

struct OrdersView: View {
  var body: some View {
    List(DataSource.orders) {
      RouterLink($0.name, destination: AppRoutes.orderDetails(orderId: $0.id, .overview))
    }
  }
}

You can also navigate using a String (not yet implemented):

struct MyApp: App {
  @Router var navigator

  var body: some Scene {
    WindowGroup("MyApp") {
      ContentView()
        .onOpenURL {
          if let path = $0.path {
            navigator.navigate(to: path)
          }
        }
    }
  }
}