From d9c7aae268c8582a6883da8101bc4e6be405ed53 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 2 Jun 2026 10:24:31 -0400 Subject: [PATCH] =?UTF-8?q?feat(android):=20slim=20NowPlaying=20scrubber?= =?UTF-8?q?=20=E2=80=94=204dp=20track=20+=20tight=20slider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The M3 Slider default track is 16dp tall and the Slider itself expands to the 48dp interactive-component minimum, so the 14dp thumb we'd already shrunk to a flat circle was still sitting in the middle of a fat horizontal pill with lots of empty space above and below. Operator framing: "puffy, not a tool." Two changes: - Custom 4dp rounded track replaces SliderDefaults.Track. The thumb (14dp) now reads as visibly taller than the bar — the classic "handle on a string" cue that says "tool, draggable." Also drops M3's stop-indicator dot which the web scrubber doesn't have. - Clamp the Slider's vertical footprint to 20dp via Modifier. height. 14dp thumb + 3dp clearance each side, vs the default ~17dp empty above and below. Touch area stays usable since the drag axis is horizontal — pulling left/right anywhere on the thin bar feels natural, and Slider's gesture detector still responds to a tap anywhere along its row. Keeps an Android flavor (slightly thicker than the web's 2-3px hairline; rounded caps; accent fill) without reading as bulky. --- .../minstrel/player/ui/NowPlayingScreen.kt | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt index 468ff0ab..27399ac1 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -85,6 +86,9 @@ private const val COVER_MAX_WIDTH_DP = 320 private const val TRANSPORT_ICON_DP = 36 private const val PLAY_PAUSE_ICON_DP = 56 private const val POP_GRACE_MS = 500L +private val SCRUB_TRACK_HEIGHT_DP = 4.dp +private val SCRUB_TRACK_CORNER_DP = 2.dp +private val SCRUB_SLIDER_HEIGHT_DP = 20.dp // Vertical drag-down threshold (in pixels) past which the gesture // pops the player. Matches Flutter's 80px threshold in spirit; @@ -472,7 +476,12 @@ private fun ScrubberRow(positionMs: Long, durationMs: Long, onSeek: (Long) -> Un onValueChange = { newFraction -> if (durationMs > 0) onSeek((newFraction * durationMs).toLong()) }, - modifier = Modifier.fillMaxWidth(), + // Clamp the Slider's vertical footprint so the M3-default + // 48dp interactive-component padding doesn't leave the thumb + // floating in empty space above and below the track. 20dp = + // 14dp thumb + 3dp clearance each side; touch area is still + // wide enough since the drag axis is horizontal. + modifier = Modifier.fillMaxWidth().height(SCRUB_SLIDER_HEIGHT_DP), colors = sliderColors, interactionSource = interactionSource, // Plain filled circle to match the web client's ` Un .background(accent), ) }, + // Custom 4dp rounded track. M3's default Track is 16dp tall + // and reads as a heavy pill rather than a measurement line; + // making the thumb visibly taller than the track (14dp thumb + // on a 4dp bar) restores the "handle on a string" cue your + // eye reads as "tool, draggable." Also drops M3's stop + // indicator dot, which the web scrubber doesn't have. + track = { _ -> + Box(modifier = Modifier.fillMaxWidth().height(SCRUB_TRACK_HEIGHT_DP)) { + Box( + modifier = Modifier + .matchParentSize() + .clip(RoundedCornerShape(SCRUB_TRACK_CORNER_DP)) + .background(MaterialTheme.colorScheme.surfaceVariant), + ) + Box( + modifier = Modifier + .fillMaxWidth(fraction) + .fillMaxHeight() + .clip(RoundedCornerShape(SCRUB_TRACK_CORNER_DP)) + .background(accent), + ) + } + }, ) Row( modifier = Modifier.fillMaxWidth(),