Skip to content

Commit

Permalink
HMA-8827-password-input-view (#191)
Browse files Browse the repository at this point in the history
* password input view'

* changelog

* spotless

* HMA-8827 password text input

* HMA-8827 letter spacing

* spotless

* Requested changes

* final requested changes

* fixes

* spotless

* bug fix

* merge conflict

* merge conflict 2
  • Loading branch information
emmaatkins authored Oct 25, 2024
1 parent d955670 commit f51ffb4
Show file tree
Hide file tree
Showing 21 changed files with 849 additions and 150 deletions.
5 changes: 5 additions & 0 deletions components-compose/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ Allowed headings:

## [Unreleased]

### Added

* `PasswordInputView` component added with show/hide feature
* `requiresSequenceSpacing` parameter added to `TextInputView` to enable additional character spacing for use during sequences

## [0.1.5] - 2024-10-25Z

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright 2024 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.gov.hmrc.components.compose.molecule.input

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import uk.gov.hmrc.components.compose.atom.text.BodyText
import uk.gov.hmrc.components.compose.atom.text.BoldText
import uk.gov.hmrc.components.compose.atom.text.ErrorText
import uk.gov.hmrc.components.compose.molecule.input.CommonInputView.CHAR_COUNT_WIDTH
import uk.gov.hmrc.components.compose.molecule.input.CommonInputView.ERROR_TEXT_WITH_CHAR_COUNT_WIDTH
import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme
import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme.typography

@Suppress("LongParameterList")
@Composable
internal fun TextField(
modifier: Modifier,
isError: Boolean,
value: String,
onInputValueChange: (String) -> Unit,
prefix: @Composable() (() -> Unit)?,
placeholderText: @Composable (() -> Unit)?,
supportingText: @Composable() (() -> Unit)?,
singleLine: Boolean,
keyboardOptions: KeyboardOptions,
visualTransformation: VisualTransformation,
colors: TextFieldColors,
trailingIcon: @Composable() (() -> Unit)? = null,
textStyle: TextStyle = typography.body,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
) {
OutlinedTextField(
modifier = modifier.fillMaxWidth(),
isError = isError,
value = value,
onValueChange = onInputValueChange,
prefix = prefix,
placeholder = placeholderText,
supportingText = supportingText,
trailingIcon = trailingIcon,
singleLine = singleLine,
keyboardOptions = keyboardOptions,
textStyle = textStyle,
colors = colors,
shape = RoundedCornerShape(0),
visualTransformation = visualTransformation,
interactionSource = interactionSource,
)
}

@Composable
internal fun Label(labelText: String?, labelContentDescription: String?,) {
labelText?.let { label ->
BoldText(
text = label,
modifier = Modifier
.semantics { labelContentDescription?.let { contentDescription = it } }
.padding(bottom = HmrcTheme.dimensions.hmrcSpacing8)
)
}
}

@Composable
internal fun Hint(hintText: String?, hintContentDescription: String?) {
hintText?.let { hint ->
BodyText(
text = hint,
modifier = Modifier
.semantics { hintContentDescription?.let { contentDescription = it } }
.padding(bottom = HmrcTheme.dimensions.hmrcSpacing8)
)
}
}

internal fun error(errorText: String?, errorContentDescription: String?):
@Composable (() -> Unit)? = errorText?.let {
@Composable {
ErrorText(
text = it,
modifier = Modifier.semantics {
errorContentDescription?.let {
contentDescription = it
}
}
)
}
}

internal fun errorTextCounterCombo(
errorText: String?,
errorContentDescription: String?,
characterCount: Int?,
localValue: String
):
@Composable (() -> Unit) = @Composable {
Row {
Column(
horizontalAlignment = Alignment.Start,
modifier = Modifier.fillMaxWidth(ERROR_TEXT_WITH_CHAR_COUNT_WIDTH)
) {
if (errorText != null) {
ErrorText(
text = errorText,
modifier = Modifier.semantics {
errorContentDescription?.let {
contentDescription = it
}
}
)
}
}
Column(
horizontalAlignment = Alignment.End,
modifier = Modifier.fillMaxWidth(CHAR_COUNT_WIDTH)
) {
val textStyle = characterCount?.let { limit ->
if (localValue.length > limit) typography.errorText else typography.body
} ?: typography.body
Text(
text = "${localValue.length}/$characterCount",
style = textStyle,
textAlign = TextAlign.End,
)
}
}
}

object CommonInputView {
const val ERROR_TEXT_WITH_CHAR_COUNT_WIDTH = 0.8f
const val CHAR_COUNT_WIDTH = 0.95f
}

@Composable
fun Modifier.adjustPaddingForCounter(counterEnabled: Boolean, localError: String?) = this.padding(
bottom = if (counterEnabled || !localError.isNullOrEmpty()) 0.dp else HmrcTheme.dimensions.hmrcIconSize24
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ fun CurrencyInputView(
errorContentDescription: String? = null,
singleLine: Boolean = true,
enableDecimal: Boolean = true,
maxChars: Int? = null,
maxChars: Int? = null
) {

// pattern matches a decimal number
val decimalPattern = remember { Regex("^([0-9]*)(\\.?)([0-9]*)$") }
// pattern matches a non decimal number
Expand Down Expand Up @@ -71,11 +70,11 @@ fun CurrencyInputView(
placeholderText = placeholderText,
errorText = errorText,
errorContentDescription = errorContentDescription,
maxChars = maxChars,
singleLine = singleLine,
keyboardOptions = KeyboardOptions(
keyboardType = if (enableDecimal) KeyboardType.Decimal else KeyboardType.Number
),
maxChars = maxChars
)
)
}

Expand All @@ -87,7 +86,7 @@ fun CurrencyInputViewPreview() {
onInputValueChange = { },
labelText = "Label",
hintText = "Hint",
placeholderText = "Text"
placeholderText = "Text",
)
}
}
Loading

0 comments on commit f51ffb4

Please sign in to comment.