From 379f794b4dda30c86f430f3ef7550eca865956f8 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 13 Aug 2026 11:29:11 -0400 Subject: [PATCH] feat(profile): add helper sublabel below display name input field Add an optional sublabel param to DisplayTextInput so the helper text is laid out inside the component's column, directly below the field. Apply the scaffold content padding to a wrapper column rather than the field so the sublabel hugs the entered text instead of being pushed far below it. --- .../flipcash/app/core/ui/DisplayTextInput.kt | 62 ++++++++++++------- .../core/src/main/res/values/strings.xml | 1 + .../internal/name/NameEntryScreen.kt | 47 +++++++------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/DisplayTextInput.kt b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/DisplayTextInput.kt index 846c4fd444..1a53a9b2dc 100644 --- a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/DisplayTextInput.kt +++ b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/DisplayTextInput.kt @@ -1,9 +1,12 @@ package com.flipcash.app.core.ui +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.InputTransformation import androidx.compose.foundation.text.input.KeyboardActionHandler import androidx.compose.foundation.text.input.TextFieldState +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -30,11 +33,15 @@ fun DisplayTextInput( placeholder: String, modifier: Modifier = Modifier, textModifier: Modifier = Modifier, + sublabel: String? = null, style: TextStyle = CodeTheme.typography.displayMedium.copy( color = CodeTheme.colors.textMain, fontWeight = FontWeight.SemiBold, ), placeholderStyle: TextStyle = style.copy(color = CodeTheme.colors.textTertiary), + sublabelStyle: TextStyle = CodeTheme.typography.textSmall.copy( + color = CodeTheme.colors.textSecondary, + ), minLines: Int = 1, maxLines: Int = 1, enabled: Boolean = true, @@ -42,27 +49,36 @@ fun DisplayTextInput( onKeyboardAction: KeyboardActionHandler? = null, inputTransformation: InputTransformation? = null, ) { - TextInput( - state = state, - modifier = modifier, - textModifier = textModifier, - placeholder = placeholder, - style = style, - placeholderStyle = placeholderStyle, - textFieldAlignment = Alignment.TopStart, - maxLines = maxLines, - minLines = minLines, - minHeight = 0.dp, - shape = RectangleShape, - enabled = enabled, - colors = inputColors( - backgroundColor = Color.Transparent, - borderColor = Color.Transparent, - unfocusedBorderColor = Color.Transparent, - placeholderColor = placeholderStyle.color, - ), - keyboardOptions = keyboardOptions, - onKeyboardAction = onKeyboardAction, - inputTransformation = inputTransformation, - ) + Column(verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x2)) { + TextInput( + state = state, + modifier = modifier, + textModifier = textModifier, + placeholder = placeholder, + style = style, + placeholderStyle = placeholderStyle, + textFieldAlignment = Alignment.TopStart, + maxLines = maxLines, + minLines = minLines, + minHeight = 0.dp, + shape = RectangleShape, + enabled = enabled, + colors = inputColors( + backgroundColor = Color.Transparent, + borderColor = Color.Transparent, + unfocusedBorderColor = Color.Transparent, + placeholderColor = placeholderStyle.color, + ), + keyboardOptions = keyboardOptions, + onKeyboardAction = onKeyboardAction, + inputTransformation = inputTransformation, + ) + + if (sublabel != null) { + Text( + text = sublabel, + style = sublabelStyle, + ) + } + } } diff --git a/apps/flipcash/core/src/main/res/values/strings.xml b/apps/flipcash/core/src/main/res/values/strings.xml index 3e91705fdf..a866509dbe 100644 --- a/apps/flipcash/core/src/main/res/values/strings.xml +++ b/apps/flipcash/core/src/main/res/values/strings.xml @@ -887,6 +887,7 @@ Start Receiving Tips What is your name? + This is how you\'ll appear to others Your Name This Name is Not Allowed Try a different name diff --git a/apps/flipcash/features/user-profile/src/main/kotlin/com/flipcash/app/userprofile/internal/name/NameEntryScreen.kt b/apps/flipcash/features/user-profile/src/main/kotlin/com/flipcash/app/userprofile/internal/name/NameEntryScreen.kt index 44dfa619b2..fd21dc810c 100644 --- a/apps/flipcash/features/user-profile/src/main/kotlin/com/flipcash/app/userprofile/internal/name/NameEntryScreen.kt +++ b/apps/flipcash/features/user-profile/src/main/kotlin/com/flipcash/app/userprofile/internal/name/NameEntryScreen.kt @@ -122,27 +122,32 @@ private fun NameEntryScreenContent( } ) { padding -> val focusRequester = remember { FocusRequester() } - DisplayTextInput( - state = state.nameFieldState, - placeholder = stringResource(R.string.hint_profileName), - modifier = Modifier - .fillMaxWidth() - .padding(padding) - .focusRequester(focusRequester), - textModifier = Modifier.sharedElementTransition( - transition = SharedTransition.CurrencyName, - ), - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Words, - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Done, - ), - onKeyboardAction = { - keyboard.hideIfVisible { - dispatchEvent(NameEntryViewModel.Event.CheckName) - } - }, - ) + // Apply the scaffold's content padding to the wrapper, not the field — + // padding on the field itself inflates its box and pushes the sublabel + // far below the entered text instead of letting it sit just underneath. + Column(modifier = Modifier.padding(padding)) { + DisplayTextInput( + state = state.nameFieldState, + placeholder = stringResource(R.string.hint_profileName), + sublabel = stringResource(R.string.subtitle_profileNameSelection), + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester), + textModifier = Modifier.sharedElementTransition( + transition = SharedTransition.CurrencyName, + ), + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Words, + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Done, + ), + onKeyboardAction = { + keyboard.hideIfVisible { + dispatchEvent(NameEntryViewModel.Event.CheckName) + } + }, + ) + } LaunchedEffect(Unit) { focusRequester.requestFocus()