ワンクリックで
kmp-navigation
Navigation libraries for KMP. Voyager, Decompose, and platform-specific navigation (Compose Navigation, SwiftUI).
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Navigation libraries for KMP. Voyager, Decompose, and platform-specific navigation (Compose Navigation, SwiftUI).
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Core Android development patterns for Kotlin, including coroutines, lifecycle management, and functional programming idioms.
Apple Combine framework for reactive programming. Publishers, subscribers, operators, and error handling.
Pattern extraction and skill generation for mobile development sessions. Automatically learns from your coding patterns.
Instinct-based learning system with confidence scoring for mobile patterns. Automatically extracts and evolves patterns.
Core Data for iOS persistence. Data models, fetch requests, background contexts, and SwiftData migration.
Kotlin Coroutines and Flow patterns for structured concurrency, error handling, and async operations.
| name | kmp-navigation |
| description | Navigation libraries for KMP. Voyager, Decompose, and platform-specific navigation (Compose Navigation, SwiftUI). |
Cross-platform navigation strategies for Kotlin Multiplatform.
// build.gradle.kts
dependencies {
implementation("cafe.adriel.voyager:voyager-navigator:1.0.0")
implementation("cafe.adriel.voyager:voyager-screen-model:1.0.0")
}
// commonMain/kotlin/navigation/VoyagerNavigation.kt
@Serializable
data object HomeScreen : Screen
@Serializable
data class DetailScreen(val id: String) : Screen
@Composable
fun AppNavigation() {
Navigator(HomeScreen) { navigator ->
VoyagerNavigation(
navigator = navigator,
screenModels = { rememberScreenModel { AppScreenModel() } }
)
}
}
@Composable
fun HomeScreen() {
Screen { // Voyager's Screen composable
val navigator = LocalNavigator.currentOrThrow
Button(onClick = { navigator.push(DetailScreen("123")) }) {
Text("Go to Detail")
}
}
}
// build.gradle.kts
dependencies {
implementation("com.arkivanov.decompose:decompose:2.1.0")
implementation("com.arkivanov.decompose:extensions-compose-jetpack:2.1.0")
}
// commonMain/kotlin/navigation/DecomposeNavigation.kt
sealed class Config : Parcelable {
@Parcelize
data object Home : Config()
@Parcelize
data class Detail(val id: String) : Config()
}
@Composable
fun AppNavigation() {
val navigator = rememberNavigator()
Decomanavigation(
navigator = navigator,
initialConfiguration = Config.Home
) {
when (val config = it.configuration) {
is Config.Home -> HomeScreen(
onNavigateToDetail = { navigator.push(Config.Detail(it)) }
)
is Config.Detail -> DetailScreen(
id = config.id,
onBack = { navigator.pop() }
)
}
}
}
// commonMain/kotlin/navigation/Navigator.kt
sealed class Screen : Parcelable {
@Parcelize
data object Home : Screen()
@Parcelize
data class Detail(val id: String) : Screen()
}
interface Navigator {
val navigationStack: StateFlow<List<Screen>>
fun navigateTo(screen: Screen)
fun navigateBack()
}
expect class Navigator() : Navigator
// androidMain - Compose Navigation
actual class Navigator : Navigator {
private val _stack = MutableStateFlow(listOf(Screen.Home))
override val navigationStack: StateFlow<List<Screen>> = _stack.asStateFlow()
@Composable
fun SetupNavigation() {
val navController = rememberNavController()
NavHost(navController, startDestination = "home") {
composable("home") {
HomeScreen(
onNavigateToDetail = { navController.navigate("detail/$it") }
)
}
composable("detail/{id}") { backStackEntry ->
val id = backStackEntry.arguments?.getString("id") ?: ""
DetailScreen(id, onBack = { navController.popBackStack() })
}
}
}
}
// iosMain - SwiftUI Navigation wrapper
actual class Navigator : Navigator {
private val _stack = MutableStateFlow(listOf(Screen.Home))
override val navigationStack: StateFlow<List<Screen>> = _stack.asStateFlow()
fun toSwiftUI() -> some View {
// Bridge to SwiftUI NavigationStack
}
}
// commonMain/kotlin/navigation/TabNavigation.kt
enum class Tab {
HOME,
SEARCH,
PROFILE
}
@Composable
fun TabNavigation() {
val navigator = rememberTabNavigator()
TabNavigator(tab = navigator.current) {
// Tab content
}
}
// commonMain/kotlin/navigation/Tabs.kt
enum class Tab {
HOME,
SEARCH,
PROFILE
}
@Composable
fun Tabs(
navigator: StackNavigator,
selectedTab: MutableState<Tab>
) {
Row {
Tab.values().forEach { tab ->
Button(
onClick = { selectedTab.value = tab }
) {
Text(tab.name)
}
}
}
}
// commonMain/kotlin/navigation/DeepLink.kt
sealed class Screen : Parcelable {
@Parcelize
data object Home : Screen()
@Parcelize
data class Detail(val id: String) : Screen()
companion object {
fun fromDeepLink(url: String): Screen? {
return when {
url.contains("/home") -> Home
"/detail/([a-z0-9]+)".toRegex().find(url) != null -> {
val id = "/detail/([a-z0-9]+)".toRegex().find(url)!!.groupValues[1]
Detail(id)
}
else -> null
}
}
}
}
// ✅ Sealed class with arguments
@Serializable
sealed class Screen : Parcelable {
@Parcelize
data object Home : Screen()
@Parcelize
data class UserDetail(
val userId: String,
val section: String? = null
) : Screen()
@Parcelize
data class EditItem(
val itemId: String,
val mode: EditMode = EditMode.View
) : Screen()
}
@Serializable
enum class EditMode {
View, Edit, Create
}
class DetailScreenModel(
private val userId: String,
private val repository: UserRepository
) : ScreenModel {
val user = mutableStateOf<User?>(null)
val isLoading = mutableStateOf(false)
init {
loadUser()
}
private fun loadUser() {
viewModelScope.launch {
isLoading.value = true
user.value = repository.getUser(userId)
isLoading.value = false
}
}
}
@Composable
fun DetailScreen(
userId: String,
onBack: () -> Unit
) {
val model = rememberScreenModel { DetailScreenModel(userId) }
if (model.isLoading.value) {
CircularProgressIndicator()
} else {
model.user.value?.let { user ->
UserContent(user, onBack)
}
}
}
Remember: Choose navigation library based on project needs. Voyager for simplicity, Decompose for control, platform-native for full platform feature support.