fix(android): uniform icon-only action buttons in playlist detail

Since the offline-download button was added, four buttons shared one row while Play
and Shuffle also carried text labels — the labels got squeezed out and the buttons
looked compressed. All four are now equal-width and icon-only (play, shuffle, edit,
download); Play stays filled as the primary action, the rest tint accent when
active/done. Icons carry contentDescriptions for accessibility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-07-19 17:21:41 +02:00
1 parent 9270d31608
commit 4503bbe54e
1 file changed
+17 -16
@@ -196,7 +196,10 @@ fun PlaylistDetailScreen(
} }
} }
// ── Play / Shuffle / Edit-mode row ──────────────────────────────── // ── Play / Shuffle / Edit / Download ──────────────────────────────
// Four buttons in one row left no room for labels (the Play/Shuffle text was being
// clipped away), so all four are equal-width and icon-only. Play stays filled as the
// primary action; the rest are outlined and tint accent when active/done.
Row( Row(
Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 12.dp), Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp), horizontalArrangement = Arrangement.spacedBy(10.dp),
@@ -206,35 +209,33 @@ fun PlaylistDetailScreen(
modifier = Modifier.weight(1f).height(46.dp), modifier = Modifier.weight(1f).height(46.dp),
colors = ButtonDefaults.buttonColors(containerColor = NsAccent, contentColor = Color.White), colors = ButtonDefaults.buttonColors(containerColor = NsAccent, contentColor = Color.White),
shape = RoundedCornerShape(14.dp), shape = RoundedCornerShape(14.dp),
contentPadding = PaddingValues(0.dp),
) { ) {
Icon(Icons.Default.PlayArrow, null, modifier = Modifier.size(20.dp)) Icon(Icons.Default.PlayArrow, "Abspielen", modifier = Modifier.size(22.dp))
Spacer(Modifier.width(6.dp))
Text("Play", fontFamily = Outfit, fontWeight = FontWeight.Bold, fontSize = 15.sp)
} }
OutlinedButton( OutlinedButton(
onClick = { if (pl.entry.isNotEmpty()) onPlay(pl.entry.shuffled(), 0) }, onClick = { if (pl.entry.isNotEmpty()) onPlay(pl.entry.shuffled(), 0) },
modifier = Modifier.weight(1f).height(46.dp), modifier = Modifier.weight(1f).height(46.dp),
border = ButtonDefaults.outlinedButtonBorder(enabled = true).copy(brush = SolidColor(NsAccent.copy(alpha = 0.55f))), border = ButtonDefaults.outlinedButtonBorder(enabled = true).copy(brush = SolidColor(NsAccent.copy(alpha = 0.55f))),
shape = RoundedCornerShape(14.dp), shape = RoundedCornerShape(14.dp),
contentPadding = PaddingValues(0.dp),
) { ) {
Icon(Icons.Default.Shuffle, null, modifier = Modifier.size(20.dp), tint = NsAccent) Icon(Icons.Default.Shuffle, "Zufällig abspielen", modifier = Modifier.size(20.dp), tint = NsAccent)
Spacer(Modifier.width(6.dp))
Text("Shuffle", fontFamily = Outfit, fontWeight = FontWeight.Bold, fontSize = 15.sp, color = NsAccent)
} }
// Toggle edit mode for removing songs // Toggle edit mode for removing songs
OutlinedButton( OutlinedButton(
onClick = { editMode = !editMode }, onClick = { editMode = !editMode },
modifier = Modifier.height(46.dp), modifier = Modifier.weight(1f).height(46.dp),
border = ButtonDefaults.outlinedButtonBorder(enabled = true).copy( border = ButtonDefaults.outlinedButtonBorder(enabled = true).copy(
brush = SolidColor(if (editMode) NsAccent else NsOnSurface3) brush = SolidColor(if (editMode) NsAccent else NsOnSurface3)
), ),
shape = RoundedCornerShape(14.dp), shape = RoundedCornerShape(14.dp),
contentPadding = PaddingValues(horizontal = 14.dp), contentPadding = PaddingValues(0.dp),
) { ) {
Icon( Icon(
if (editMode) Icons.Default.Done else Icons.Default.Edit, if (editMode) Icons.Default.Done else Icons.Default.Edit,
null, if (editMode) "Bearbeiten beenden" else "Titel entfernen",
modifier = Modifier.size(18.dp), modifier = Modifier.size(20.dp),
tint = if (editMode) NsAccent else NsOnSurface2, tint = if (editMode) NsAccent else NsOnSurface2,
) )
} }
@@ -242,17 +243,17 @@ fun PlaylistDetailScreen(
val dlDone = downloadGroup?.let { it.downloadedTracks >= it.totalTracks && it.totalTracks > 0 } ?: false val dlDone = downloadGroup?.let { it.downloadedTracks >= it.totalTracks && it.totalTracks > 0 } ?: false
OutlinedButton( OutlinedButton(
onClick = { if (!dlDone) vm.downloadPlaylist() }, onClick = { if (!dlDone) vm.downloadPlaylist() },
modifier = Modifier.height(46.dp), modifier = Modifier.weight(1f).height(46.dp),
border = ButtonDefaults.outlinedButtonBorder(enabled = true).copy( border = ButtonDefaults.outlinedButtonBorder(enabled = true).copy(
brush = SolidColor(if (dlDone) NsAccent else NsOnSurface3) brush = SolidColor(if (dlDone) NsAccent else NsOnSurface3)
), ),
shape = RoundedCornerShape(14.dp), shape = RoundedCornerShape(14.dp),
contentPadding = PaddingValues(horizontal = 14.dp), contentPadding = PaddingValues(0.dp),
) { ) {
when { when {
dlDone -> Icon(Icons.Default.CheckCircle, null, modifier = Modifier.size(18.dp), tint = NsAccent) dlDone -> Icon(Icons.Default.CheckCircle, "Offline verfügbar", modifier = Modifier.size(20.dp), tint = NsAccent)
isDownloading -> CircularProgressIndicator(modifier = Modifier.size(16.dp), strokeWidth = 2.dp, color = NsAccent) isDownloading -> CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp, color = NsAccent)
else -> Icon(Icons.Default.Download, null, modifier = Modifier.size(18.dp), tint = NsOnSurface2) else -> Icon(Icons.Default.Download, "Herunterladen", modifier = Modifier.size(20.dp), tint = NsOnSurface2)
} }
} }
} }