PeachField.kt

3.7 KB · raw

1package com.peachpasswords.ui.components23import 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.padding10import androidx.compose.foundation.layout.width11import androidx.compose.foundation.text.BasicTextField12import androidx.compose.foundation.text.KeyboardOptions13import androidx.compose.material3.MaterialTheme14import 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.PeachSpacing32import com.peachpasswords.ui.theme.PeachType33import com.peachpasswords.ui.theme.peachColors3435@Composable36fun PeachField(37    label: String,38    value: String,39    onValueChange: (String) -> Unit,40    modifier: Modifier = Modifier,41    singleLine: Boolean = true,42    mono: Boolean = true,43    keyboardType: KeyboardType = KeyboardType.Text,44    visualTransformation: VisualTransformation = VisualTransformation.None,45    trailing: (@Composable () -> Unit)? = null,46) {47    val accent = LocalPeachAccent.current48    val interaction = remember { MutableInteractionSource() }49    val focused by interaction.collectIsFocusedAsState()50    // Gate 1: colorScheme.outline is PeachTheme's exact mapping of T3 — route51    // through it here so this primitive doesn't bypass the theme.52    val hairline = MaterialTheme.colorScheme.outline5354    Column(modifier.fillMaxWidth()) {55        Text(56            label.uppercase(),57            color = peachColors.T2,58            fontFamily = PeachType.Mono,59            fontSize = 9.sp,60            letterSpacing = 0.08.em,61        )62        Row(verticalAlignment = Alignment.CenterVertically) {63            BasicTextField(64                value = value,65                onValueChange = onValueChange,66                singleLine = singleLine,67                textStyle = TextStyle(68                    color = MaterialTheme.colorScheme.onSurface,69                    fontFamily = if (mono) PeachType.Mono else PeachType.Body,70                    fontSize = 13.sp,71                ),72                cursorBrush = SolidColor(accent),73                interactionSource = interaction,74                keyboardOptions = KeyboardOptions(keyboardType = keyboardType),75                visualTransformation = visualTransformation,76                modifier = Modifier77                    .weight(1f)78                    .drawBehind {79                        drawRect(80                            color = if (focused) accent else hairline,81                            topLeft = Offset(0f, size.height - 1.dp.toPx()),82                            size = Size(size.width, 1.dp.toPx()),83                        )84                    }85                    .padding(vertical = PeachSpacing.sm),86            )87            if (trailing != null) {88                Spacer(Modifier.width(PeachSpacing.sm))89                trailing()90            }91        }92    }93}