9.0 KiB
Navigation 3 & Material 3 Adaptive — API Alignment Audit
Date: 2026-03-26
Status: Active
Scope: Adoption of Navigation 3 1.1.0-beta01 Scene APIs, transition metadata, ViewModel scoping, and Material 3 Adaptive integration.
Supersedes: navigation3-parity-2026-03.md Alpha04 Changelog section (versions updated).
Current Dependency Baseline
| Library | Version | Group |
|---|---|---|
| Navigation 3 UI | 1.1.0-beta01 |
org.jetbrains.androidx.navigation3:navigation3-ui |
| Navigation Event | 1.1.0-alpha01 |
org.jetbrains.androidx.navigationevent:navigationevent-compose |
| Lifecycle ViewModel Navigation3 | 2.11.0-alpha02 |
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-navigation3 |
| Material 3 Adaptive | 1.3.0-alpha06 |
org.jetbrains.compose.material3.adaptive:adaptive* |
| Material 3 Adaptive Navigation Suite | 1.11.0-alpha05 |
org.jetbrains.compose.material3:material3-adaptive-navigation-suite |
| Compose Multiplatform | 1.11.0-beta01 |
org.jetbrains.compose |
| Compose Multiplatform Material 3 | 1.11.0-alpha05 |
org.jetbrains.compose.material3:material3 |
API Audit: What's Available vs. What We Use
1. NavDisplay — Scene Architecture (available since 1.1.0-alpha04, stable in beta01)
Available APIs we're NOT using:
| API | Purpose | Status in project |
|---|---|---|
sceneStrategies: List<SceneStrategy<T>> |
Allows NavDisplay to render multi-pane Scenes | ✅ Used — DialogSceneStrategy, ListDetailSceneStrategy, SupportingPaneSceneStrategy, SinglePaneSceneStrategy |
SceneStrategy<T> interface |
Custom scene calculation from backstack entries | ✅ Used via built-in strategies |
DialogSceneStrategy |
Renders entry<T>(metadata = dialog()) entries as overlay Dialogs |
✅ Adopted |
SceneDecoratorStrategy<T> |
Wraps/decorates scenes with additional UI | ❌ Not used |
NavEntry.metadata |
Attaches typed metadata to entries (transitions, dialog hints, Scene classification) | ✅ Used — ListDetailSceneStrategy.listPane(), .detailPane(), .extraPane() |
NavDisplay.TransitionKey / PopTransitionKey / PredictivePopTransitionKey |
Per-entry custom transitions via metadata | ❌ Not used |
transitionSpec / popTransitionSpec / predictivePopTransitionSpec params |
Default transition animations for NavDisplay | ✅ Used — 350 ms crossfade |
sharedTransitionScope: SharedTransitionScope? |
Shared element transitions between scenes | ❌ Not used |
entryDecorators: List<NavEntryDecorator<T>> |
Wraps entry content with additional behavior | ✅ Used — SaveableStateHolderNavEntryDecorator + ViewModelStoreNavEntryDecorator |
APIs we ARE using correctly:
| API | Usage |
|---|---|
NavDisplay(backStack, entryProvider, modifier) |
Both app/Main.kt and desktop/DesktopMainScreen.kt |
rememberNavBackStack(SavedStateConfiguration, startKey) |
Backstack persistence |
entryProvider<NavKey> { entry<T> { ... } } |
All feature graph registrations |
NavigationBackHandler from navigationevent-compose |
Used with ListDetailSceneStrategy |
2. ViewModel Scoping (lifecycle-viewmodel-navigation3 2.11.0-alpha02)
Key finding: The ViewModelStoreNavEntryDecorator is available and provides automatic per-entry ViewModel scoping tied to backstack lifetime. The project passes it as an entryDecorator to NavDisplay via MeshtasticNavDisplay in core:ui/commonMain.
ViewModels obtained via koinViewModel() inside entry<T> blocks are scoped to the entry's backstack lifetime and automatically cleared when the entry is popped.
3. Material 3 Adaptive — Nav3 Scene Integration
Key finding: The JetBrains adaptive-navigation3 artifact at 1.3.0-alpha06 includes ListDetailSceneStrategy and SupportingPaneSceneStrategy. The project uses both via rememberListDetailSceneStrategy and rememberSupportingPaneSceneStrategy in MeshtasticNavDisplay, with draggable pane dividers via VerticalDragHandle + paneExpansionDraggable.
This means the project successfully uses the M3 Adaptive Scene bridge through NavDisplay(sceneStrategies = ...). Feature entries annotate themselves with ListDetailSceneStrategy.listPane(), .detailPane(), or .extraPane() metadata.
When to revisit: Monitor the JetBrains adaptive fork for MaterialListDetailSceneStrategy inclusion. It will likely arrive when the JetBrains fork catches up to the AndroidX 1.3.0-alpha09+ feature set.
4. NavigationSuiteScaffold (1.11.0-alpha05)
Status: ✅ Adopted (2026-03-26). MeshtasticNavigationSuite now uses NavigationSuiteScaffold with calculateFromAdaptiveInfo() and custom NavigationSuiteType coercion. No further alignment needed.
Prioritized Opportunities
P0: Add ViewModelStoreNavEntryDecorator to NavDisplay (high-value, low-risk)
Status: ✅ Adopted (2026-03-26). Each backstack entry now gets its own ViewModelStoreOwner via rememberViewModelStoreNavEntryDecorator(). ViewModels obtained via koinViewModel() are automatically cleared when their entry is popped. Encapsulated in MeshtasticNavDisplay in core:ui/commonMain.
Impact: Fixes subtle ViewModel leaks where popped entries retain their ViewModel in the Activity/Window store. Eliminates the need for manual key = "metrics-$destNum" ViewModel keying patterns over time.
P1: Add default NavDisplay transitions (medium-value, low-risk)
Status: ✅ Adopted (2026-03-26). A shared 350 ms crossfade (fadeIn + fadeOut) is applied for both forward and pop navigation via MeshtasticNavDisplay. This replaces the library's platform defaults (Android: 700 ms fade; Desktop: no animation) with a faster, consistent transition.
Impact: Immediate UX improvement on both Android and Desktop. Desktop now has visible navigation transitions.
P2: Adopt DialogSceneStrategy for navigation-driven dialogs (medium-value, medium-risk)
Status: ✅ Adopted (2026-03-26). MeshtasticNavDisplay includes DialogSceneStrategy in sceneStrategies before SinglePaneSceneStrategy. Feature modules can now use entry<T>(metadata = DialogSceneStrategy.dialog()) { ... } to render entries as overlay Dialogs with proper backstack lifecycle and predictive-back support.
Impact: Cleaner dialog lifecycle management available for future dialog routes. Existing dialogs via AlertHost are unaffected.
Consolidation: MeshtasticNavDisplay shared wrapper
Status: ✅ Adopted (2026-03-26). A new MeshtasticNavDisplay composable in core:ui/commonMain encapsulates the standard NavDisplay configuration:
- Entry decorators:
rememberSaveableStateHolderNavEntryDecorator+rememberViewModelStoreNavEntryDecorator - Scene strategies:
DialogSceneStrategy+SinglePaneSceneStrategy - Transition specs: 350 ms crossfade (forward + pop)
Both app/Main.kt and desktop/DesktopMainScreen.kt now call MeshtasticNavDisplay instead of configuring NavDisplay directly. The lifecycle-viewmodel-navigation3 dependency was moved from host modules to core:ui.
P3: Per-entry transition metadata (low-value until Scene adoption)
Individual entries can declare custom transitions via entry<T>(metadata = NavDisplay.transitionSpec { ... }). This is most useful when different route types should animate differently (e.g., detail screens slide in, settings screens fade).
Impact: Polish improvement. Low priority until default transitions (P1) are established. Now unblocked by P1 adoption.
Deferred: Custom Scene strategies
The ListDetailSceneStrategy and SupportingPaneSceneStrategy are adopted and working. Consider writing additional custom SceneStrategy implementations for specialized layouts (e.g., three-pane "Power User" scenes) as the Navigation 3 Scene API matures.
Decision
Adopt P0 (ViewModel scoping) and P1 (default transitions) now. Defer P2/P3 and Scene-based multi-pane until the JetBrains adaptive fork adds MaterialListDetailSceneStrategy.
Updated 2026-03-26: P0, P1, and P2 adopted and consolidated into MeshtasticNavDisplay in core:ui/commonMain. P3 (per-entry transitions) is available for incremental adoption by feature modules. Scene-based multi-pane remains deferred.
References
- Navigation 3 source:
navigation3-ui1.1.0-beta01(inspected from Gradle cache) NavDisplay.kt(upstream)SceneStrategy.kt(upstream)- Material 3 Adaptive JetBrains fork:
org.jetbrains.compose.material3.adaptive1.3.0-alpha06