diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index 7df20acb96..c98f7a6c0b 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -9,7 +9,9 @@ package io.element.android.features.logout.impl +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Spacer @@ -52,19 +54,18 @@ import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrgani import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.components.list.SwitchListItem +import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconButton -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.autofill -import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -257,26 +258,21 @@ private fun Content( ) } - Column( + Box( modifier = Modifier .fillMaxWidth() .padding(top = 16.dp), ) { - Text( - text = stringResource(CommonStrings.action_confirm_password), - style = ElementTheme.typography.fontBodySmMedium, - color = ElementTheme.colors.textSecondary, - ) var passwordVisible by remember { mutableStateOf(false) } if (isLoading) { // Ensure password is hidden when user submits the form passwordVisible = false } - OutlinedTextField( + TextField2( value = passwordFieldState, + label = stringResource(CommonStrings.action_confirm_password), readOnly = isLoading, modifier = Modifier - .padding(top = 8.dp) .fillMaxWidth() .onTabOrEnterKeyFocusNext(focusManager) .testTag(TestTags.loginPassword) @@ -293,9 +289,7 @@ private fun Content( passwordFieldState = sanitized eventSink(AccountDeactivationEvents.SetPassword(sanitized)) }, - placeholder = { - Text(text = stringResource(CommonStrings.common_password)) - }, + placeholder = stringResource(CommonStrings.common_password), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { val image = @@ -303,7 +297,7 @@ private fun Content( val description = if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - IconButton(onClick = { passwordVisible = !passwordVisible }) { + Box(modifier = Modifier.clickable { passwordVisible = !passwordVisible }) { Icon(imageVector = image, description) } }, diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index b73742c05b..e6cf8d23e7 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -60,8 +60,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.OutlinedButton -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.room.RoomType @@ -390,19 +390,13 @@ private fun DefaultLoadedContent( ) } else if (contentState.joinAuthorisationStatus is JoinAuthorisationStatus.CanKnock) { Spacer(modifier = Modifier.height(24.dp)) - OutlinedTextField( + TextField2( value = knockMessage, onValueChange = onKnockMessageUpdate, maxLines = 3, minLines = 3, - modifier = Modifier.fillMaxWidth() - ) - Text( - text = stringResource(R.string.screen_join_room_knock_message_description), - style = ElementTheme.typography.fontBodySmRegular, - color = ElementTheme.colors.textPlaceholder, - textAlign = TextAlign.Start, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + supportingText = stringResource(R.string.screen_join_room_knock_message_description) ) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt index a76a2afbea..38a97f0cad 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt @@ -7,6 +7,7 @@ package io.element.android.features.login.impl.screens.loginpassword +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -52,17 +53,15 @@ import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.form.textFieldState +import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconButton -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Scaffold -import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.autofill -import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -101,12 +100,12 @@ fun LoginPasswordView( Column( modifier = Modifier - .fillMaxSize() - .imePadding() - .padding(padding) - .consumeWindowInsets(padding) - .verticalScroll(state = scrollState) - .padding(start = 20.dp, end = 20.dp, bottom = 20.dp), + .fillMaxSize() + .imePadding() + .padding(padding) + .consumeWindowInsets(padding) + .verticalScroll(state = scrollState) + .padding(start = 20.dp, end = 20.dp, bottom = 20.dp), ) { // Title IconTitleSubtitleMolecule( @@ -140,8 +139,8 @@ fun LoginPasswordView( onClick = ::submit, enabled = state.submitEnabled || isLoading, modifier = Modifier - .fillMaxWidth() - .testTag(TestTags.loginContinue) + .fillMaxWidth() + .testTag(TestTags.loginContinue) ) Spacer(modifier = Modifier.height(48.dp)) } @@ -170,16 +169,10 @@ private fun LoginForm( val eventSink = state.eventSink Column { - Text( - text = stringResource(R.string.screen_login_form_header), - modifier = Modifier.padding(start = 16.dp), - style = ElementTheme.typography.fontBodyMdRegular, - ) - - Spacer(modifier = Modifier.height(8.dp)) - OutlinedTextField( + TextField2( + label = stringResource(R.string.screen_login_form_header), value = loginFieldState, - readOnly = isLoading, + enabled = !isLoading, modifier = Modifier .fillMaxWidth() .onTabOrEnterKeyFocusNext(focusManager) @@ -192,9 +185,7 @@ private fun LoginForm( eventSink(LoginPasswordEvents.SetLogin(sanitized)) } ), - placeholder = { - Text(text = stringResource(CommonStrings.common_username)) - }, + placeholder = stringResource(CommonStrings.common_username), onValueChange = { val sanitized = it.sanitize() loginFieldState = sanitized @@ -210,10 +201,14 @@ private fun LoginForm( singleLine = true, trailingIcon = if (loginFieldState.isNotEmpty()) { { - IconButton(onClick = { + Box(Modifier.clickable { loginFieldState = "" }) { - Icon(imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_clear)) + Icon( + imageVector = CompoundIcons.Close(), + contentDescription = stringResource(CommonStrings.action_clear), + tint = ElementTheme.colors.iconSecondary + ) } } } else { @@ -226,9 +221,9 @@ private fun LoginForm( passwordVisible = false } Spacer(Modifier.height(20.dp)) - OutlinedTextField( + TextField2( value = passwordFieldState, - readOnly = isLoading, + enabled = !isLoading, modifier = Modifier .fillMaxWidth() .onTabOrEnterKeyFocusNext(focusManager) @@ -246,18 +241,18 @@ private fun LoginForm( passwordFieldState = sanitized eventSink(LoginPasswordEvents.SetPassword(sanitized)) }, - placeholder = { - Text(text = stringResource(CommonStrings.common_password)) - }, + placeholder = stringResource(CommonStrings.common_password), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { val image = if (passwordVisible) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() val description = if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - - IconButton(onClick = { passwordVisible = !passwordVisible }) { - Icon(imageVector = image, description) + Box(Modifier.clickable { passwordVisible = !passwordVisible }) { + Icon( + imageVector = image, + contentDescription = description, + ) } }, keyboardOptions = KeyboardOptions( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt index 118f3611d0..63131d6845 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt @@ -9,6 +9,7 @@ package io.element.android.features.login.impl.screens.searchaccountprovider +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets @@ -23,7 +24,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable @@ -51,14 +51,12 @@ import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubti import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.form.textFieldState +import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconButton -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField -import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -86,10 +84,10 @@ fun SearchAccountProviderView( ) { padding -> Box( modifier = Modifier - .fillMaxSize() - .imePadding() - .padding(padding) - .consumeWindowInsets(padding) + .fillMaxSize() + .imePadding() + .padding(padding) + .consumeWindowInsets(padding) ) { LazyColumn(modifier = Modifier.fillMaxWidth(), state = rememberLazyListState()) { item { @@ -104,7 +102,7 @@ fun SearchAccountProviderView( // TextInput var userInputState by textFieldState(stateValue = state.userInput) val focusManager = LocalFocusManager.current - OutlinedTextField( + TextField2( value = userInputState, // readOnly = isLoading, modifier = Modifier @@ -126,7 +124,7 @@ fun SearchAccountProviderView( singleLine = true, trailingIcon = if (userInputState.isNotEmpty()) { { - IconButton(onClick = { + Box(Modifier.clickable { userInputState = "" eventSink(SearchAccountProviderEvents.UserInput("")) }) { @@ -139,9 +137,7 @@ fun SearchAccountProviderView( } else { null }, - supportingText = { - Text(text = stringResource(id = R.string.screen_account_provider_form_notice), color = MaterialTheme.colorScheme.secondary) - } + supportingText = stringResource(id = R.string.screen_account_provider_form_notice), ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt index 3ec347a5f0..b96bc3303e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt @@ -27,7 +27,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -39,9 +38,9 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.ui.strings.CommonStrings @@ -89,21 +88,16 @@ fun ReportMessageView( ) { Spacer(modifier = Modifier.height(20.dp)) - OutlinedTextField( + TextField2( value = state.reason, onValueChange = { state.eventSink(ReportMessageEvents.UpdateReason(it)) }, - placeholder = { Text(stringResource(R.string.screen_report_content_hint)) }, + placeholder = stringResource(R.string.screen_report_content_hint), + minLines = 3, enabled = !isSending, modifier = Modifier .fillMaxWidth() - .heightIn(min = 90.dp) - ) - Text( - text = stringResource(R.string.screen_report_content_explanation), - style = ElementTheme.typography.fontBodySmRegular, - color = MaterialTheme.colorScheme.secondary, - textAlign = TextAlign.Start, - modifier = Modifier.padding(top = 4.dp, bottom = 24.dp, start = 16.dp, end = 16.dp) + .heightIn(min = 90.dp), + supportingText = stringResource(R.string.screen_report_content_explanation), ) Row( diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt index de782e33c5..1b3c1a10fb 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt @@ -33,7 +33,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.poll.impl.R @@ -48,10 +47,10 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItemStyle -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.ui.strings.CommonStrings @@ -109,14 +108,10 @@ fun CreatePollView( ) { item { Column { - Text( - text = stringResource(id = R.string.screen_create_poll_question_desc), - modifier = Modifier.padding(start = 32.dp), - style = ElementTheme.typography.fontBodyMdRegular, - ) ListItem( headlineContent = { - OutlinedTextField( + TextField2( + label = stringResource(id = R.string.screen_create_poll_question_desc), value = state.question, onValueChange = { state.eventSink(CreatePollEvents.SetQuestion(it)) @@ -124,9 +119,7 @@ fun CreatePollView( modifier = Modifier .focusRequester(questionFocusRequester) .fillMaxWidth(), - placeholder = { - Text(text = stringResource(id = R.string.screen_create_poll_question_hint)) - }, + placeholder = stringResource(id = R.string.screen_create_poll_question_hint), keyboardOptions = keyboardOptions, ) } @@ -137,7 +130,7 @@ fun CreatePollView( val isLastItem = index == state.answers.size - 1 ListItem( headlineContent = { - OutlinedTextField( + TextField2( value = answer.text, onValueChange = { state.eventSink(CreatePollEvents.SetAnswer(index, it)) @@ -145,9 +138,7 @@ fun CreatePollView( modifier = Modifier .then(if (isLastItem) Modifier.focusRequester(answerFocusRequester) else Modifier) .fillMaxWidth(), - placeholder = { - Text(text = stringResource(id = R.string.screen_create_poll_answer_hint, index + 1)) - }, + placeholder = stringResource(id = R.string.screen_create_poll_answer_hint, index + 1), keyboardOptions = keyboardOptions, ) }, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt index 5048580da0..3457d62be7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.preferences.impl.R -import io.element.android.libraries.designsystem.components.LabelledOutlinedTextField import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -41,6 +40,7 @@ import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet import io.element.android.libraries.matrix.ui.components.EditableAvatarView @@ -112,7 +112,7 @@ fun EditUserProfileView( textAlign = TextAlign.Center, ) Spacer(modifier = Modifier.height(40.dp)) - LabelledOutlinedTextField( + TextField2( label = stringResource(R.string.screen_edit_profile_display_name), value = state.displayName, placeholder = stringResource(CommonStrings.common_room_name_placeholder), diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt index 9010523041..b7a37d670b 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt @@ -39,13 +39,12 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen import io.element.android.libraries.designsystem.components.preferences.PreferenceRow import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch import io.element.android.libraries.designsystem.components.preferences.PreferenceText +import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField -import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.ui.strings.CommonStrings @Composable @@ -70,17 +69,14 @@ fun BugReportView( ) Spacer(modifier = Modifier.height(16.dp)) PreferenceRow { - OutlinedTextField( + TextField2( value = descriptionFieldState, - modifier = Modifier.fillMaxWidth() - .onTabOrEnterKeyFocusNext(LocalFocusManager.current), + modifier = Modifier + .fillMaxWidth() + .onTabOrEnterKeyFocusNext(LocalFocusManager.current), enabled = isFormEnabled, - label = { - Text(text = stringResource(id = R.string.screen_bug_report_editor_placeholder)) - }, - supportingText = { - Text(text = stringResource(id = R.string.screen_bug_report_editor_description)) - }, + label = stringResource(id = R.string.screen_bug_report_editor_placeholder), + supportingText = stringResource(id = R.string.screen_bug_report_editor_description), onValueChange = { descriptionFieldState = it eventSink(BugReportEvents.SetDescription(it)) @@ -152,8 +148,8 @@ fun BugReportView( enabled = state.submitEnabled, showProgress = state.sending.isLoading(), modifier = Modifier - .fillMaxWidth() - .padding(top = 24.dp, bottom = 16.dp) + .fillMaxWidth() + .padding(top = 24.dp, bottom = 16.dp) ) } } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt index 49d545e457..3ae77f607e 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt @@ -7,6 +7,8 @@ package io.element.android.features.securebackup.impl.reset.password +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -25,14 +27,12 @@ import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.form.textFieldState +import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconButton -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField -import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.ui.strings.CommonStrings @Composable @@ -80,14 +80,13 @@ fun ResetIdentityPasswordView( @Composable private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Boolean) { var showPassword by remember { mutableStateOf(false) } - OutlinedTextField( + TextField2( modifier = Modifier .fillMaxWidth() .onTabOrEnterKeyFocusNext(LocalFocusManager.current), value = text, onValueChange = onTextChange, - label = { Text(stringResource(CommonStrings.common_password)) }, - placeholder = { Text(stringResource(R.string.screen_reset_encryption_password_placeholder)) }, + placeholder = stringResource(CommonStrings.common_password), singleLine = true, visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { @@ -96,13 +95,13 @@ private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Bool val description = if (showPassword) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - IconButton(onClick = { showPassword = !showPassword }) { + Box(Modifier.clickable { showPassword = !showPassword }) { Icon(imageVector = image, description) } }, isError = hasError, supportingText = if (hasError) { - { Text(stringResource(R.string.screen_reset_encryption_password_error)) } + stringResource(R.string.screen_reset_encryption_password_error) } else { null } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt index 7ebf2d0219..2a44385ff0 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt @@ -41,8 +41,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextField2 import io.element.android.libraries.designsystem.theme.components.autofill import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag @@ -62,7 +62,6 @@ internal fun RecoveryKeyView( ) { Text( text = stringResource(id = CommonStrings.common_recovery_key), - modifier = Modifier.padding(start = 16.dp), style = ElementTheme.typography.fontBodyMdRegular, ) RecoveryKeyContent(state, onClick, onChange, onSubmit) @@ -159,7 +158,7 @@ private fun RecoveryKeyFormContent( // Do not apply a visual transformation if the key has spaces, to let user enter passphrase if (keyHasSpace) VisualTransformation.None else RecoveryKeyVisualTransformation() } - OutlinedTextField( + TextField2( modifier = Modifier .fillMaxWidth() .testTag(TestTags.recoveryKey) @@ -179,7 +178,7 @@ private fun RecoveryKeyFormContent( keyboardActions = KeyboardActions( onDone = { onSubmit() } ), - label = { Text(text = stringResource(id = R.string.screen_recovery_key_confirm_key_placeholder)) } + placeholder = stringResource(id = R.string.screen_recovery_key_confirm_key_placeholder), ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt deleted file mode 100644 index 61463ccb15..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2023, 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only - * Please see LICENSE in the repository root for full details. - */ - -package io.element.android.libraries.designsystem.components - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import io.element.android.compound.theme.ElementTheme -import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField -import io.element.android.libraries.designsystem.theme.components.Text - -@Composable -fun LabelledOutlinedTextField( - label: String, - value: String, - onValueChange: (String) -> Unit, - modifier: Modifier = Modifier, - placeholder: String? = null, - singleLine: Boolean = false, - maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, - keyboardOptions: KeyboardOptions = KeyboardOptions.Default, -) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text( - modifier = Modifier.padding(horizontal = 16.dp), - style = ElementTheme.typography.fontBodyMdRegular, - color = MaterialTheme.colorScheme.primary, - text = label - ) - - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = value, - placeholder = placeholder?.let { { Text(placeholder) } }, - onValueChange = onValueChange, - singleLine = singleLine, - maxLines = maxLines, - keyboardOptions = keyboardOptions, - ) - } -} - -@PreviewsDayNight -@Composable -internal fun LabelledOutlinedTextFieldPreview() = ElementPreview { - Column { - LabelledOutlinedTextField( - label = "Room name", - value = "", - onValueChange = {}, - placeholder = "e.g. Product Sprint", - ) - LabelledOutlinedTextField( - label = "Room name", - value = "a room name", - onValueChange = {}, - placeholder = "e.g. Product Sprint", - ) - } -} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/TextFieldListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/TextFieldListItem.kt index f9201ec045..c5c05de4b8 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/TextFieldListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/TextFieldListItem.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.designsystem.components.list import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -18,7 +19,6 @@ import androidx.compose.ui.tooling.preview.Preview import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup -import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Text @Composable diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/OnTabOrEnterKeyFocusNext.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/OnTabOrEnterKeyFocusNext.kt new file mode 100644 index 0000000000..9d4c45977a --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/OnTabOrEnterKeyFocusNext.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.designsystem.modifiers + +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusDirection +import androidx.compose.ui.focus.FocusManager +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent +import androidx.compose.ui.input.key.type + +fun Modifier.onTabOrEnterKeyFocusNext(focusManager: FocusManager): Modifier = onPreviewKeyEvent { event -> + if (event.key == Key.Tab || event.key == Key.Enter) { + if (event.type == KeyEventType.KeyUp) { + focusManager.moveFocus(FocusDirection.Down) + } + true + } else { + false + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/OutlinedTextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/OutlinedTextField.kt deleted file mode 100644 index 97a6bcdd38..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/OutlinedTextField.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2023, 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only - * Please see LICENSE in the repository root for full details. - */ - -package io.element.android.libraries.designsystem.theme.components - -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.LocalTextStyle -import androidx.compose.material3.OutlinedTextFieldDefaults -import androidx.compose.material3.TextFieldColors -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusDirection -import androidx.compose.ui.focus.FocusManager -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.input.key.Key -import androidx.compose.ui.input.key.KeyEventType -import androidx.compose.ui.input.key.key -import androidx.compose.ui.input.key.onPreviewKeyEvent -import androidx.compose.ui.input.key.type -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage -import io.element.android.libraries.designsystem.preview.ElementPreviewDark -import io.element.android.libraries.designsystem.preview.ElementPreviewLight -import io.element.android.libraries.designsystem.preview.PreviewGroup -import io.element.android.libraries.designsystem.utils.allBooleans -import io.element.android.libraries.designsystem.utils.asInt - -@Composable -fun OutlinedTextField( - value: String, - onValueChange: (String) -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, - readOnly: Boolean = false, - textStyle: TextStyle = LocalTextStyle.current, - label: @Composable (() -> Unit)? = null, - placeholder: @Composable (() -> Unit)? = null, - leadingIcon: @Composable (() -> Unit)? = null, - trailingIcon: @Composable (() -> Unit)? = null, - supportingText: @Composable (() -> Unit)? = null, - isError: Boolean = false, - visualTransformation: VisualTransformation = VisualTransformation.None, - keyboardOptions: KeyboardOptions = KeyboardOptions.Default, - keyboardActions: KeyboardActions = KeyboardActions.Default, - singleLine: Boolean = false, - maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, - minLines: Int = 1, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - shape: Shape = OutlinedTextFieldDefaults.shape, - colors: TextFieldColors = OutlinedTextFieldDefaults.colors() -) { - androidx.compose.material3.OutlinedTextField( - value = value, - onValueChange = onValueChange, - modifier = modifier, - enabled = enabled, - readOnly = readOnly, - textStyle = textStyle, - label = label, - placeholder = placeholder, - leadingIcon = leadingIcon, - trailingIcon = trailingIcon, - supportingText = supportingText, - isError = isError, - visualTransformation = visualTransformation, - keyboardOptions = keyboardOptions, - keyboardActions = keyboardActions, - singleLine = singleLine, - maxLines = maxLines, - minLines = minLines, - interactionSource = interactionSource, - shape = shape, - colors = colors, - ) -} - -@Composable -fun OutlinedTextField( - value: TextFieldValue, - onValueChange: (TextFieldValue) -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, - readOnly: Boolean = false, - textStyle: TextStyle = LocalTextStyle.current, - label: @Composable (() -> Unit)? = null, - placeholder: @Composable (() -> Unit)? = null, - leadingIcon: @Composable (() -> Unit)? = null, - trailingIcon: @Composable (() -> Unit)? = null, - supportingText: @Composable (() -> Unit)? = null, - isError: Boolean = false, - visualTransformation: VisualTransformation = VisualTransformation.None, - keyboardOptions: KeyboardOptions = KeyboardOptions.Default, - keyboardActions: KeyboardActions = KeyboardActions.Default, - singleLine: Boolean = false, - maxLines: Int = Int.MAX_VALUE, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - shape: Shape = OutlinedTextFieldDefaults.shape, - colors: TextFieldColors = OutlinedTextFieldDefaults.colors() -) { - androidx.compose.material3.OutlinedTextField( - value = value, - onValueChange = onValueChange, - modifier = modifier, - enabled = enabled, - readOnly = readOnly, - textStyle = textStyle, - label = label, - placeholder = placeholder, - leadingIcon = leadingIcon, - trailingIcon = trailingIcon, - supportingText = supportingText, - isError = isError, - visualTransformation = visualTransformation, - keyboardOptions = keyboardOptions, - keyboardActions = keyboardActions, - singleLine = singleLine, - maxLines = maxLines, - interactionSource = interactionSource, - shape = shape, - colors = colors, - ) -} - -@OptIn(ExperimentalComposeUiApi::class) -fun Modifier.onTabOrEnterKeyFocusNext(focusManager: FocusManager): Modifier = onPreviewKeyEvent { event -> - if (event.key == Key.Tab || event.key == Key.Enter) { - if (event.type == KeyEventType.KeyUp) { - focusManager.moveFocus(FocusDirection.Down) - } - true - } else { - false - } -} - -@Preview(group = PreviewGroup.TextFields) -@Composable -internal fun OutlinedTextFieldsPreview() = ElementPreviewLight { ContentToPreview() } - -@Preview(group = PreviewGroup.TextFields) -@Composable -internal fun OutlinedTextFieldsDarkPreview() = ElementPreviewDark { ContentToPreview() } - -@Composable -@ExcludeFromCoverage -private fun ContentToPreview() { - Column(modifier = Modifier.padding(4.dp)) { - allBooleans.forEach { isError -> - allBooleans.forEach { enabled -> - allBooleans.forEach { readonly -> - OutlinedTextField( - onValueChange = {}, - label = { Text(text = "label") }, - value = "Hello er=${isError.asInt()}, en=${enabled.asInt()}, ro=${readonly.asInt()}", - isError = isError, - enabled = enabled, - readOnly = readonly, - ) - Spacer(modifier = Modifier.height(2.dp)) - } - } - } - } -}