diff --git a/CHANGELOG.md b/CHANGELOG.md index f784a29..322d9ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,8 +30,11 @@ are no binary releases; "version" tracks the shared `version` in the root build own thin themed `CrashReportActivity`. - **`identity`** (Android library) — the family's Material 3 Expressive theme factory `FloretExpressiveTheme(lightScheme, darkScheme, …)` (dynamic colour on - API 31+, system light/dark fallback, the standard motion scheme) plus - `rememberNavSlideSpec()`. Each app passes its own seed-derived colour schemes + API 31+, system light/dark fallback, the standard motion scheme) plus the + shared motion helpers — `rememberNavSlideSpec()`, the content transitions, + `Modifier.predictiveBack()` and `Modifier.animateContentSizeMotion()` (eases a + block's own height changes, e.g. a text field wrapping to a new line), each + reduced-motion-aware. Each app passes its own seed-derived colour schemes and typography — the mechanics are shared, the look is not. - **`components`** (Android library) — the shared Compose component vocabulary: - `GroupedSurface` / `GroupedRow` + `Position` / `positionOf` — the canonical diff --git a/identity/src/main/kotlin/de/jeanlucmakiola/floret/identity/Motion.kt b/identity/src/main/kotlin/de/jeanlucmakiola/floret/identity/Motion.kt index c02c1de..8431988 100644 --- a/identity/src/main/kotlin/de/jeanlucmakiola/floret/identity/Motion.kt +++ b/identity/src/main/kotlin/de/jeanlucmakiola/floret/identity/Motion.kt @@ -3,9 +3,12 @@ package de.jeanlucmakiola.floret.identity import android.provider.Settings import androidx.activity.BackEventCompat import androidx.activity.compose.PredictiveBackHandler +import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -14,6 +17,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import kotlin.coroutines.cancellation.CancellationException @@ -36,6 +40,21 @@ fun rememberReduceMotion(): Boolean { } } +/** + * Animates a composable's own size changes with the family's spatial motion, so + * a block that grows or shrinks — a text field wrapping to a new line, a value + * swapped for a longer one — eases into its new height instead of jumping. Wraps + * Compose's [androidx.compose.animation.animateContentSize] onto the active M3 + * Expressive motion scheme; under reduced motion the new size snaps in. + * + * Apply it high in the modifier chain of the element whose height changes. + */ +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun Modifier.animateContentSizeMotion(reduceMotion: Boolean = rememberReduceMotion()): Modifier = + if (reduceMotion) this + else animateContentSize(animationSpec = MaterialTheme.motionScheme.fastSpatialSpec()) + /** * The standard Android predictive-back transform for a full-screen surface: as * the back gesture is dragged, the surface scales toward ~90%, shifts toward the