Skip to main content

navigation-adaptive-ui

Best practices for Type-Safe Navigation (Nav 3) and Adaptive Layouts in Upnext. Use when this capability is needed.

Ir para a instalação

Informações da origem

Repositório
tomevault-io/skills-registry
Última atividade na origem
28 de abril de 2026 às 22:53
Idioma detectado do SKILL.md
inglês
Estrelas
1
Forks
0

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
2 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
navigation-adaptive-ui
description
Best practices for Type-Safe Navigation (Nav 3) and Adaptive Layouts in Upnext. Use when this capability is needed.
metadata
{"author":"akitikkx"}
# Navigation & Adaptive UI Skill This skill encapsulates the critical patterns for implementing adaptive layouts and navigation in the Upnext application. It specifically addresses "Gotchas" related to `ListDetailPaneScaffold` and Compose Navigation 3. ## 📱 Adaptive Layouts (List-Detail) Upnext uses `NavigableListDetailPaneScaffold` to support phones, tablets, and foldables. > [!NOTE] > Adaptive UI utilities, such as `WindowSizeClassUtil` and the `@ReferenceDevices` Preview annotation, are now centralized in the `:core:designsystem` module to prevent circular dependencies. Ensure feature modules depend on `:core:designsystem` to use them. ### ⚠️ Critical Rule: Navigator Mismatch **NEVER** use `rememberSupportingPaneScaffoldNavigator` with `NavigableListDetailPaneScaffold`. This causes back navigation conflicts and UI flickering. **✅ Correct Usage:** ```kotlin // MainScreen.kt val listDetailNavigator = rememberListDetailPaneScaffoldNavigator<Any>() NavigableListDetailPaneScaffold( navigator = listDetailNavigator, defaultBackBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange, // Let scaffold handle pane back // ... ) ``` ### Back Navigation The scaffold handles back navigation between panes (Detail -> List) automatically if `defaultBackBehavior` is set correctly. * **Do NOT** manually intercept back presses for pane navigation using `BackHandler` if the scaffold can handle it. * **Do** use `BackHandler` only for top-level destination changes (e.g., Explore -> Dashboard). ### Resetting Pane State (OAuth / Deep Links) When returning to the list view from an external intent (like an OAuth browser callback), the navigation graphs may become out of sync, leading to `IllegalArgumentException: Destination with route cannot be found`. * **Fix:** Route the detail pane to the `EmptyDetail` destination to gracefully clear the view. The scaffold will interpret the empty detail state and automatically jump back to the list cleanly logic! ```kotlin // Example callback reset mainNavController.navigate(Destinations.EmptyDetail) { popUpTo(Destinations.EmptyDetail) { inclusive = true } } ``` --- ## 🧭 Type-Safe Navigation (Nav 3) We use the official [Compose Navigation 3](https://developer.android.com/guide/navigation/design/type-safety) with Kotlin Serialization. ### 1. Defining Routes Routes are defined in `Destinations.kt` as `@Serializable` classes or objects. ```kotlin @Serializable object Dashboard : Destinations @Serializable data class ShowDetail( val showId: Long, val showTitle: String? ) : Destinations ``` ### 2. Navigating ```kotlin navController.navigate(Destinations.ShowDetail(showId = 123, showTitle = "Arcane")) ``` ### 3. Extracting Arguments (The "Title Unknown" Fix) To extract arguments (e.g., for a TopBar title), use `toRoute<T>()` on the `NavBackStackEntry`. **✅ Correct Pattern:** ```kotlin // AppNavigation.kt val currentEntry = navBackStackEntry val showTitle = if (currentEntry?.destination?.hasRoute<Destinations.ShowDetail>() == true) { try { currentEntry.toRoute<Destinations.ShowDetail>().showTitle } catch (e: Exception) { null } } else { null } ``` --- ## 🔧 Common Pitfalls ### "Title Unknown" * **Cause:** Hardcoding titles or failing to parse args from the current route. * **Fix:** Always attempt to extract the specific route args (like `ShowDetail`) when the destination matches. ### Infinite Navigation Loops * **Cause:** Updating state (like `isDetailFlowActive`) inside a `LaunchedEffect` that observes that same state without proper checks. * **Fix:** Ensure state updates only happen when the *target* state differs from *current* state. ### Lazy Grid Null Pointer Exceptions (Stream Drops) * **Cause:** Using aggressive non-null assertions (`!!`) on `LazyRow` or `LazyVerticalGrid` `items(list!!)` when the underlying data stream is briefly interrupted (e.g. during a Trakt logout where the Database momentarily clears its snapshot before the Viewmodel drops the authorization state). * **Fix:** Always use safe-unwrapping `.orEmpty()` on Compose list arguments, like `items(list.orEmpty())`, ensuring Compose safely renders zero items instead of instantly crashing the active Activity during auth transitions. ### Bottom Bar Visibility * **Rule:** The `NavigationSuiteScaffold` (Bottom Bar / Rail) should wrap the content. * **Logic:** The list-detail scaffold lives *inside* the navigation suite. --- > Converted and distributed by [TomeVault](https://tomevault.io/claim/akitikkx) — claim your Tome and manage your conversions. <!-- tomevault:4.0:skill_md:2026-04-11 -->
Ver no GitHub