Skip to content

feat(designsystem): content-shaped skeletons, Coil crossfade pipeline… - #12

Merged
Prajwal-4121998 merged 1 commit into
developfrom
feature/designsystem-polish-loading-ux
Aug 4, 2026
Merged

Prajwal-4121998 merged 1 commit into
developfrom
feature/designsystem-polish-loading-ux

Conversation

@Prajwal-4121998

Copy link
Copy Markdown
Owner

…, dark theme fix, nav safety guards, bundled fonts
core:designsystem Polish — 2026 Production Loading UX
Summary

Upgrades loading states across Catalog, Detail, and the design system to content-shaped skeleton screens, a unified Coil image pipeline, and crossfade-based state transitions — replacing spinner-based loading with the pattern used by production catalog/e-commerce apps. Also fixes several real bugs surfaced during implementation: a silent no-op refresh, a dead retry button, a dark-mode theming bug affecting every screen, and double-tap navigation crashes.

What's included

Skeleton loading system

ProductCardSkeleton, SearchResultSkeleton, DetailSkeleton, CategoryChipRowSkeleton — content-shaped shimmer skeletons structurally locked to their real counterparts via shared *Defaults objects (ProductCardDefaults, SearchResultCardDefaults, DetailBottomBarDefaults) promoted to core:designsystem, eliminating drift risk between loading and loaded states
AnimatedContent-driven crossfades (Loading/Error/Empty/Content) on Catalog and Detail, keyed on enum-based contentState() derived state instead of raw booleans

Image pipeline

CatalogAsyncImage — unified Coil wrapper with theme-aware tonal placeholder and a distinct error state (muted broken-image icon over the same tonal background), replacing raw AsyncImage calls across feature:catalog, feature:detail, feature:search
Non-success visuals grouped into CatalogImagePlaceholders to keep the composable's parameter count under Detekt's LongParameterList threshold

Navigation

NavHost enter/exit/pop transitions with FastOutSlowInEasing
navigateSafely() / popBackStackSafely() extensions on NavController, gating navigation on back-stack entry RESUMED state — prevents duplicate navigation from rapid double-taps or multiple simultaneous triggers (two product cards tapped in quick succession, back button double-tapped)
Root Surface background added around NavHost to eliminate a white flash during slide transitions (window background gap)

Bug fixes found during implementation

CatalogViewModel.refreshProducts() was a no-op (set isRefreshing = true then immediately false with no actual fetch) — replaced with shared fetchProducts(showAsRefresh: Boolean), verified via verify(exactly = 2) { getProductsUseCase() } (previous test passed against the broken version — replaced, not just patched)
DetailViewModel had no RetryLoad intent — retry button on the error state did nothing; added intent + currentProductId tracking
DarkColorScheme had surfaceContainerLow/surfaceContainerLowest/surfaceContainerHigh wired to their light-mode color values instead of the *Dark variants — root cause of every screen (top bar, cards, bottom bar, chips) showing white/light backgrounds in dark mode despite correct dark values already being defined and unused

Other
Detekt fixes: CatalogAsyncImage parameter grouping (LongParameterList), DetailSkeleton split into sub-composables (LongMethod)
Testing
CatalogViewModelTest: replaced weak refresh test with call-count verification + a test asserting a failed refresh doesn't wipe existing products
Manual on-device pass: skeleton→content crossfades (light/dark), pull-to-refresh, rapid-tap navigation guard, retry flow, dark mode across all screens, image placeholder/error states under throttled network
Deferred (tracked, not lost)
App cold-start investigation (~7s gap on Android 13-and-below emulator, ViewModel init → first render) — narrowed to likely debug-build classloading cost; pending release-build/real-device timing confirmation. Baseline Profiles identified as the fix if confirmed.
Nav transition perceived lag — deferred to a dedicated Profiler session (Find CPU Hotspots)
Search screen loading skeleton — scoped out; existing debounce/typing rhythm judged sufficient
Detail bottom bar skeleton — implemented then reverted (low-dwell UI, snap is imperceptible; simplified via AnimatedVisibility reasoning, then dropped by scope decision)
lastUpdated staleness timestamp — implemented then removed; doesn't serve FakeStore's static data, reserved for WorkManager sync feedback later
Checklist
[] lintDevDebug passing
[]detekt passing
[]testDevDebugUnitTest passing
[]jacocoTestReport / jacocoTestCoverageVerification passing
[]assembleDevDebug passing
[]Manual verification on emulator (light + dark mode)

…, dark theme fix, nav safety guards, bundled fonts
@Prajwal-4121998
Prajwal-4121998 merged commit 824f71f into develop Aug 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant