fix(client/android): a settings row's gaps are set, not inherited

One `spacedBy(4.dp)` was doing three different jobs in a settings row, and got
all of them wrong. The caption sat as close to its control as the override
marker did, so the row read as one undifferentiated stack — and the marker,
being the FIRST child of a card that already pads 16dp, added its own vertical
padding on top of that, so a marked row started with visibly double the gap
every other row has.

Each gap is now stated where it belongs: the marker has no vertical padding of
its own (it sits exactly at the card's padding, level with an unmarked row's
control) and owns the 6dp down to the field it annotates; the caption owns the
10dp up to it. Tighter above, roomier below — so the marker groups with its
control and the caption reads as a separate note rather than part of it.

The "Reset" hit area loses most of its vertical padding to make that work; it
keeps the horizontal padding and the full-width row, so the target is wide
rather than tall. Confirmed on glass, not just in the screenshots.
This commit is contained in:
2026-07-29 12:17:18 +02:00
parent 7f40afc525
commit 4803260aff
@@ -394,7 +394,14 @@ private fun OverrideBadge(field: String?) {
// One compact line. A `TextButton` here carried its own 48dp touch target and dwarfed both the // One compact line. A `TextButton` here carried its own 48dp touch target and dwarfed both the
// control it annotates and the caption under it; the reset keeps a generous padded hit area // control it annotates and the caption under it; the reset keeps a generous padded hit area
// instead, which is the right trade for a secondary action inside a dense settings list. // instead, which is the right trade for a secondary action inside a dense settings list.
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) { Row(
verticalAlignment = Alignment.CenterVertically,
// No vertical padding of its own: this row is the FIRST thing in a card whose column
// already pads 16dp, and anything added here reads as double the gap every other row has.
// The bottom padding is the badge's tie to the control it annotates — deliberately tighter
// than the gap down to the caption, so the marker groups upward with its own field.
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp),
) {
AccentDot(MaterialTheme.colorScheme.primary, size = 6) AccentDot(MaterialTheme.colorScheme.primary, size = 6)
Text( Text(
"Overridden", "Overridden",
@@ -409,7 +416,7 @@ private fun OverrideBadge(field: String?) {
modifier = Modifier modifier = Modifier
.clip(RoundedCornerShape(6.dp)) .clip(RoundedCornerShape(6.dp))
.clickable { scope.onReset(field) } .clickable { scope.onReset(field) }
.padding(horizontal = 10.dp, vertical = 6.dp), .padding(horizontal = 10.dp, vertical = 2.dp),
) )
} }
} }
@@ -876,7 +883,7 @@ private fun ToggleRow(
) { ) {
// Dim the labels when disabled so the row reads as inactive (the Switch dims itself). // Dim the labels when disabled so the row reads as inactive (the Switch dims itself).
val labelAlpha = if (enabled) 1f else 0.38f val labelAlpha = if (enabled) 1f else 0.38f
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { Column {
OverrideBadge(field) OverrideBadge(field)
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) { Column(Modifier.weight(1f)) {
@@ -940,7 +947,7 @@ private fun <T> SettingDropdown(
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
val selectedLabel = options.firstOrNull { it.first == selected }?.second val selectedLabel = options.firstOrNull { it.first == selected }?.second
?: options.firstOrNull()?.second.orEmpty() ?: options.firstOrNull()?.second.orEmpty()
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { Column {
OverrideBadge(field) OverrideBadge(field)
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) { ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
OutlinedTextField( OutlinedTextField(
@@ -970,6 +977,7 @@ private fun <T> SettingDropdown(
caption, caption,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 10.dp),
) )
} }
} }