MultiSelectUi.kt

4.1 KB · raw

1package com.peachpasswords.ui.vault23import androidx.compose.animation.animateColorAsState4import androidx.compose.foundation.background5import androidx.compose.foundation.border6import androidx.compose.foundation.clickable7import androidx.compose.foundation.layout.Arrangement8import androidx.compose.foundation.layout.Box9import androidx.compose.foundation.layout.Row10import androidx.compose.foundation.layout.Spacer11import androidx.compose.foundation.layout.fillMaxWidth12import androidx.compose.foundation.layout.height13import androidx.compose.foundation.layout.padding14import androidx.compose.foundation.layout.size15import androidx.compose.foundation.layout.statusBarsPadding16import androidx.compose.foundation.layout.width17import androidx.compose.foundation.shape.CircleShape18import androidx.compose.foundation.shape.RoundedCornerShape19import androidx.compose.material.icons.Icons20import androidx.compose.material.icons.rounded.Check21import androidx.compose.material3.Icon22import androidx.compose.material3.Text23import androidx.compose.runtime.Composable24import androidx.compose.runtime.getValue25import androidx.compose.ui.Alignment26import androidx.compose.ui.Modifier27import androidx.compose.ui.draw.clip28import androidx.compose.ui.graphics.Color29import androidx.compose.ui.unit.dp30import androidx.compose.ui.unit.sp31import com.peachpasswords.ui.theme.LocalPeachAccent32import com.peachpasswords.ui.theme.peachColors33import com.peachpasswords.ui.theme.PeachType3435/**36 * D12 multi-select per-row checkbox (spec §9). 20dp circle: unchecked = 1dp t237 * border on a transparent fill; checked = accent fill with a white check.38 */39@Composable40fun MultiSelectCheckbox(checked: Boolean, modifier: Modifier = Modifier) {41    val accent = LocalPeachAccent.current42    val fill by animateColorAsState(43        targetValue = if (checked) accent else Color.Transparent,44        label = "checkbox-fill",45    )46    Box(47        modifier = modifier48            .size(20.dp)49            .clip(CircleShape)50            .background(fill)51            .then(52                if (checked) Modifier53                else Modifier.border(1.dp, peachColors.T2, CircleShape),54            ),55        contentAlignment = Alignment.Center,56    ) {57        if (checked) {58            Icon(59                Icons.Rounded.Check,60                contentDescription = "selected",61                tint = Color.White,62                modifier = Modifier.size(13.dp),63            )64        }65    }66}6768/**69 * D12 multi-select top bar (spec §9). Replaces the wordmark/icons row while70 * [com.peachpasswords.ui.vault.VaultListViewModel.isMultiSelectMode] is on:71 * "[N] selected" + a breach-colored Delete + a t2 Cancel.72 */73@Composable74fun MultiSelectTopBar(75    count: Int,76    onDelete: () -> Unit,77    onCancel: () -> Unit,78) {79    Row(80        modifier = Modifier81            .fillMaxWidth()82            .statusBarsPadding()83            .height(56.dp)84            .padding(horizontal = 16.dp),85        verticalAlignment = Alignment.CenterVertically,86        horizontalArrangement = Arrangement.SpaceBetween,87    ) {88        Text(89            text = "$count selected",90            color = peachColors.T0,91            style = PeachType.bodyMono.copy(fontSize = 13.sp),92        )93        Row(verticalAlignment = Alignment.CenterVertically) {94            Text(95                text = "Delete",96                color = if (count > 0) peachColors.Breach else peachColors.T2,97                style = PeachType.labelMono.copy(fontSize = 11.sp),98                modifier = Modifier99                    .clip(RoundedCornerShape(4.dp))100                    .clickable(enabled = count > 0, onClick = onDelete)101                    .padding(horizontal = 8.dp, vertical = 6.dp),102            )103            Spacer(Modifier.width(8.dp))104            Text(105                text = "Cancel",106                color = peachColors.T2,107                style = PeachType.labelMono.copy(fontSize = 11.sp),108                modifier = Modifier109                    .clip(RoundedCornerShape(4.dp))110                    .clickable(onClick = onCancel)111                    .padding(horizontal = 8.dp, vertical = 6.dp),112            )113        }114    }115}