Compare commits

...

2 Commits

Author SHA1 Message Date
Patrick Honkonen
da57763635 Fix logic for password field content description
Simplify the conditional logic used to set the `contentDescription` for the `BitwardenPasswordField`.

The previous implementation used a double negative (`takeUnless { !showPassword }`) to determine if the password text should be exposed to accessibility services. This change replaces it with the more direct and readable `takeIf { showPassword }`, ensuring the content description is only populated when the password is explicitly visible.
2025-12-03 16:03:12 -05:00
Patrick Honkonen
ae5e4cace3 Update BitwardenPasswordField semantics to support accessibility for visible passwords
Improve accessibility support in `BitwardenPasswordField` by ensuring Talkback can read the password aloud when the user chooses to make it visible, while explicitly marking the content as sensitive data.

Behavioral changes:
*   When the "show password" toggle is active, Talkback will now read the actual password text instead of silence or obfuscated characters. This behavior occurs regardless of the system-wide "Speak Passwords" setting due to the custom visual transformation usage.
*   The field is semantically marked as containing sensitive data.

Specific changes:
*   Apply a `semantics` modifier to the internal `TextField` in `BitwardenPasswordField`.
*   Set `contentDescription` to the actual text value only when `showPassword` is true; otherwise, it defaults to an empty string.
*   Set the `isSensitiveData` semantic property to `true`.
2025-12-03 14:13:37 -05:00

View File

@@ -36,6 +36,9 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalTextToolbar
import androidx.compose.ui.platform.TextToolbar
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.isSensitiveData
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
@@ -228,6 +231,19 @@ fun BitwardenPasswordField(
)
},
modifier = Modifier
.semantics {
// Content description must be set to the field value in order for Talkback
// to speak the password aloud when it is visible because we apply a custom
// VisualTransformation to the text, which prevents Talkback from reading
// the value as it normally would.
// NOTE: This overrides the default behavior of Talkback's "Speak Passwords"
// setting. When visible, the password will always be spoken aloud
// regardless of the user's configuration.
contentDescription = textFieldValue.text
.takeIf { showPassword }
.orEmpty()
isSensitiveData = true
}
.nullableTestTag(tag = passwordFieldTestTag)
.fillMaxWidth()
.onFocusChanged { focusState -> focused = focusState.isFocused },