Add asterisk as required indicator to TextField atoms
This commit is contained in:
parent
8f02a9e279
commit
9ea4d8045a
6 changed files with 189 additions and 13 deletions
|
@ -44,6 +44,27 @@ private fun LazyGridScope.textFieldOutlinedItems() {
|
|||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "Input text required") { state ->
|
||||
TextFieldOutlined(
|
||||
value = state.value,
|
||||
label = "Label",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "Input text required with error") { state ->
|
||||
TextFieldOutlined(
|
||||
value = state.value,
|
||||
label = "Label",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyGridScope.passwordTextFieldOutlinedItems() {
|
||||
|
@ -68,15 +89,36 @@ private fun LazyGridScope.passwordTextFieldOutlinedItems() {
|
|||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "Password disabled") { state ->
|
||||
WithRememberedState(input = "Password") { state ->
|
||||
TextFieldOutlinedPassword(
|
||||
value = state.value,
|
||||
label = "Password",
|
||||
label = "Password disabled",
|
||||
onValueChange = { state.value = it },
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "Password") { state ->
|
||||
TextFieldOutlinedPassword(
|
||||
value = state.value,
|
||||
label = "Password required",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "Password") { state ->
|
||||
TextFieldOutlinedPassword(
|
||||
value = state.value,
|
||||
label = "Password required with error",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyGridScope.emailTextFieldOutlinedItems() {
|
||||
|
@ -101,13 +143,34 @@ private fun LazyGridScope.emailTextFieldOutlinedItems() {
|
|||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "email@example.com disabled") { state ->
|
||||
WithRememberedState(input = "email@example.com") { state ->
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = state.value,
|
||||
label = "Email address",
|
||||
label = "Email address disabled",
|
||||
onValueChange = { state.value = it },
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "email@example.com") { state ->
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = state.value,
|
||||
label = "Email address required",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedState(input = "email@example.com") { state ->
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = state.value,
|
||||
label = "Email address required with error",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,67 @@ package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
|||
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
|
||||
internal fun selectLabel(label: String?): @Composable (() -> Unit)? {
|
||||
return if (label != null) {
|
||||
internal fun selectLabel(
|
||||
label: String?,
|
||||
isRequired: Boolean,
|
||||
): @Composable (() -> Unit)? {
|
||||
return if (label != null || isRequired) {
|
||||
{
|
||||
Text(text = label)
|
||||
TextFieldLabel(label.orEmpty(), isRequired)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun TextFieldLabel(
|
||||
label: String,
|
||||
isRequired: Boolean,
|
||||
) {
|
||||
Text(
|
||||
text = if (isRequired) {
|
||||
"$label$ASTERISK"
|
||||
} else {
|
||||
label
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private const val ASTERISK = "*"
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun TextFieldLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldLabel(
|
||||
label = "Label",
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun TextFieldLabelRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldLabel(
|
||||
label = "Label",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun TextFieldLabelRequiredEmptyLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldLabel(
|
||||
label = "",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ fun TextFieldOutlined(
|
|||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isRequired: Boolean = false,
|
||||
isError: Boolean = false,
|
||||
) {
|
||||
MaterialOutlinedTextField(
|
||||
|
@ -20,7 +21,7 @@ fun TextFieldOutlined(
|
|||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = selectLabel(label),
|
||||
label = selectLabel(label, isRequired),
|
||||
isError = isError,
|
||||
)
|
||||
}
|
||||
|
@ -71,3 +72,16 @@ internal fun TextFieldOutlinedErrorPreview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun TextFieldOutlinedRequiredPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
label = "Label",
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ fun TextFieldOutlinedEmailAddress(
|
|||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isRequired: Boolean = false,
|
||||
isError: Boolean = false,
|
||||
) {
|
||||
MaterialOutlinedTextField(
|
||||
|
@ -22,7 +23,7 @@ fun TextFieldOutlinedEmailAddress(
|
|||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = selectLabel(label),
|
||||
label = selectLabel(label, isRequired),
|
||||
isError = isError,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Email,
|
||||
|
|
|
@ -26,6 +26,7 @@ fun TextFieldOutlinedPassword(
|
|||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isRequired: Boolean = false,
|
||||
isError: Boolean = false,
|
||||
) {
|
||||
var passwordVisibilityState by rememberSaveable { mutableStateOf(false) }
|
||||
|
@ -35,7 +36,7 @@ fun TextFieldOutlinedPassword(
|
|||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = selectLabel(label),
|
||||
label = selectLabel(label, isRequired),
|
||||
trailingIcon = selectTrailingIcon(
|
||||
isEnabled = enabled,
|
||||
isPasswordVisible = passwordVisibilityState,
|
||||
|
|
|
@ -28,6 +28,7 @@ data class TextFieldTestData(
|
|||
modifier: Modifier,
|
||||
enabled: Boolean?,
|
||||
label: String?,
|
||||
isRequired: Boolean,
|
||||
) -> Unit,
|
||||
)
|
||||
|
||||
|
@ -49,6 +50,7 @@ class TextFieldKtTest(
|
|||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = null,
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -67,6 +69,7 @@ class TextFieldKtTest(
|
|||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = null,
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -82,6 +85,7 @@ class TextFieldKtTest(
|
|||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = false,
|
||||
label = null,
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -97,12 +101,45 @@ class TextFieldKtTest(
|
|||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithText(LABEL).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should show asterisk when isRequired is true`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
isRequired = true,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithText("$LABEL*").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not show asterisk when isRequired is false`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
isRequired = false,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithText("$LABEL*").assertDoesNotExist()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
|
||||
|
@ -110,7 +147,7 @@ class TextFieldKtTest(
|
|||
fun data(): List<TextFieldTestData> = listOf(
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlined",
|
||||
content = { value, onValueChange, modifier, enabled, label ->
|
||||
content = { value, onValueChange, modifier, enabled, label, isRequired ->
|
||||
if (enabled != null) {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
|
@ -118,6 +155,7 @@ class TextFieldKtTest(
|
|||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlined(
|
||||
|
@ -125,13 +163,14 @@ class TextFieldKtTest(
|
|||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlinedPassword",
|
||||
content = { value, onValueChange, modifier, enabled, label ->
|
||||
content = { value, onValueChange, modifier, enabled, label, isRequired ->
|
||||
if (enabled != null) {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
|
@ -139,6 +178,7 @@ class TextFieldKtTest(
|
|||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlinedPassword(
|
||||
|
@ -146,13 +186,14 @@ class TextFieldKtTest(
|
|||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlinedEmail",
|
||||
content = { value, onValueChange, modifier, enabled, label ->
|
||||
content = { value, onValueChange, modifier, enabled, label, isRequired ->
|
||||
if (enabled != null) {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = value,
|
||||
|
@ -160,6 +201,7 @@ class TextFieldKtTest(
|
|||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
|
@ -167,6 +209,7 @@ class TextFieldKtTest(
|
|||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue