diff --git a/app/src/main/java/com/rada/ui/library/LibraryScreen.kt b/app/src/main/java/com/rada/ui/library/LibraryScreen.kt index d9ee346..0dcf76d 100644 --- a/app/src/main/java/com/rada/ui/library/LibraryScreen.kt +++ b/app/src/main/java/com/rada/ui/library/LibraryScreen.kt @@ -79,6 +79,9 @@ import com.rada.data.repository.SortOrder import com.rada.ui.theme.AppearanceDialog import com.rada.ui.components.AppHomeButton import com.rada.ui.components.EqualizerBars +import com.rada.ui.theme.LocalReduceMotion +import com.rada.ui.theme.pressDip +import androidx.compose.foundation.interaction.MutableInteractionSource import com.rada.ui.theme.LocalTokens @OptIn(ExperimentalMaterial3Api::class) @@ -463,10 +466,12 @@ private fun SongListItem( onToggleFavorite: () -> Unit, onDelete: () -> Unit, ) { + val interaction = remember { MutableInteractionSource() } Row( modifier = Modifier .fillMaxWidth() - .clickable(onClick = onClick) + .pressDip(interaction, LocalReduceMotion.current) + .clickable(interactionSource = interaction, indication = androidx.compose.foundation.LocalIndication.current, onClick = onClick) .padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, ) { diff --git a/app/src/main/java/com/rada/ui/theme/Motion.kt b/app/src/main/java/com/rada/ui/theme/Motion.kt index d114d7e..eb7f622 100644 --- a/app/src/main/java/com/rada/ui/theme/Motion.kt +++ b/app/src/main/java/com/rada/ui/theme/Motion.kt @@ -1,5 +1,13 @@ package com.rada.ui.theme +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.animation.core.CubicBezierEasing @@ -107,3 +115,30 @@ fun metadataExit(reduce: Boolean): ExitTransition = /** Duration for press/feedback animations, zeroed under reduce motion. */ fun feedbackDuration(reduce: Boolean): Int = if (reduce) 0 else FeedbackMs + +// ── Press feedback ──────────────────────────────────────────────────────── +// Taps should feel physical before navigation resolves: the row dips +// (scale 0.97) on press and springs back on release. Transform-only, so +// it's cheap; zeroed under Reduce Motion by the caller. + + +/** + * Press-dip for list rows: scales to 0.97 while pressed. Use on rows that + * already have a clickable/combinedClickable modifier earlier in the chain. + */ +fun Modifier.pressDip( + interactionSource: MutableInteractionSource, + reduce: Boolean, +): Modifier = composed { + if (reduce) return@composed this + val pressed by interactionSource.collectIsPressedAsState() + val scale by animateFloatAsState( + targetValue = if (pressed) 0.97f else 1f, + animationSpec = androidx.compose.animation.core.tween( + durationMillis = if (pressed) 90 else 160, + easing = if (pressed) MotionExit else MotionArrival, + ), + label = "pressDip", + ) + this.graphicsLayer { scaleX = scale; scaleY = scale } +}