design : removes usage of OutlinedTextField

This commit is contained in:
ganfra
2024-11-08 15:15:08 +01:00
parent a4b83fe024
commit 784b0a5c24
14 changed files with 116 additions and 386 deletions

View File

@@ -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)
}
},

View File

@@ -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)
)
}
}

View File

@@ -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(

View File

@@ -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),
)
}

View File

@@ -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(

View File

@@ -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,
)
},

View File

@@ -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),

View File

@@ -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)
)
}
}

View File

@@ -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
}

View File

@@ -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),
)
}

View File

@@ -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",
)
}
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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))
}
}
}
}
}