@@ -34,10 +34,7 @@ import androidx.compose.material3.TextFieldLabelPosition
3434import androidx.compose.material3.Typography
3535import androidx.compose.runtime.Composable
3636import androidx.compose.runtime.CompositionLocalProvider
37- import androidx.compose.runtime.getValue
38- import androidx.compose.runtime.mutableStateOf
3937import androidx.compose.runtime.remember
40- import androidx.compose.runtime.setValue
4138import androidx.compose.ui.Modifier
4239import androidx.compose.ui.draw.alpha
4340import androidx.compose.ui.graphics.SolidColor
@@ -64,6 +61,10 @@ import com.duckduckgo.mobile.android.R
6461 * It's a single line text field that obscures the input by default, with an option to toggle visibility.
6562 *
6663 * @param state The state of the text field that is used to read and write the text and selection.
64+ * @param isPasswordVisible Boolean flag indicating whether the password is currently visible or obscured.
65+ * You should manage this state and update it accordingly when [onShowHidePasswordIconClick] is called.
66+ * @param onShowHidePasswordIconClick Callback for when the show/hide password icon is clicked by the user.
67+ * You should update the [isPasswordVisible] state accordingly.
6768 * @param modifier Optional [Modifier] for this text field. Can be used request focus via [Modifier.focusRequester] for example.
6869 * @param label Optional label/hint text to display inside the text field when it's empty or above the text field when it has text or is focused.
6970 * @param inputMode Input mode for the text field, such as editable, read-only or disabled. See [DaxTextFieldInputMode] for details.
@@ -82,6 +83,8 @@ import com.duckduckgo.mobile.android.R
8283@Composable
8384fun DaxSecureTextField (
8485 state : TextFieldState ,
86+ isPasswordVisible : Boolean ,
87+ onShowHidePasswordIconClick : () -> Unit ,
8588 modifier : Modifier = Modifier ,
8689 label : String? = null,
8790 inputMode : DaxTextFieldInputMode = DaxTextFieldInputMode .Editable ,
@@ -92,7 +95,7 @@ fun DaxSecureTextField(
9295) {
9396 // needed by the OutlinedTextField container
9497 val internalInteractionSource = interactionSource ? : remember { MutableInteractionSource () }
95- var isPasswordVisible by remember { mutableStateOf( false ) }
98+ val daxTextFieldColors = daxTextFieldColors()
9699
97100 // combine the password visibility toggle icon with any provided trailing icon
98101 val trailingIconCombined: @Composable (() -> Unit )? = {
@@ -106,7 +109,7 @@ fun DaxSecureTextField(
106109 },
107110 ),
108111 contentDescription = null ,
109- onClick = { isPasswordVisible = ! isPasswordVisible } ,
112+ onClick = onShowHidePasswordIconClick ,
110113 enabled = inputMode == DaxTextFieldInputMode .Editable || inputMode == DaxTextFieldInputMode .ReadOnly ,
111114 )
112115
@@ -129,7 +132,7 @@ fun DaxSecureTextField(
129132 ),
130133 ),
131134 ) {
132- CompositionLocalProvider (LocalTextSelectionColors provides daxTextFieldColors() .textSelectionColors) {
135+ CompositionLocalProvider (LocalTextSelectionColors provides daxTextFieldColors.textSelectionColors) {
133136 // need to use BasicSecureTextField over OutlinedSecureTextField as the latter does not support readOnly mode
134137 BasicSecureTextField (
135138 state = state,
@@ -166,8 +169,10 @@ fun DaxSecureTextField(
166169 ),
167170 enabled = inputMode == DaxTextFieldInputMode .Editable || inputMode == DaxTextFieldInputMode .ReadOnly ,
168171 readOnly = inputMode == DaxTextFieldInputMode .ReadOnly || inputMode == DaxTextFieldInputMode .Disabled ,
169- textStyle = DuckDuckGoTheme .typography.body1.asTextStyle,
170- cursorBrush = SolidColor (daxTextFieldColors().cursorColor),
172+ textStyle = DuckDuckGoTheme .typography.body1.asTextStyle.copy(
173+ color = DuckDuckGoTheme .textColors.primary,
174+ ),
175+ cursorBrush = SolidColor (daxTextFieldColors.cursorColor),
171176 keyboardOptions = keyboardOptions,
172177 interactionSource = internalInteractionSource,
173178 textObfuscationMode = if (isPasswordVisible) {
@@ -210,14 +215,14 @@ fun DaxSecureTextField(
210215 null
211216 },
212217 isError = ! error.isNullOrBlank(),
213- colors = daxTextFieldColors() ,
218+ colors = daxTextFieldColors,
214219 contentPadding = OutlinedTextFieldDefaults .contentPadding(),
215220 container = {
216221 OutlinedTextFieldDefaults .Container (
217222 enabled = inputMode == DaxTextFieldInputMode .Editable || inputMode == DaxTextFieldInputMode .ReadOnly ,
218223 isError = ! error.isNullOrBlank(),
219224 interactionSource = internalInteractionSource,
220- colors = daxTextFieldColors() ,
225+ colors = daxTextFieldColors,
221226 shape = DuckDuckGoTheme .shapes.small,
222227 )
223228 },
@@ -244,18 +249,36 @@ private fun DaxSecureTextFieldEmptyPreview() {
244249 DaxSecureTextField (
245250 state = TextFieldState (),
246251 label = " Enter password" ,
252+ isPasswordVisible = false ,
253+ onShowHidePasswordIconClick = {},
254+ )
255+ }
256+ }
257+
258+ @PreviewFontScale
259+ @PreviewLightDark
260+ @Composable
261+ private fun DaxSecureTextFieldWithPlainTextPreview () {
262+ DaxSecureTextFieldPreviewBox {
263+ DaxSecureTextField (
264+ state = TextFieldState (initialText = " SecurePassword123" ),
265+ label = " Enter password" ,
266+ isPasswordVisible = true ,
267+ onShowHidePasswordIconClick = {},
247268 )
248269 }
249270}
250271
251272@PreviewFontScale
252273@PreviewLightDark
253274@Composable
254- private fun DaxSecureTextFieldWithTextPreview () {
275+ private fun DaxSecureTextFieldWithObscureTextPreview () {
255276 DaxSecureTextFieldPreviewBox {
256277 DaxSecureTextField (
257278 state = TextFieldState (initialText = " SecurePassword123" ),
258279 label = " Enter password" ,
280+ isPasswordVisible = false ,
281+ onShowHidePasswordIconClick = {},
259282 )
260283 }
261284}
@@ -266,6 +289,8 @@ private fun DaxSecureTextFieldNoLabelPreview() {
266289 DaxSecureTextFieldPreviewBox {
267290 DaxSecureTextField (
268291 state = TextFieldState (initialText = " SecurePassword123" ),
292+ isPasswordVisible = false ,
293+ onShowHidePasswordIconClick = {},
269294 )
270295 }
271296}
@@ -276,6 +301,8 @@ private fun DaxSecureTextFieldEditablePreview() {
276301 DaxSecureTextFieldPreviewBox {
277302 DaxSecureTextField (
278303 state = TextFieldState (initialText = " SecurePassword123" ),
304+ isPasswordVisible = false ,
305+ onShowHidePasswordIconClick = {},
279306 label = " Enter password" ,
280307 inputMode = DaxTextFieldInputMode .Editable ,
281308 )
@@ -288,6 +315,8 @@ private fun DaxSecureTextFieldDisabledPreview() {
288315 DaxSecureTextFieldPreviewBox {
289316 DaxSecureTextField (
290317 state = TextFieldState (initialText = " SecurePassword123" ),
318+ isPasswordVisible = false ,
319+ onShowHidePasswordIconClick = {},
291320 label = " Enter password" ,
292321 inputMode = DaxTextFieldInputMode .Disabled ,
293322 )
@@ -300,6 +329,8 @@ private fun DaxSecureTextFieldNonEditablePreview() {
300329 DaxSecureTextFieldPreviewBox {
301330 DaxSecureTextField (
302331 state = TextFieldState (initialText = " SecurePassword123" ),
332+ isPasswordVisible = false ,
333+ onShowHidePasswordIconClick = {},
303334 label = " Read only password" ,
304335 inputMode = DaxTextFieldInputMode .ReadOnly ,
305336 )
@@ -312,6 +343,8 @@ private fun DaxSecureTextFieldWithErrorPreview() {
312343 DaxSecureTextFieldPreviewBox {
313344 DaxSecureTextField (
314345 state = TextFieldState (initialText = " weak" ),
346+ isPasswordVisible = false ,
347+ onShowHidePasswordIconClick = {},
315348 label = " Enter password" ,
316349 error = " Password must be at least 8 characters" ,
317350 )
@@ -324,6 +357,8 @@ private fun DaxSecureTextFieldWithTrailingIconPreview() {
324357 DaxSecureTextFieldPreviewBox {
325358 DaxSecureTextField (
326359 state = TextFieldState (initialText = " SecurePassword123" ),
360+ isPasswordVisible = false ,
361+ onShowHidePasswordIconClick = {},
327362 label = " Enter password" ,
328363 trailingIcon = {
329364 DaxTextFieldTrailingIconScope .DaxTextFieldTrailingIcon (
@@ -342,6 +377,8 @@ private fun DaxSecureTextFieldEmptyWithTrailingIconPreview() {
342377 DaxSecureTextFieldPreviewBox {
343378 DaxSecureTextField (
344379 state = TextFieldState (),
380+ isPasswordVisible = false ,
381+ onShowHidePasswordIconClick = {},
345382 label = " Enter password" ,
346383 trailingIcon = {
347384 DaxTextFieldTrailingIconScope .DaxTextFieldTrailingIcon (
@@ -360,6 +397,8 @@ private fun DaxSecureTextFieldErrorWithTrailingIconPreview() {
360397 DaxSecureTextFieldPreviewBox {
361398 DaxSecureTextField (
362399 state = TextFieldState (initialText = " weak" ),
400+ isPasswordVisible = false ,
401+ onShowHidePasswordIconClick = {},
363402 label = " Enter password" ,
364403 error = " Password must contain uppercase, lowercase, and numbers" ,
365404 trailingIcon = {
0 commit comments