diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt index df796db59df..32ad40cc4c8 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt @@ -33,8 +33,8 @@ import com.bitwarden.ui.platform.base.util.EventsEffect import com.bitwarden.ui.platform.base.util.mirrorIfRtl import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow import com.bitwarden.ui.platform.components.row.BitwardenPushRow import com.bitwarden.ui.platform.components.row.BitwardenTextRow @@ -277,9 +277,10 @@ private fun ColumnScope.FlightRecorderCard( label = stringResource(id = BitwardenString.flight_recorder), isChecked = isFlightRecorderEnabled, onCheckedChange = onFlightRecorderCheckedChange, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( contentDescription = stringResource(id = BitwardenString.flight_recorder_help), onClick = onFlightRecorderTooltipClick, + isExternalLink = true, ), subtext = logExpiration?.invoke(), cardStyle = CardStyle.Top(), diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt index 348e19c0647..a32543a028d 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt @@ -26,10 +26,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitwarden.ui.platform.base.util.EventsEffect import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog import com.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch import com.bitwarden.ui.platform.components.util.rememberVectorPainter @@ -136,13 +136,14 @@ fun AppearanceScreen( onCheckedChange = { viewModel.trySendAction(AppearanceAction.ShowWebsiteIconsToggle(it)) }, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = { viewModel.trySendAction(AppearanceAction.ShowWebsiteIconsTooltipClick) }, contentDescription = stringResource( id = BitwardenString.show_website_icons_help, ), + isExternalLink = true, ), cardStyle = CardStyle.Full, modifier = Modifier diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt index 1973f1d35e3..0d5fdbc1f9d 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt @@ -44,6 +44,7 @@ import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.base.util.toAnnotatedString import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.bitwarden.ui.platform.components.badge.NotificationBadge +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.card.BitwardenActionCard import com.bitwarden.ui.platform.components.card.BitwardenActionCardSmall import com.bitwarden.ui.platform.components.card.actionCardExitAnimation @@ -53,7 +54,6 @@ import com.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton import com.bitwarden.ui.platform.components.dropdown.model.MultiSelectOption import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow import com.bitwarden.ui.platform.components.row.BitwardenPushRow import com.bitwarden.ui.platform.components.row.BitwardenTextRow @@ -263,11 +263,12 @@ private fun AutoFillScreenContent( BitwardenTextRow( text = stringResource(BitwardenString.privileged_apps), onClick = autoFillHandlers.onPrivilegedAppsClick, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( contentDescription = stringResource( id = BitwardenString.learn_more_about_privileged_apps, ), onClick = autoFillHandlers.onPrivilegedAppsHelpLinkClick, + isExternalLink = false, ), cardStyle = CardStyle.Bottom, modifier = Modifier diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt index 4ff9c448a06..c5a35431d35 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt @@ -49,6 +49,7 @@ import com.bitwarden.ui.platform.components.appbar.model.TopAppBarDividerStyle import com.bitwarden.ui.platform.components.button.BitwardenFilledButton import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton import com.bitwarden.ui.platform.components.button.BitwardenTextButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.card.BitwardenActionCard import com.bitwarden.ui.platform.components.card.BitwardenInfoCalloutCard import com.bitwarden.ui.platform.components.coachmark.CoachMarkActionText @@ -61,7 +62,6 @@ import com.bitwarden.ui.platform.components.field.BitwardenPasswordField import com.bitwarden.ui.platform.components.field.BitwardenTextField import com.bitwarden.ui.platform.components.field.model.TextToolbarType import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold import com.bitwarden.ui.platform.components.segment.BitwardenSegmentedButton import com.bitwarden.ui.platform.components.segment.SegmentedButtonOptionContent @@ -1157,9 +1157,10 @@ private fun UsernameOptionsItem( supportingText = currentSubState.selectedType.supportingStringResId?.let { stringResource(id = it) }, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = usernameTypeHandlers.onUsernameTooltipClicked, contentDescription = stringResource(id = BitwardenString.learn_more), + isExternalLink = true, ), cardStyle = CardStyle.Full, modifier = modifier.testTag(tag = "UsernameTypePicker"), diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt index 24bc1c39a22..1b88f423b61 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt @@ -153,6 +153,7 @@ fun SendScreen( OverflowMenuItemData( text = stringResource(id = BitwardenString.about_send), onClick = { viewModel.trySendAction(SendAction.AboutSendClick) }, + isExternalLink = true, ), ), ) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditAdditionalOptions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditAdditionalOptions.kt index adba6f8a915..43659d21a1b 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditAdditionalOptions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditAdditionalOptions.kt @@ -13,11 +13,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.bitwarden.core.util.persistentListOfNotNull import com.bitwarden.ui.platform.base.util.standardHorizontalMargin +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.field.BitwardenTextField import com.bitwarden.ui.platform.components.header.BitwardenExpandingHeader import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch import com.bitwarden.ui.platform.resource.BitwardenString import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers @@ -78,11 +78,12 @@ fun LazyListScope.vaultAddEditAdditionalOptions( label = stringResource(id = BitwardenString.password_prompt), isChecked = commonState.masterPasswordReprompt, onCheckedChange = commonTypeHandlers.onToggleMasterPasswordReprompt, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = commonTypeHandlers.onTooltipClick, contentDescription = stringResource( id = BitwardenString.master_password_re_prompt_help, ), + isExternalLink = true, ), cardStyle = CardStyle.Full, modifier = Modifier diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt index 1243cd3c179..ba7bb60d173 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.base.util.cardStyle import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.coachmark.CoachMarkActionText import com.bitwarden.ui.platform.components.coachmark.model.CoachMarkHighlightShape import com.bitwarden.ui.platform.components.coachmark.scope.CoachMarkScope @@ -31,7 +32,6 @@ import com.bitwarden.ui.platform.components.field.BitwardenPasswordField import com.bitwarden.ui.platform.components.field.BitwardenTextField import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.text.BitwardenClickableText import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.resource.BitwardenString @@ -386,9 +386,10 @@ private fun TotpRow( ) } }, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = loginItemTypeHandlers.onAuthenticatorHelpToolTipClick, contentDescription = stringResource(id = BitwardenString.authenticator_key_help), + isExternalLink = true, ), supportingContentPadding = PaddingValues(), supportingContent = { diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/importlogins/components/ImportLoginsInstructionStep.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/importlogins/components/ImportLoginsInstructionStep.kt index ab821b41a4a..99d59055bd6 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/importlogins/components/ImportLoginsInstructionStep.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/importlogins/components/ImportLoginsInstructionStep.kt @@ -19,13 +19,13 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.bitwarden.ui.platform.base.util.annotatedStringResource import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.base.util.toAnnotatedString import com.bitwarden.ui.platform.components.button.BitwardenFilledButton import com.bitwarden.ui.platform.components.button.BitwardenOutlinedButton import com.bitwarden.ui.platform.components.card.BitwardenContentCard import com.bitwarden.ui.platform.components.content.model.ContentBlockData +import com.bitwarden.ui.platform.components.text.BitwardenHyperTextLink import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.resource.BitwardenString import com.bitwarden.ui.platform.theme.BitwardenTheme @@ -40,12 +40,12 @@ import kotlinx.collections.immutable.persistentListOf fun ImportLoginsInstructionStep( stepText: String, stepTitle: String, - ctaText: String = stringResource(BitwardenString.continue_text), instructions: ImmutableList, onBackClick: () -> Unit, onContinueClick: () -> Unit, onHelpClick: () -> Unit, modifier: Modifier = Modifier, + ctaText: String = stringResource(BitwardenString.continue_text), ) { Column( modifier = modifier.verticalScroll(rememberScrollState()), @@ -67,13 +67,12 @@ fun ImportLoginsInstructionStep( contentSubtitleTextStyle = BitwardenTheme.typography.labelSmall, ) Spacer(Modifier.height(24.dp)) - Text( - text = annotatedStringResource( - id = BitwardenString.need_help_check_out_import_help, - onAnnotationClick = { onHelpClick() }, - ), + BitwardenHyperTextLink( + annotatedResId = BitwardenString.need_help_check_out_import_help, + annotationKey = "importHelp", + accessibilityString = stringResource(id = BitwardenString.import_help), + onClick = onHelpClick, style = BitwardenTheme.typography.bodySmall, - color = BitwardenTheme.colorScheme.text.secondary, modifier = Modifier.standardHorizontalMargin(), ) Spacer(Modifier.height(24.dp)) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt index e55d2b8fbeb..188c1a6cf1e 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemLoginContent.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.base.util.toListItemCardStyle import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.field.BitwardenHiddenPasswordField import com.bitwarden.ui.platform.components.field.BitwardenPasswordField import com.bitwarden.ui.platform.components.field.BitwardenTextField @@ -29,7 +30,6 @@ import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText import com.bitwarden.ui.platform.components.icon.model.IconData import com.bitwarden.ui.platform.components.indicator.BitwardenCircularCountdownIndicator import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.text.BitwardenClickableText import com.bitwarden.ui.platform.components.text.BitwardenHyperTextLink import com.bitwarden.ui.platform.resource.BitwardenDrawable @@ -456,9 +456,10 @@ private fun TotpField( textStyle = BitwardenTheme.typography.sensitiveInfoSmall, readOnly = true, singleLine = true, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = onAuthenticatorHelpToolTipClick, contentDescription = stringResource(id = BitwardenString.authenticator_key_help), + isExternalLink = true, ), actions = { BitwardenCircularCountdownIndicator( @@ -480,9 +481,10 @@ private fun TotpField( BitwardenTextField( label = stringResource(id = BitwardenString.authenticator_key), value = "", - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = onAuthenticatorHelpToolTipClick, contentDescription = stringResource(id = BitwardenString.authenticator_key_help), + isExternalLink = true, ), supportingText = stringResource(id = BitwardenString.premium_subscription_required), enabled = false, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt index 9d816a20938..1fab9100b9e 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt @@ -18,21 +18,17 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.CustomAccessibilityAction -import androidx.compose.ui.semantics.customActions -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import com.bitwarden.ui.platform.base.util.EventsEffect import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect -import com.bitwarden.ui.platform.base.util.annotatedStringResource import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.bitwarden.ui.platform.components.camera.CameraPreview import com.bitwarden.ui.platform.components.camera.QrCodeSquare import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold +import com.bitwarden.ui.platform.components.text.BitwardenHyperTextLink import com.bitwarden.ui.platform.components.util.rememberVectorPainter import com.bitwarden.ui.platform.composition.LocalQrCodeAnalyzer import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzer @@ -143,7 +139,7 @@ private fun QrCodeContentCompact( Text( text = stringResource(id = BitwardenString.point_your_camera_at_the_qr_code), textAlign = TextAlign.Center, - color = Color.White, + color = BitwardenTheme.colorScheme.text.primary, style = BitwardenTheme.typography.bodyMedium, modifier = Modifier.padding(horizontal = 16.dp), ) @@ -184,7 +180,7 @@ private fun QrCodeContentMedium( Text( text = stringResource(id = BitwardenString.point_your_camera_at_the_qr_code), textAlign = TextAlign.Center, - color = Color.White, + color = BitwardenTheme.colorScheme.text.primary, style = BitwardenTheme.typography.bodySmall, ) @@ -200,30 +196,13 @@ private fun EnterKeyManuallyText( onEnterKeyManuallyClick: () -> Unit, modifier: Modifier = Modifier, ) { - val enterKeyManuallyString = stringResource(BitwardenString.enter_key_manually) - Text( - text = annotatedStringResource( - id = BitwardenString.cannot_scan_qr_code_enter_key_manually, - onAnnotationClick = { - when (it) { - "enterKeyManually" -> onEnterKeyManuallyClick() - } - }, - ), + BitwardenHyperTextLink( + annotatedResId = BitwardenString.cannot_scan_qr_code_enter_key_manually, + annotationKey = "enterKeyManually", + accessibilityString = stringResource(BitwardenString.enter_key_manually), + onClick = onEnterKeyManuallyClick, style = BitwardenTheme.typography.bodySmall, - color = Color.White, - textAlign = TextAlign.Center, - modifier = modifier - .semantics { - customActions = listOf( - CustomAccessibilityAction( - label = enterKeyManuallyString, - action = { - onEnterKeyManuallyClick() - true - }, - ), - ) - }, + color = BitwardenTheme.colorScheme.text.primary, + modifier = modifier, ) } diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt index bf2d37bb5bd..9a5ff2dce87 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt @@ -73,7 +73,7 @@ class AboutScreenTest : BitwardenComposeTest() { @Test fun `on flight recorder tooltip click should emit FlightRecorderTooltipClick`() { composeTestRule - .onNodeWithContentDescription("Flight recorder help") + .onNodeWithContentDescription("Flight recorder help, External link") .performScrollTo() .performClick() verify { diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt index a9fee4e99b4..e451154b858 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreenTest.kt @@ -178,7 +178,7 @@ class AppearanceScreenTest : BitwardenComposeTest() { @Test fun `on show website icons tooltip click should send ShowWebsiteIconsToggled`() { composeTestRule - .onNodeWithContentDescription(label = "Show website icons help") + .onNodeWithContentDescription(label = "Show website icons help, External link") .performScrollTo() .performClick() verify { diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt index ac4a35a39df..885312890eb 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreenTest.kt @@ -1464,7 +1464,7 @@ class GeneratorScreenTest : BitwardenComposeTest() { .filterToOne(hasClickAction()) // Find the content description .onChildren() - .filterToOne(hasContentDescription("Learn more")) + .filterToOne(hasContentDescription("Learn more, External link")) .assertIsDisplayed() .performClick() diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt index 51a56066f0e..069d4e54bef 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreenTest.kt @@ -1268,7 +1268,9 @@ class VaultAddEditScreenTest : BitwardenComposeTest() { @Test fun `Clicking the Authenticator key tooltip sends AuthenticatorHelpToolTipClick action`() { composeTestRule - .onNodeWithContentDescriptionAfterScroll(label = "Authenticator key help") + .onNodeWithContentDescriptionAfterScroll( + label = "Authenticator key help, External link", + ) .performClick() verify { @@ -3071,7 +3073,9 @@ class VaultAddEditScreenTest : BitwardenComposeTest() { .performClick() composeTestRule - .onNodeWithContentDescriptionAfterScroll(label = "Master password re-prompt help") + .onNodeWithContentDescriptionAfterScroll( + label = "Master password re-prompt help, External link", + ) .performClick() verify { diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt index 47bd19adcd0..da17a1cd207 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt @@ -2339,7 +2339,7 @@ class VaultItemScreenTest : BitwardenComposeTest() { } composeTestRule - .onNodeWithContentDescriptionAfterScroll("Authenticator key help") + .onNodeWithContentDescriptionAfterScroll("Authenticator key help, External link") .performClick() verify { diff --git a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt index b53337f7ba2..8cf7b3d39a0 100644 --- a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt +++ b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt @@ -22,8 +22,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.CustomAccessibilityAction -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel @@ -31,14 +29,13 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitwarden.authenticator.ui.platform.util.isPortrait import com.bitwarden.ui.platform.base.util.EventsEffect import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect -import com.bitwarden.ui.platform.base.util.annotatedStringResource -import com.bitwarden.ui.platform.base.util.spanStyleOf import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.bitwarden.ui.platform.components.camera.CameraPreview import com.bitwarden.ui.platform.components.camera.QrCodeSquare import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold +import com.bitwarden.ui.platform.components.text.BitwardenHyperTextLink import com.bitwarden.ui.platform.composition.LocalQrCodeAnalyzer import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzer import com.bitwarden.ui.platform.resource.BitwardenDrawable @@ -181,7 +178,7 @@ private fun PortraitQRCodeContent( Text( text = stringResource(id = BitwardenString.point_your_camera_at_the_qr_code), textAlign = TextAlign.Center, - color = Color.White, + color = BitwardenTheme.colorScheme.text.primary, style = BitwardenTheme.typography.bodyMedium, modifier = Modifier.padding(horizontal = 16.dp), ) @@ -222,7 +219,7 @@ private fun LandscapeQRCodeContent( Text( text = stringResource(id = BitwardenString.point_your_camera_at_the_qr_code), textAlign = TextAlign.Center, - color = Color.White, + color = BitwardenTheme.colorScheme.text.primary, style = BitwardenTheme.typography.bodySmall, ) @@ -239,32 +236,13 @@ private fun BottomClickableText( onEnterCodeManuallyClick: () -> Unit, modifier: Modifier = Modifier, ) { - val enterKeyText = stringResource(id = BitwardenString.enter_key_manually) - Text( - text = annotatedStringResource( - id = BitwardenString.cannot_scan_qr_code_enter_key_manually, - linkHighlightStyle = spanStyleOf( - color = BitwardenTheme.colorScheme.text.interaction, - textStyle = BitwardenTheme.typography.bodyMedium, - ), - style = spanStyleOf( - color = Color.White, - textStyle = BitwardenTheme.typography.bodyMedium, - ), - onAnnotationClick = { - when (it) { - "enterKeyManually" -> onEnterCodeManuallyClick() - } - }, - ), - modifier = modifier.semantics { - CustomAccessibilityAction( - label = enterKeyText, - action = { - onEnterCodeManuallyClick() - true - }, - ) - }, + BitwardenHyperTextLink( + annotatedResId = BitwardenString.cannot_scan_qr_code_enter_key_manually, + annotationKey = "enterKeyManually", + accessibilityString = stringResource(BitwardenString.enter_key_manually), + onClick = onEnterCodeManuallyClick, + style = BitwardenTheme.typography.bodySmall, + color = BitwardenTheme.colorScheme.text.primary, + modifier = modifier, ) } diff --git a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt index 06ade12fa09..9996b4ab687 100644 --- a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt +++ b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt @@ -35,7 +35,9 @@ import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.CustomAccessibilityAction import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.customActions import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -401,6 +403,7 @@ private fun ColumnScope.VaultSettings( }, ) if (shouldShowSyncWithBitwardenApp) { + val learnMore = stringResource(id = BitwardenString.learn_more_link) BitwardenTextRow( text = stringResource(id = BitwardenString.sync_with_bitwarden_app), description = annotatedStringResource( @@ -412,7 +415,19 @@ private fun ColumnScope.VaultSettings( }, ), onClick = onSyncWithBitwardenClick, - modifier = Modifier.standardHorizontalMargin(), + modifier = Modifier + .semantics { + customActions = listOf( + CustomAccessibilityAction( + label = learnMore, + action = { + onSyncLearnMoreClick() + true + }, + ), + ) + } + .standardHorizontalMargin(), cardStyle = if (shouldShowDefaultSaveOptions) { CardStyle.Middle() } else { diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/action/BitwardenOverflowActionItem.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/action/BitwardenOverflowActionItem.kt index 1c201ac6819..38e762af390 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/action/BitwardenOverflowActionItem.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/action/BitwardenOverflowActionItem.kt @@ -16,6 +16,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.hideFromAccessibility import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.tooling.preview.Preview @@ -26,6 +29,7 @@ import com.bitwarden.ui.platform.components.appbar.color.bitwardenMenuItemColors import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton import com.bitwarden.ui.platform.resource.BitwardenDrawable +import com.bitwarden.ui.platform.resource.BitwardenString import com.bitwarden.ui.platform.theme.BitwardenTheme import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -75,26 +79,9 @@ fun BitwardenOverflowActionItem( ), content = { menuItemDataList.forEach { dropdownMenuItemData -> - DropdownMenuItem( - modifier = Modifier.testTag("FloatingOptionsItem"), - colors = bitwardenMenuItemColors( - textColor = dropdownMenuItemData - .color - .takeUnless { it == Color.Unspecified } - ?: BitwardenTheme.colorScheme.text.primary, - ), - enabled = dropdownMenuItemData.isEnabled, - text = { - Text( - text = dropdownMenuItemData.text, - style = BitwardenTheme.typography.bodyLarge, - modifier = Modifier.testTag("FloatingOptionsItemName"), - ) - }, - onClick = { - isOverflowMenuVisible = false - dropdownMenuItemData.onClick() - }, + BitwardenDropdownMenuItem( + data = dropdownMenuItemData, + onHideOverflowMenu = { isOverflowMenuVisible = false }, ) } }, @@ -102,6 +89,46 @@ fun BitwardenOverflowActionItem( } } +@Composable +private fun BitwardenDropdownMenuItem( + data: OverflowMenuItemData, + onHideOverflowMenu: () -> Unit, + modifier: Modifier = Modifier, +) { + val contentDescriptionText = if (data.isExternalLink) { + stringResource(id = BitwardenString.external_link_format, formatArgs = arrayOf(data.text)) + } else { + data.text + } + DropdownMenuItem( + modifier = modifier + .semantics(mergeDescendants = true) { + contentDescription = contentDescriptionText + } + .testTag(tag = "FloatingOptionsItem"), + colors = bitwardenMenuItemColors( + textColor = data + .color + .takeUnless { it == Color.Unspecified } + ?: BitwardenTheme.colorScheme.text.primary, + ), + enabled = data.isEnabled, + text = { + Text( + text = data.text, + style = BitwardenTheme.typography.bodyLarge, + modifier = Modifier + .semantics { hideFromAccessibility() } + .testTag(tag = "FloatingOptionsItemName"), + ) + }, + onClick = { + onHideOverflowMenu() + data.onClick() + }, + ) +} + @Preview(showBackground = true) @Composable private fun BitwardenOverflowActionItem_preview() { diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/model/OverflowMenuItemData.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/model/OverflowMenuItemData.kt index f771862adb8..573110abec8 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/model/OverflowMenuItemData.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/appbar/model/OverflowMenuItemData.kt @@ -6,6 +6,7 @@ import androidx.compose.ui.graphics.Color * Data used to populate one row of an overflow dropdown menu. * * @param text The text displayed for the item in the menu. + * @param isExternalLink Indicates that this item will launch an external link. * @param onClick A callback for when the menu item is clicked. * @param isEnabled Indicates that this overflow item is enabled or not. * @param color The color of the content. @@ -13,6 +14,7 @@ import androidx.compose.ui.graphics.Color data class OverflowMenuItemData( val text: String, val onClick: () -> Unit, + val isExternalLink: Boolean = false, val isEnabled: Boolean = true, val color: Color = Color.Unspecified, ) diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenHelpIconButton.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenHelpIconButton.kt new file mode 100644 index 00000000000..1b8ca4b9834 --- /dev/null +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenHelpIconButton.kt @@ -0,0 +1,36 @@ +package com.bitwarden.ui.platform.components.button + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData +import com.bitwarden.ui.platform.resource.BitwardenDrawable +import com.bitwarden.ui.platform.resource.BitwardenString +import com.bitwarden.ui.platform.theme.BitwardenTheme + +/** + * A filled icon button that displays an icon. + * + * @param helpData All the relevant data for displaying a help icon button. + * @param modifier A [Modifier] for the composable. + */ +@Composable +fun BitwardenHelpIconButton( + helpData: BitwardenHelpButtonData, + modifier: Modifier = Modifier, +) { + BitwardenStandardIconButton( + vectorIconRes = BitwardenDrawable.ic_question_circle_small, + contentDescription = if (helpData.isExternalLink) { + stringResource( + id = BitwardenString.external_link_format, + formatArgs = arrayOf(helpData.contentDescription), + ) + } else { + helpData.contentDescription + }, + onClick = helpData.onClick, + contentColor = BitwardenTheme.colorScheme.icon.secondary, + modifier = modifier, + ) +} diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenTextSelectionButton.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenTextSelectionButton.kt index 169bb2a45ad..d6d149825a2 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenTextSelectionButton.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/BitwardenTextSelectionButton.kt @@ -31,11 +31,11 @@ import androidx.compose.ui.unit.dp import com.bitwarden.core.util.persistentListOfNotNull import com.bitwarden.ui.platform.base.util.cardStyle import com.bitwarden.ui.platform.base.util.nullableTestTag +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider import com.bitwarden.ui.platform.components.field.color.bitwardenTextFieldButtonColors import com.bitwarden.ui.platform.components.field.color.bitwardenTextFieldColors import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.row.BitwardenRowOfActions import com.bitwarden.ui.platform.components.util.rememberVectorPainter import com.bitwarden.ui.platform.resource.BitwardenDrawable @@ -53,7 +53,7 @@ fun BitwardenTextSelectionButton( modifier: Modifier = Modifier, enabled: Boolean = true, supportingText: String? = null, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, insets: PaddingValues = PaddingValues(), textFieldTestTag: String? = null, semanticRole: Role = Role.Button, @@ -67,7 +67,7 @@ fun BitwardenTextSelectionButton( cardStyle = cardStyle, modifier = modifier, enabled = enabled, - tooltip = tooltip, + helpData = helpData, insets = insets, textFieldTestTag = textFieldTestTag, semanticRole = semanticRole, @@ -100,7 +100,7 @@ fun BitwardenTextSelectionButton( modifier: Modifier = Modifier, enabled: Boolean = true, showChevron: Boolean = true, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, insets: PaddingValues = PaddingValues(), textFieldTestTag: String? = null, semanticRole: Role = Role.Button, @@ -115,7 +115,7 @@ fun BitwardenTextSelectionButton( role = semanticRole contentDescription = "$selectedOption. $label" customActions = persistentListOfNotNull( - tooltip?.let { + helpData?.let { CustomAccessibilityAction( label = it.contentDescription, action = { @@ -146,14 +146,11 @@ fun BitwardenTextSelectionButton( maxLines = 1, overflow = TextOverflow.Ellipsis, ) - tooltip?.let { + helpData?.let { Spacer(modifier = Modifier.width(8.dp)) - BitwardenStandardIconButton( - vectorIconRes = BitwardenDrawable.ic_question_circle_small, - contentDescription = it.contentDescription, - onClick = it.onClick, - contentColor = BitwardenTheme.colorScheme.icon.secondary, - modifier = Modifier.size(16.dp), + BitwardenHelpIconButton( + helpData = it, + modifier = Modifier.size(size = 16.dp), ) } } diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/model/TooltipData.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/model/BitwardenHelpButtonData.kt similarity index 63% rename from ui/src/main/kotlin/com/bitwarden/ui/platform/components/model/TooltipData.kt rename to ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/model/BitwardenHelpButtonData.kt index 9effdb11005..2e272237c82 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/model/TooltipData.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/button/model/BitwardenHelpButtonData.kt @@ -1,4 +1,4 @@ -package com.bitwarden.ui.platform.components.model +package com.bitwarden.ui.platform.components.button.model /** * Data class representing the data needed to create a tooltip icon in a composable. @@ -6,8 +6,10 @@ package com.bitwarden.ui.platform.components.model * @property onClick A lambda function that defines the action to be performed when the tooltip icon * is clicked. * @property contentDescription A text description of the icon for accessibility purposes. + * @property isExternalLink Indicates that this button will launch an external link. */ -data class TooltipData( +data class BitwardenHelpButtonData( val onClick: () -> Unit, val contentDescription: String, + val isExternalLink: Boolean, ) diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenMultiSelectButton.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenMultiSelectButton.kt index e696ec9dbf5..1ac08336aa9 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenMultiSelectButton.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenMultiSelectButton.kt @@ -21,11 +21,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.base.util.nullableTestTag import com.bitwarden.ui.platform.components.button.BitwardenTextSelectionButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.dialog.BitwardenSelectionDialog import com.bitwarden.ui.platform.components.dialog.row.BitwardenSelectionRow import com.bitwarden.ui.platform.components.dropdown.model.MultiSelectOption import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.theme.BitwardenTheme import com.bitwarden.ui.util.asText import kotlinx.collections.immutable.ImmutableList @@ -44,12 +44,12 @@ import kotlinx.collections.immutable.toImmutableList * (or `null` if no option is selected). * @param onOptionSelected A lambda that is invoked when an option is selected from the dropdown * menu. - * @param isEnabled Whether or not the button is enabled. + * @param isEnabled Whether the button is enabled. * @param cardStyle Indicates the type of card style to be applied. * @param modifier A [Modifier] that you can use to apply custom modifications to the composable. * @param dialogSubtitle The subtitle to apply to the dialog. - * @param supportingText A optional supporting text that will appear below the text field. - * @param tooltip A nullable [TooltipData], representing the tooltip icon. + * @param supportingText An optional supporting text that will appear below the text field. + * @param helpData An optional [BitwardenHelpButtonData], representing the help button. * @param insets Inner padding to be applied withing the card. * @param textFieldTestTag The optional test tag associated with the inner text field. * @param actionsPadding Padding to be applied to the [actions] block. @@ -68,7 +68,7 @@ fun BitwardenMultiSelectButton( dialogSubtitle: String? = null, isEnabled: Boolean = true, supportingText: String? = null, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, insets: PaddingValues = PaddingValues(), textFieldTestTag: String? = null, actionsPadding: PaddingValues = PaddingValues(end = 4.dp), @@ -93,7 +93,7 @@ fun BitwardenMultiSelectButton( ) } }, - tooltip = tooltip, + helpData = helpData, insets = insets, textFieldTestTag = textFieldTestTag, actionsPadding = actionsPadding, @@ -113,11 +113,11 @@ fun BitwardenMultiSelectButton( * (or `null` if no option is selected). * @param onOptionSelected A lambda that is invoked when an option is selected from the dropdown * menu. - * @param isEnabled Whether or not the button is enabled. + * @param isEnabled Whether the button is enabled. * @param supportingContent An optional supporting content that will appear below the button. * @param cardStyle Indicates the type of card style to be applied. * @param modifier A [Modifier] that you can use to apply custom modifications to the composable. - * @param tooltip A nullable [TooltipData], representing the tooltip icon. + * @param helpData An optional [BitwardenHelpButtonData], representing the help button. * @param insets Inner padding to be applied withing the card. * @param textFieldTestTag The optional test tag associated with the inner text field. * @param actionsPadding Padding to be applied to the [actions] block. @@ -136,7 +136,7 @@ fun BitwardenMultiSelectButton( dialogSubtitle: String? = null, isEnabled: Boolean = true, supportingContent: @Composable (ColumnScope.() -> Unit)?, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, insets: PaddingValues = PaddingValues(), textFieldTestTag: String? = null, actionsPadding: PaddingValues = PaddingValues(end = 4.dp), @@ -153,7 +153,7 @@ fun BitwardenMultiSelectButton( cardStyle = cardStyle, enabled = isEnabled, supportingContent = supportingContent, - tooltip = tooltip, + helpData = helpData, insets = insets, textFieldTestTag = textFieldTestTag, actionsPadding = actionsPadding, diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenTimePickerButton.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenTimePickerButton.kt index cccc47e66b5..2997e57d823 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenTimePickerButton.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/dropdown/BitwardenTimePickerButton.kt @@ -14,9 +14,9 @@ import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.components.button.BitwardenTextSelectionButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.dialog.BitwardenTimePickerDialog import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.resource.BitwardenPlurals import com.bitwarden.ui.platform.resource.BitwardenString @@ -28,12 +28,12 @@ private const val MINUTES_PER_HOUR: Int = 60 * @param label The descriptive text label for the [OutlinedTextField]. * @param totalMinutes The currently selected time value in minutes. * @param onTimeSelect A lambda that is invoked when a time is selected from the menu. - * @param is24Hour Whether or not the time should be displayed in 24-hour format. + * @param is24Hour Whether the time should be displayed in 24-hour format. * @param cardStyle Indicates the type of card style to be applied. * @param modifier A [Modifier] that you can use to apply custom modifications to the composable. - * @param isEnabled Whether or not the button is enabled. + * @param isEnabled Whether the button is enabled. * @param supportingContent An optional supporting content that will appear below the button. - * @param tooltip A nullable [TooltipData], representing the tooltip icon. + * @param helpData An optional [BitwardenHelpButtonData], representing the help button. * @param insets Inner padding to be applied within the card. * @param textFieldTestTag The optional test tag associated with the inner text field. * @param actionsPadding Padding to be applied to the [actions] block. @@ -51,7 +51,7 @@ fun BitwardenTimePickerButton( modifier: Modifier = Modifier, isEnabled: Boolean = true, supportingContent: @Composable (ColumnScope.() -> Unit)?, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, insets: PaddingValues = PaddingValues(), textFieldTestTag: String? = null, actionsPadding: PaddingValues = PaddingValues(end = 4.dp), @@ -67,7 +67,7 @@ fun BitwardenTimePickerButton( modifier = modifier, isEnabled = isEnabled, supportingContent = supportingContent, - tooltip = tooltip, + helpData = helpData, insets = insets, textFieldTestTag = textFieldTestTag, actionsPadding = actionsPadding, @@ -82,12 +82,12 @@ fun BitwardenTimePickerButton( * @param hours The currently selected time value in hours. * @param minutes The currently selected time value in minutes. * @param onTimeSelect A lambda that is invoked when a time is selected from the menu. - * @param is24Hour Whether or not the time should be displayed in 24-hour format. + * @param is24Hour Whether the time should be displayed in 24-hour format. * @param cardStyle Indicates the type of card style to be applied. * @param modifier A [Modifier] that you can use to apply custom modifications to the composable. - * @param isEnabled Whether or not the button is enabled. + * @param isEnabled Whether the button is enabled. * @param supportingContent An optional supporting content that will appear below the button. - * @param tooltip A nullable [TooltipData], representing the tooltip icon. + * @param helpData An optional [BitwardenHelpButtonData], representing the help button. * @param insets Inner padding to be applied within the card. * @param textFieldTestTag The optional test tag associated with the inner text field. * @param actionsPadding Padding to be applied to the [actions] block. @@ -106,7 +106,7 @@ fun BitwardenTimePickerButton( modifier: Modifier = Modifier, isEnabled: Boolean = true, supportingContent: @Composable (ColumnScope.() -> Unit)?, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, insets: PaddingValues = PaddingValues(), textFieldTestTag: String? = null, actionsPadding: PaddingValues = PaddingValues(end = 4.dp), @@ -152,7 +152,7 @@ fun BitwardenTimePickerButton( enabled = isEnabled, showChevron = false, supportingContent = supportingContent, - tooltip = tooltip, + helpData = helpData, insets = insets, textFieldTestTag = textFieldTestTag, actionsPadding = actionsPadding, diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenPasswordField.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenPasswordField.kt index 18842041baf..e976af17430 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenPasswordField.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenPasswordField.kt @@ -46,14 +46,15 @@ import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.base.util.cardStyle import com.bitwarden.ui.platform.base.util.nullableTestTag import com.bitwarden.ui.platform.base.util.tabNavigation +import com.bitwarden.ui.platform.components.button.BitwardenHelpIconButton import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider import com.bitwarden.ui.platform.components.field.color.bitwardenTextFieldColors import com.bitwarden.ui.platform.components.field.model.TextToolbarType import com.bitwarden.ui.platform.components.field.toolbar.BitwardenCutCopyTextToolbar import com.bitwarden.ui.platform.components.field.toolbar.BitwardenEmptyTextToolbar import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.row.BitwardenRowOfActions import com.bitwarden.ui.platform.components.support.BitwardenSupportingContent import com.bitwarden.ui.platform.components.util.nonLetterColorVisualTransformation @@ -68,13 +69,13 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme * * @param label Label for the text field. * @param value Current next on the text field. - * @param showPassword Whether or not password should be shown. + * @param showPassword Whether password should be shown. * @param showPasswordChange Lambda that is called when user request show/hide be toggled. * @param onValueChange Callback that is triggered when the password changes. * @param supportingContent An optional supporting content that will appear below the text input. * @param supportingContentPadding The padding to be placed on the [supportingContent]. * @param modifier Modifier for the composable. - * @param tooltip the optional tooltip to be displayed in the label. + * @param helpData An optional help button to be displayed in the label. * @param readOnly `true` if the input should be read-only and not accept user interactions. * @param singleLine when `true`, this text field becomes a single line that horizontally scrolls * instead of wrapping onto multiple lines. @@ -104,7 +105,7 @@ fun BitwardenPasswordField( supportingContent: @Composable (ColumnScope.() -> Unit)?, cardStyle: CardStyle, modifier: Modifier = Modifier, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, readOnly: Boolean = false, singleLine: Boolean = true, showPasswordTestTag: String? = null, @@ -160,7 +161,7 @@ fun BitwardenPasswordField( { Row(verticalAlignment = Alignment.CenterVertically) { Text(text = it) - tooltip?.let { tooltipData -> + helpData?.let { helpButtonData -> val targetSize = if (textFieldValue.text.isEmpty() || focused) { 16.dp } else { @@ -168,15 +169,12 @@ fun BitwardenPasswordField( } val size by animateDpAsState( targetValue = targetSize, - label = "${tooltipData.contentDescription}_animation", + label = "${helpButtonData.contentDescription}_animation", ) Spacer(modifier = Modifier.width(width = 8.dp)) - BitwardenStandardIconButton( - vectorIconRes = BitwardenDrawable.ic_question_circle_small, - contentDescription = tooltipData.contentDescription, - onClick = tooltipData.onClick, - contentColor = BitwardenTheme.colorScheme.icon.secondary, - modifier = Modifier.size(size), + BitwardenHelpIconButton( + helpData = helpButtonData, + modifier = Modifier.size(size = size), ) } } @@ -261,11 +259,11 @@ fun BitwardenPasswordField( * * @param label Label for the text field. * @param value Current next on the text field. - * @param showPassword Whether or not password should be shown. + * @param showPassword Whether password should be shown. * @param showPasswordChange Lambda that is called when user request show/hide be toggled. * @param onValueChange Callback that is triggered when the password changes. * @param modifier Modifier for the composable. - * @param tooltip the optional tooltip to be displayed in the label. + * @param helpData An optional help button to be displayed in the label. * @param readOnly `true` if the input should be read-only and not accept user interactions. * @param singleLine when `true`, this text field becomes a single line that horizontally scrolls * instead of wrapping onto multiple lines. @@ -294,7 +292,7 @@ fun BitwardenPasswordField( onValueChange: (String) -> Unit, cardStyle: CardStyle, modifier: Modifier = Modifier, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, readOnly: Boolean = false, singleLine: Boolean = true, supportingText: String? = null, @@ -316,7 +314,7 @@ fun BitwardenPasswordField( showPasswordTestTag = showPasswordTestTag, onValueChange = onValueChange, modifier = modifier, - tooltip = tooltip, + helpData = helpData, readOnly = readOnly, singleLine = singleLine, supportingContent = supportingText?.let { @@ -350,7 +348,7 @@ fun BitwardenPasswordField( * @param value Current next on the text field. * @param onValueChange Callback that is triggered when the password changes. * @param modifier Modifier for the composable. - * @param tooltip the optional tooltip to be displayed in the label. + * @param helpData An optional help button to be displayed in the label. * @param initialShowPassword The initial state of the show/hide password control. A value of * `false` (the default) indicates that that password should begin in the hidden state. * @param readOnly `true` if the input should be read-only and not accept user interactions. @@ -381,7 +379,7 @@ fun BitwardenPasswordField( supportingContent: @Composable (ColumnScope.() -> Unit)?, cardStyle: CardStyle, modifier: Modifier = Modifier, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, initialShowPassword: Boolean = false, readOnly: Boolean = false, singleLine: Boolean = true, @@ -405,7 +403,7 @@ fun BitwardenPasswordField( showPasswordTestTag = showPasswordTestTag, onValueChange = onValueChange, modifier = modifier, - tooltip = tooltip, + helpData = helpData, readOnly = readOnly, singleLine = singleLine, supportingContent = supportingContent, @@ -430,7 +428,7 @@ fun BitwardenPasswordField( * @param value Current next on the text field. * @param onValueChange Callback that is triggered when the password changes. * @param modifier Modifier for the composable. - * @param tooltip the optional tooltip to be displayed in the label. + * @param helpData An optional help button to be displayed in the label. * @param readOnly `true` if the input should be read-only and not accept user interactions. * @param singleLine when `true`, this text field becomes a single line that horizontally scrolls * instead of wrapping onto multiple lines. @@ -458,7 +456,7 @@ fun BitwardenPasswordField( onValueChange: (String) -> Unit, cardStyle: CardStyle, modifier: Modifier = Modifier, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, readOnly: Boolean = false, singleLine: Boolean = true, supportingText: String? = null, @@ -480,7 +478,7 @@ fun BitwardenPasswordField( showPassword = showPassword, showPasswordChange = { showPassword = !showPassword }, onValueChange = onValueChange, - tooltip = tooltip, + helpData = helpData, readOnly = readOnly, singleLine = singleLine, supportingText = supportingText, diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenTextField.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenTextField.kt index 150427875bb..d2b2f6770ed 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenTextField.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/field/BitwardenTextField.kt @@ -60,7 +60,8 @@ import com.bitwarden.ui.platform.base.util.simpleVerticalScrollbar import com.bitwarden.ui.platform.base.util.toPx import com.bitwarden.ui.platform.base.util.withLineBreaksAtWidth import com.bitwarden.ui.platform.components.appbar.color.bitwardenMenuItemColors -import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton +import com.bitwarden.ui.platform.components.button.BitwardenHelpIconButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider import com.bitwarden.ui.platform.components.field.color.bitwardenTextFieldColors import com.bitwarden.ui.platform.components.field.model.TextToolbarType @@ -69,10 +70,8 @@ import com.bitwarden.ui.platform.components.field.toolbar.BitwardenEmptyTextTool import com.bitwarden.ui.platform.components.icon.BitwardenIcon import com.bitwarden.ui.platform.components.icon.model.IconData import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.row.BitwardenRowOfActions import com.bitwarden.ui.platform.components.support.BitwardenSupportingContent -import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.theme.BitwardenTheme import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -86,7 +85,7 @@ import kotlinx.collections.immutable.toImmutableList * @param value current next on the text field. * @param modifier modifier for the composable. * @param onValueChange callback that is triggered when the input of the text field changes. - * @param tooltip the optional tooltip to be displayed in the label. + * @param helpData An optional help button to be displayed in the label. * @param placeholder the optional placeholder to be displayed when the text field is in focus and * the [value] is empty. * @param leadingIconData the optional resource for the leading icon on the text field. @@ -94,7 +93,7 @@ import kotlinx.collections.immutable.toImmutableList * @param singleLine when `true`, this text field becomes a single line that horizontally scrolls * instead of wrapping onto multiple lines. * @param readOnly `true` if the input should be read-only and not accept user interactions. - * @param enabled Whether or not the text field is enabled. + * @param enabled Whether the text field is enabled. * @param textStyle An optional style that may be used to override the default used. * @param textColor An optional color that may be used to override the text color. * @param shouldAddCustomLineBreaks If `true`, line breaks will be inserted to allow for filling @@ -119,7 +118,7 @@ fun BitwardenTextField( onValueChange: (String) -> Unit, cardStyle: CardStyle?, modifier: Modifier = Modifier, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, placeholder: String? = null, leadingIconData: IconData? = null, supportingText: String? = null, @@ -147,7 +146,7 @@ fun BitwardenTextField( label = label, value = value, onValueChange = onValueChange, - tooltip = tooltip, + helpData = helpData, placeholder = placeholder, leadingIconData = leadingIconData, supportingContent = supportingText?.let { @@ -189,7 +188,7 @@ fun BitwardenTextField( * @param label label for the text field. * @param value current next on the text field. * @param modifier modifier for the composable. - * @param tooltip the optional tooltip to be displayed in the label. + * @param helpData An optional help button to be displayed in the label. * @param onValueChange callback that is triggered when the input of the text field changes. * @param supportingContent An optional supporting content composable that will appear below the * text input. @@ -200,7 +199,7 @@ fun BitwardenTextField( * @param singleLine when `true`, this text field becomes a single line that horizontally scrolls * instead of wrapping onto multiple lines. * @param readOnly `true` if the input should be read-only and not accept user interactions. - * @param enabled Whether or not the text field is enabled. + * @param enabled Whether the text field is enabled. * @param textStyle An optional style that may be used to override the default used. * @param textColor An optional color that may be used to override the text color. * @param shouldAddCustomLineBreaks If `true`, line breaks will be inserted to allow for filling @@ -228,7 +227,7 @@ fun BitwardenTextField( supportingContent: (@Composable ColumnScope.() -> Unit)?, cardStyle: CardStyle?, modifier: Modifier = Modifier, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, supportingContentPadding: PaddingValues = PaddingValues(vertical = 12.dp, horizontal = 16.dp), placeholder: String? = null, leadingIconData: IconData? = null, @@ -309,7 +308,7 @@ fun BitwardenTextField( .fillMaxWidth() .semantics { customActions = listOfNotNull( - tooltip?.let { + helpData?.let { CustomAccessibilityAction( label = it.contentDescription, action = { @@ -330,7 +329,7 @@ fun BitwardenTextField( { Row(verticalAlignment = Alignment.CenterVertically) { Text(text = it) - tooltip?.let { tooltipData -> + helpData?.let { helpButtonData -> val targetSize = if (textFieldValue.text.isEmpty() || focused) { 16.dp } else { @@ -338,15 +337,12 @@ fun BitwardenTextField( } val size by animateDpAsState( targetValue = targetSize, - label = "${tooltipData.contentDescription}_animation", + label = "${helpButtonData.contentDescription}_animation", ) Spacer(modifier = Modifier.width(width = 8.dp)) - BitwardenStandardIconButton( - vectorIconRes = BitwardenDrawable.ic_question_circle_small, - contentDescription = tooltipData.contentDescription, - onClick = tooltipData.onClick, - contentColor = BitwardenTheme.colorScheme.icon.secondary, - modifier = Modifier.size(size), + BitwardenHelpIconButton( + helpData = helpButtonData, + modifier = Modifier.size(size = size), ) } } diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/row/BitwardenTextRow.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/row/BitwardenTextRow.kt index 587443b8bc0..a47148f75ce 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/row/BitwardenTextRow.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/row/BitwardenTextRow.kt @@ -22,11 +22,10 @@ import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.base.util.cardStyle import com.bitwarden.ui.platform.base.util.nullableTestTag import com.bitwarden.ui.platform.base.util.toAnnotatedString -import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton +import com.bitwarden.ui.platform.components.button.BitwardenHelpIconButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData -import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.theme.BitwardenTheme /** @@ -45,7 +44,7 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme * [isEnabled]. * @param withDivider Indicates if a divider should be drawn on the bottom of the row, defaults * to `false`. - * @param tooltip The data required to display a tooltip. + * @param helpData The data required to display a help button. * @param content The content of the [BitwardenTextRow]. */ @Suppress("LongMethod") @@ -60,7 +59,7 @@ fun BitwardenTextRow( isEnabled: Boolean = true, clickable: Boolean = isEnabled, withDivider: Boolean = false, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, content: (@Composable () -> Unit)? = null, ) { Box( @@ -96,7 +95,7 @@ fun BitwardenTextRow( }, modifier = Modifier.nullableTestTag(tag = textTestTag), ) - tooltip?.let { ToolTip(tooltip = it) } + helpData?.let { HelpButton(helpData = it) } } description?.let { Text( @@ -119,17 +118,13 @@ fun BitwardenTextRow( } @Composable -private fun RowScope.ToolTip( - tooltip: TooltipData, +private fun RowScope.HelpButton( + helpData: BitwardenHelpButtonData, ) { Spacer(modifier = Modifier.width(width = 8.dp)) - BitwardenStandardIconButton( - vectorIconRes = BitwardenDrawable.ic_question_circle_small, - contentDescription = tooltip.contentDescription, - onClick = tooltip.onClick, - contentColor = BitwardenTheme.colorScheme.icon.secondary, - modifier = Modifier - .testTag(tag = "TextRowTooltip"), + BitwardenHelpIconButton( + helpData = helpData, + modifier = Modifier.testTag(tag = "TextRowTooltip"), ) } @@ -144,9 +139,10 @@ private fun BitwardenTextRowWithTooltipAndContent_Preview() { textTestTag = "sampleTestTag", isEnabled = true, withDivider = false, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( contentDescription = "Tooltip Description", onClick = {}, + isExternalLink = false, ), ) } @@ -162,6 +158,6 @@ private fun BitwardenTextRowWithDividerDisabled_Preview() { textTestTag = "sampleDisabledTestTag", isEnabled = false, withDivider = true, - tooltip = null, + helpData = null, ) } diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/toggle/BitwardenSwitch.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/toggle/BitwardenSwitch.kt index d3916f92df7..7c0b60c1c9c 100644 --- a/ui/src/main/kotlin/com/bitwarden/ui/platform/components/toggle/BitwardenSwitch.kt +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/components/toggle/BitwardenSwitch.kt @@ -32,10 +32,11 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.bitwarden.ui.platform.base.util.cardStyle import com.bitwarden.ui.platform.base.util.toAnnotatedString +import com.bitwarden.ui.platform.components.button.BitwardenHelpIconButton import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton +import com.bitwarden.ui.platform.components.button.model.BitwardenHelpButtonData import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider import com.bitwarden.ui.platform.components.model.CardStyle -import com.bitwarden.ui.platform.components.model.TooltipData import com.bitwarden.ui.platform.components.row.BitwardenRowOfActions import com.bitwarden.ui.platform.components.support.BitwardenSupportingContent import com.bitwarden.ui.platform.components.toggle.color.bitwardenSwitchColors @@ -53,9 +54,9 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme * @param subtext The text to be displayed under the [label]. * @param supportingText An optional supporting text to be displayed below the [label]. * @param contentDescription A description of the switch's UI for accessibility purposes. - * @param tooltip The data required to display a tooltip. + * @param helpData The data required to display a help button. * @param readOnly Disables the click functionality without modifying the other UI characteristics. - * @param enabled Whether or not this switch is enabled. This is similar to setting [readOnly] but + * @param enabled Whether this switch is enabled. This is similar to setting [readOnly] but * comes with some additional visual changes. * @param actions A lambda containing the set of actions (usually icons or similar) to display * in between the [label] and the toggle. This lambda extends [RowScope], allowing flexibility in @@ -71,7 +72,7 @@ fun BitwardenSwitch( subtext: String? = null, supportingText: String? = null, contentDescription: String? = null, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, readOnly: Boolean = false, enabled: Boolean = true, actions: (@Composable RowScope.() -> Unit)? = null, @@ -83,7 +84,7 @@ fun BitwardenSwitch( isChecked = isChecked, onCheckedChange = onCheckedChange, contentDescription = contentDescription, - tooltip = tooltip, + helpData = helpData, readOnly = readOnly, enabled = enabled, cardStyle = cardStyle, @@ -115,9 +116,9 @@ fun BitwardenSwitch( * @param subtext The text to be displayed under the [label]. * @param supportingText An optional supporting text to be displayed below the [label]. * @param contentDescription A description of the switch's UI for accessibility purposes. - * @param tooltip The data required to display a tooltip. + * @param helpData The data required to display a help button. * @param readOnly Disables the click functionality without modifying the other UI characteristics. - * @param enabled Whether or not this switch is enabled. This is similar to setting [readOnly] but + * @param enabled Whether this switch is enabled. This is similar to setting [readOnly] but * comes with some additional visual changes. * @param actions A lambda containing the set of actions (usually icons or similar) to display * in between the [label] and the toggle. This lambda extends [RowScope], allowing flexibility in @@ -133,7 +134,7 @@ fun BitwardenSwitch( subtext: String? = null, supportingText: String? = null, contentDescription: String? = null, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, readOnly: Boolean = false, enabled: Boolean = true, actions: (@Composable RowScope.() -> Unit)? = null, @@ -145,7 +146,7 @@ fun BitwardenSwitch( isChecked = isChecked, onCheckedChange = onCheckedChange, contentDescription = contentDescription, - tooltip = tooltip, + helpData = helpData, readOnly = readOnly, enabled = enabled, cardStyle = cardStyle, @@ -177,7 +178,7 @@ fun BitwardenSwitch( * @param subtext The text to be displayed under the [label]. * @param contentDescription A description of the switch's UI for accessibility purposes. * @param readOnly Disables the click functionality without modifying the other UI characteristics. - * @param enabled Whether or not this switch is enabled. This is similar to setting [readOnly] but + * @param enabled Whether this switch is enabled. This is similar to setting [readOnly] but * comes with some additional visual changes. * @param actions A lambda containing the set of actions (usually icons or similar) to display * in between the [label] and the toggle. This lambda extends [RowScope], allowing flexibility in @@ -223,9 +224,9 @@ fun BitwardenSwitch( * @param modifier A [Modifier] that you can use to apply custom modifications to the composable. * @param subtext The text to be displayed under the [label]. * @param contentDescription A description of the switch's UI for accessibility purposes. - * @param tooltip The data required to display a tooltip. + * @param helpData The data required to display a help button. * @param readOnly Disables the click functionality without modifying the other UI characteristics. - * @param enabled Whether or not this switch is enabled. This is similar to setting [readOnly] but + * @param enabled Whether this switch is enabled. This is similar to setting [readOnly] but * comes with some additional visual changes. * @param actions A lambda containing the set of actions (usually icons or similar) to display * in between the [label] and the toggle. This lambda extends [RowScope], allowing flexibility in @@ -242,7 +243,7 @@ fun BitwardenSwitch( modifier: Modifier = Modifier, subtext: String? = null, contentDescription: String? = null, - tooltip: TooltipData? = null, + helpData: BitwardenHelpButtonData? = null, readOnly: Boolean = false, enabled: Boolean = true, supportingContentPadding: PaddingValues = PaddingValues(vertical = 12.dp, horizontal = 16.dp), @@ -291,9 +292,9 @@ fun BitwardenSwitch( } .testTag(tag = "SwitchText"), ) - tooltip?.let { - ToolTip( - tooltip = it, + helpData?.let { + HelpButton( + helpData = it, isVisible = subtext != null, size = 16.dp, ) @@ -315,7 +316,7 @@ fun BitwardenSwitch( ) } } - tooltip?.let { ToolTip(tooltip = it, isVisible = subtext == null) } + helpData?.let { HelpButton(helpData = it, isVisible = subtext == null) } } Spacer(modifier = Modifier.width(width = 16.dp)) Switch( @@ -360,18 +361,15 @@ private fun ColumnScope.SupportingContent( } @Composable -private fun RowScope.ToolTip( - tooltip: TooltipData, +private fun RowScope.HelpButton( + helpData: BitwardenHelpButtonData, isVisible: Boolean, size: Dp = 48.dp, ) { if (!isVisible) return Spacer(modifier = Modifier.width(width = 8.dp)) - BitwardenStandardIconButton( - vectorIconRes = BitwardenDrawable.ic_question_circle_small, - contentDescription = tooltip.contentDescription, - onClick = tooltip.onClick, - contentColor = BitwardenTheme.colorScheme.icon.secondary, + BitwardenHelpIconButton( + helpData = helpData, modifier = Modifier .size(size = size) .testTag(tag = "SwitchTooltip"), @@ -402,9 +400,10 @@ private fun BitwardenSwitch_preview() { supportingText = "description", isChecked = true, onCheckedChange = {}, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = { }, contentDescription = "content description", + isExternalLink = false, ), actions = { BitwardenStandardIconButton( @@ -420,9 +419,10 @@ private fun BitwardenSwitch_preview() { supportingText = "description", isChecked = true, onCheckedChange = {}, - tooltip = TooltipData( + helpData = BitwardenHelpButtonData( onClick = { }, contentDescription = "content description", + isExternalLink = true, ), cardStyle = CardStyle.Middle(), ) diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index c48ba203acb..bb89a42e878 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -836,6 +836,7 @@ Do you want to switch to this account? Fill out the form and import your saved password file. For your security, be sure to delete your saved password file. Need help? Check out import help. + import help Save the exported file somewhere on your computer you can find easily. This is not a recognized Bitwarden server. You may need to check with your provider or update your server. Syncing logins… @@ -1220,4 +1221,5 @@ Do you want to switch to this account? Launch browser Continue without syncing External link + %1$s, External link