PeachField.kt

4.2 KB · raw

1package com.peachpasswords.ui.vault23import androidx.compose.foundation.interaction.MutableInteractionSource4import androidx.compose.foundation.interaction.collectIsFocusedAsState5import androidx.compose.foundation.layout.Column6import androidx.compose.foundation.layout.Row7import androidx.compose.foundation.layout.Spacer8import androidx.compose.foundation.layout.fillMaxWidth9import androidx.compose.foundation.layout.height10import androidx.compose.foundation.layout.padding11import androidx.compose.foundation.layout.width12import androidx.compose.foundation.text.BasicTextField13import androidx.compose.foundation.text.KeyboardOptions14import androidx.compose.material3.Text15import androidx.compose.runtime.Composable16import androidx.compose.runtime.getValue17import androidx.compose.runtime.remember18import androidx.compose.ui.Alignment19import androidx.compose.ui.Modifier20import androidx.compose.ui.draw.drawBehind21import androidx.compose.ui.geometry.Offset22import androidx.compose.ui.geometry.Size23import androidx.compose.ui.graphics.SolidColor24import androidx.compose.ui.text.TextStyle25import androidx.compose.ui.text.input.KeyboardType26import androidx.compose.ui.text.input.VisualTransformation27import androidx.compose.ui.unit.dp28import androidx.compose.ui.unit.em29import androidx.compose.ui.unit.sp30import com.peachpasswords.ui.theme.LocalPeachAccent31import com.peachpasswords.ui.theme.peachColors32import com.peachpasswords.ui.theme.PeachType3334/**35 * The Peach text field used across the entry-edit screens: a bare underline (no36 * border box), drawn in t3 and lit to the accent while focused — matching the37 * lock screen's credential inputs. Label is IBM Plex Mono 9sp, uppercase, t2,38 * with 0.08em tracking.39 *40 * Replaces the old boxed `Field`/`CardField` primitives so every new-entry input41 * shares one underline style (brief Fix 6).42 */43@Composable44fun PeachField(45    label: String,46    value: String,47    onChange: (String) -> Unit,48    modifier: Modifier = Modifier,49    singleLine: Boolean = true,50    mono: Boolean = true,51    keyboardType: KeyboardType = KeyboardType.Text,52    visualTransformation: VisualTransformation = VisualTransformation.None,53    labelTrailing: (@Composable () -> Unit)? = null,54    trailing: (@Composable () -> Unit)? = null,55) {56    val accent = LocalPeachAccent.current57    val interaction = remember { MutableInteractionSource() }58    val focused by interaction.collectIsFocusedAsState()59    val hairline = peachColors.T360    Column(modifier.fillMaxWidth().padding(bottom = 14.dp)) {61        Row(verticalAlignment = Alignment.CenterVertically) {62            Text(63                label.uppercase(),64                color = peachColors.T2,65                fontFamily = PeachType.Mono,66                fontSize = 9.sp,67                letterSpacing = 0.08.em,68            )69            if (labelTrailing != null) {70                Spacer(Modifier.width(8.dp))71                labelTrailing()72            }73        }74        Spacer(Modifier.height(6.dp))75        Row(verticalAlignment = Alignment.CenterVertically) {76            BasicTextField(77                value = value,78                onValueChange = onChange,79                singleLine = singleLine,80                textStyle = TextStyle(81                    color = peachColors.T0,82                    fontFamily = if (mono) PeachType.Mono else PeachType.Body,83                    fontSize = 13.sp,84                ),85                cursorBrush = SolidColor(accent),86                interactionSource = interaction,87                keyboardOptions = KeyboardOptions(keyboardType = keyboardType),88                visualTransformation = visualTransformation,89                modifier = Modifier90                    .weight(1f)91                    .drawBehind {92                        drawRect(93                            color = if (focused) accent else hairline,94                            topLeft = Offset(0f, size.height - 1.dp.toPx()),95                            size = Size(size.width, 1.dp.toPx()),96                        )97                    }98                    .padding(vertical = 8.dp),99            )100            if (trailing != null) {101                Spacer(Modifier.width(8.dp))102                trailing()103            }104        }105    }106}