I've been exploring Compose Multiplatform and went through the documentation, particularly Compose Multiplatform Navigation Routing. Despite the library being supported on the web, the docs mention that navigation and handling via routing is not yet supported.
Additionally, I reviewed Getting Started with Compose for Web and noticed that none of the demo projects showcase route navigation or changing the URL state dynamically. For instance, in a scenario where I click on a list item, I expect to navigate to that item's page with a new URL like "https://example.com/list/id", but this isn't demonstrated.
I've also checked the Compose for Web Slack channel but didn't find relevant queries. The documentation suggests other libraries like Voyager, Decompose, Appyx, PreCompose, and Circuit, but I haven't tried any yet.
Goal: I aim to run a single project on Web, iOS, and Android, meaning it should compile seamlessly across all platforms. Theoretically, I assume handling this through communication with native platforms is possible. Still, I'd appreciate confirmation on whether achieving this solely with Compose Multiplatform tools is not feasible at the moment.
If anyone has successfully implemented this or has insights into whether it’s possible with the mentioned libraries, please share your experience.
I created a YouTrack ticket (https://youtrack.jetbrains.com/issue/CMP-7336/Add-Routing-Support-for-Compose-Multiplatform-Web) for this issue and received a response indicating that this feature has been recently released in an “alpha” version. Here’s how to implement it:
Overview
The functionality is described in the corresponding pull request (https://github.com/JetBrains/compose-multiplatform-core/pull/1621#issue-2570681373). However, there were gaps in the documentation and setup. Here’s a step-by-step guide to get it working.
Setup
Follow the official Compose Navigation Routing documentation (https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-navigation-routing.html).
Use the dependency:
implementation("org.jetbrains.androidx.navigation:navigation-compose:2.8.0-alpha11")
I found this version recommendation in this comment (https://youtrack.jetbrains.com/issue/CMP-4983/is-compose-multiplatform-for-web-wasmJs-support-routing#focus=Comments-27-11342053.0-0). Do not follow auto-import suggestions in Android Studio as they will add androidx.navigation:navigation-compose
, which doesn’t work for Compose Multiplatform.
Ensure you’re using:
compose-multiplatform = "1.8.0-alpha01"
The default project wizard sets the stable version (1.7.0
), which might doesn’t support this feature.
What Didn’t Work • The sample project (https://github.com/JetBrains/compose-multiplatform/tree/master/examples/nav_cupcake) showcases web URL support but differs from the example in the pull request and was not functional for me.
Code Example
Here’s how I implemented it:
commonMain
enum class NavigationDestination {
Landing,
Book,
}
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import org.jetbrains.compose.ui.tooling.preview.Preview
@Composable
@Preview
fun App(
navController: NavHostController = rememberNavController()
) {
AppTheme {
NavHost(
navController = navController,
startDestination = NavigationDestination.Landing.name
) {
composable(route = NavigationDestination.Landing.name) {
LandingPage(onNavigateToBook = {
navController.navigate(NavigationDestination.Book.name)
})
}
composable(route = NavigationDestination.Book.name) {
Page()
}
}
}
}
wasmJsMain
Set up the web-specific logic:
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.ComposeViewport
import androidx.navigation.ExperimentalBrowserHistoryApi
import androidx.navigation.NavHostController
import androidx.navigation.bindToNavigation
import androidx.navigation.compose.rememberNavController
import kotlinx.browser.document
import kotlinx.browser.window
import org.w3c.dom.HTMLElement
@OptIn(ExperimentalComposeUiApi::class, ExperimentalBrowserHistoryApi::class)
fun main() {
val body: HTMLElement = document.body ?: return
ComposeViewport(body) {
val navController: NavHostController = rememberNavController()
App(navController = navController)
LaunchedEffect(Unit) {
window.bindToNavigation(navController)
}
}
}
With this setup, URL-based navigation is now functional for Compose Multiplatform Web in an alpha release.