23df9cfbbe84

fix the real vault list bug: PeachSegmentedControl rendered every option as an equal-weight full-width accent-or-neutral pill (SMART and ALL both solid orange bars). Added PeachFilterPills (small content-sized accent pill for the active option, bare quiet text for the rest) matching the browser's actual restraint, and switched vault list's sort row to it. Consolidated the header from 4 stacked rows to 3 by folding the ALL/NOTES segmented control into a single toggle icon in the action cluster. Added explicit '9 entries' count matching browser's integrated count display. Tightened entry row vertical padding

time
2026-07-24 06:31 UTC · 3 months ago
machine
koh2
agent
claude-sonnet-5
session
critical-corrections-c1-c7
parent
ac11454ad814
2 files app/src/main/java/com/peachpasswords/ui/components/PeachSegmentedControl.kt+54 −0app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+35 −27
app/src/main/java/com/peachpasswords/ui/components/PeachSegmentedControl.kt+54 −0
@@ -12,6 +12,7 @@1212 import androidx.compose.runtime.Composable1313 import androidx.compose.ui.Alignment1414 import androidx.compose.ui.Modifier15+import androidx.compose.ui.draw.clip1516 import androidx.compose.ui.unit.dp1617 import com.peachpasswords.ui.theme.LocalPeachAccent1718 import com.peachpasswords.ui.theme.PeachSpacing@@ -61,6 +62,59 @@6162                         Text(segment.label.uppercase(), style = PeachType.sortPill)6263                     }6364                 }65+            }66+        }67+    }68+}69+70+/**71+ * Browser-matched quiet filter row: the active option gets one small,72+ * content-sized accent pill; every other option is bare text (no box,73+ * no fill) sitting quietly beside it. Distinct from [PeachSegmentedControl],74+ * which renders every option as an equal-weight full-width button — right for75+ * a real multi-way choice (entry type), wrong for a filter/sort row, where76+ * giving every option the same loud pill treatment reads as several accent77+ * moments stacked instead of one (SMART/A-Z/Z-A/RECENT in the browser).78+ */79+@Composable80+fun PeachFilterPills(81+    segments: List<PeachSegment>,82+    selectedKey: String,83+    onSelected: (String) -> Unit,84+    modifier: Modifier = Modifier,85+) {86+    val accent = LocalPeachAccent.current87+    Row(88+        modifier = modifier,89+        verticalAlignment = Alignment.CenterVertically,90+        horizontalArrangement = Arrangement.spacedBy(PeachSpacing.md),91+    ) {92+        segments.forEach { segment ->93+            val selected = segment.key == selectedKey94+            if (selected) {95+                Surface(96+                    color = accent,97+                    contentColor = peachColors.Bg,98+                    shape = RoundedCornerShape(999.dp),99+                ) {100+                    Text(101+                        segment.label.uppercase(),102+                        style = PeachType.sortPill,103+                        modifier = Modifier104+                            .clip(RoundedCornerShape(999.dp))105+                            .clickable { onSelected(segment.key) }106+                            .padding(horizontal = PeachSpacing.sm, vertical = PeachSpacing.xs),107+                    )108+                }109+            } else {110+                Text(111+                    segment.label.uppercase(),112+                    color = peachColors.T2,113+                    style = PeachType.sortPill,114+                    modifier = Modifier115+                        .clickable { onSelected(segment.key) }116+                        .padding(vertical = PeachSpacing.xs),117+                )64118             }65119         }66120     }

view file

app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+35 −27
@@ -36,6 +36,7 @@3636 import androidx.compose.foundation.shape.RoundedCornerShape3737 import androidx.compose.foundation.text.BasicTextField3838 import androidx.compose.material.icons.Icons39+import androidx.compose.material.icons.automirrored.outlined.Notes3940 import androidx.compose.material.icons.outlined.DeleteOutline4041 import androidx.compose.material.icons.outlined.FavoriteBorder4142 import androidx.compose.material.icons.outlined.Lock@@ -94,8 +95,8 @@9495 import com.peachpasswords.ui.sync.SyncViewModel9596 import com.peachpasswords.ui.PeachNav9697 import com.peachpasswords.ui.components.PeachEmptyOrEndState98+import com.peachpasswords.ui.components.PeachFilterPills9799 import com.peachpasswords.ui.components.PeachSegment98-import com.peachpasswords.ui.components.PeachSegmentedControl99100 import com.peachpasswords.ui.components.PeachTopBar100101 import com.peachpasswords.ui.components.FaviconInitials101102 import com.peachpasswords.ui.theme.LocalPeachAccent@@ -176,7 +177,7 @@176177             SearchBar(177178                 value = search,178179                 onChange = vm::setSearch,179-                count = if (search.isNotBlank()) "${entries.size}/$total" else "$total",180+                count = if (search.isNotBlank()) "${entries.size}/$total" else pluralEntries(total),180181             )181182             if (allTags.isNotEmpty()) {182183                 TagFilterStrip(@@ -412,6 +413,8 @@412413     }413414 }414415 416+private fun pluralEntries(total: Int): String = if (total == 1) "1 entry" else "$total entries"417+415418 @Composable416419 private fun SearchBar(value: String, onChange: (String) -> Unit, count: String) {417420     val accent = LocalPeachAccent.current@@ -457,7 +460,11 @@457460     onTrash: () -> Unit,458461 ) {459462     val hairline = peachColors.T3460-    Column(463+    // One row, matching the browser's single combined sort+actions bar — the464+    // notes-only filter used to get a whole second segmented control the same465+    // visual weight as the 4-way sort control; folded into a single toggle466+    // icon in the action cluster instead, same as trash/select/health.467+    Row(461468         modifier = Modifier462469             .fillMaxWidth()463470             .drawBehind {@@ -468,45 +475,36 @@468475                 )469476             }470477             .padding(horizontal = PeachSpacing.md, vertical = PeachSpacing.sm),471-        verticalArrangement = Arrangement.spacedBy(PeachSpacing.sm),478+        verticalAlignment = Alignment.CenterVertically,479+        horizontalArrangement = Arrangement.spacedBy(PeachSpacing.sm),472480     ) {473-        PeachSegmentedControl(481+        PeachFilterPills(474482             segments = SortOrder.entries.map { PeachSegment(it.name, it.label) },475483             selectedKey = active.name,476484             onSelected = { key ->477485                 SortOrder.entries.firstOrNull { it.name == key }?.let(onSort)478486             },487+            modifier = Modifier.weight(1f),479488         )480-        Row(481-            verticalAlignment = Alignment.CenterVertically,482-            horizontalArrangement = Arrangement.spacedBy(PeachSpacing.sm),483-        ) {484-            PeachSegmentedControl(485-                segments = listOf(486-                    PeachSegment("all", "All"),487-                    PeachSegment("notes", "Notes"),488-                ),489-                selectedKey = if (noteOnly) "notes" else "all",490-                onSelected = { key ->491-                    if ((key == "notes") != noteOnly) onToggleNote()492-                },493-                modifier = Modifier.weight(1f),494-            )495-            ActionCluster(496-                onHealth = onHealth,497-                onSelectMode = onSelectMode,498-                onTrash = onTrash,499-            )500-        }489+        ActionCluster(490+            noteOnly = noteOnly,491+            onToggleNote = onToggleNote,492+            onHealth = onHealth,493+            onSelectMode = onSelectMode,494+            onTrash = onTrash,495+        )501496     }502497 }503498 504499 @Composable505500 private fun ActionCluster(501+    noteOnly: Boolean,502+    onToggleNote: () -> Unit,506503     onHealth: () -> Unit,507504     onSelectMode: () -> Unit,508505     onTrash: () -> Unit,509506 ) {507+    val accent = LocalPeachAccent.current510508     Surface(511509         color = peachColors.S1,512510         contentColor = peachColors.T1,@@ -519,6 +517,16 @@519517             horizontalArrangement = Arrangement.spacedBy(PeachSpacing.xs),520518         ) {521519             ClusterIcon(520+                icon = {521+                    Icon(522+                        Icons.AutoMirrored.Outlined.Notes,523+                        contentDescription = "Notes only",524+                        tint = if (noteOnly) accent else peachColors.T1,525+                    )526+                },527+                onClick = onToggleNote,528+            )529+            ClusterIcon(522530                 icon = { Icon(Icons.Outlined.FavoriteBorder, contentDescription = "health") },523531                 onClick = onHealth,524532             )@@ -607,7 +615,7 @@607615                 )608616             }609617             .clickable(interactionSource = interaction, indication = null, onClick = onTap)610-            .padding(horizontal = 16.dp, vertical = 9.dp),618+            .padding(horizontal = 16.dp, vertical = 7.dp),611619         horizontalArrangement = Arrangement.spacedBy(10.dp),612620         verticalAlignment = Alignment.CenterVertically,613621     ) {

view file