mirror of
https://github.com/bitwarden/android.git
synced 2026-03-21 13:52:07 -05:00
PM-19653: Add tooltip and subtext tupport for the switch (#4936)
This commit is contained in:
@@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
@@ -23,7 +24,9 @@ import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.toggleableState
|
||||
import androidx.compose.ui.state.ToggleableState
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.cardStyle
|
||||
@@ -31,6 +34,8 @@ import com.x8bit.bitwarden.ui.platform.base.util.toAnnotatedString
|
||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.TooltipData
|
||||
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenRowOfActions
|
||||
import com.x8bit.bitwarden.ui.platform.components.toggle.color.bitwardenSwitchColors
|
||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
|
||||
@@ -42,8 +47,10 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
* @param onCheckedChange A lambda that is invoked when the switch's state changes.
|
||||
* @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 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 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
|
||||
* comes with some additional visual changes.
|
||||
@@ -58,8 +65,10 @@ fun BitwardenSwitch(
|
||||
onCheckedChange: ((Boolean) -> Unit)?,
|
||||
cardStyle: CardStyle?,
|
||||
modifier: Modifier = Modifier,
|
||||
subtext: String? = null,
|
||||
supportingText: String? = null,
|
||||
contentDescription: String? = null,
|
||||
tooltip: TooltipData? = null,
|
||||
readOnly: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
actions: (@Composable RowScope.() -> Unit)? = null,
|
||||
@@ -67,9 +76,11 @@ fun BitwardenSwitch(
|
||||
BitwardenSwitch(
|
||||
modifier = modifier,
|
||||
label = label.toAnnotatedString(),
|
||||
subtext = subtext,
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
contentDescription = contentDescription,
|
||||
tooltip = tooltip,
|
||||
readOnly = readOnly,
|
||||
enabled = enabled,
|
||||
cardStyle = cardStyle,
|
||||
@@ -98,8 +109,10 @@ fun BitwardenSwitch(
|
||||
* @param onCheckedChange A lambda that is invoked when the switch's state changes.
|
||||
* @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 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 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
|
||||
* comes with some additional visual changes.
|
||||
@@ -114,8 +127,10 @@ fun BitwardenSwitch(
|
||||
onCheckedChange: ((Boolean) -> Unit)?,
|
||||
cardStyle: CardStyle?,
|
||||
modifier: Modifier = Modifier,
|
||||
subtext: String? = null,
|
||||
supportingText: String? = null,
|
||||
contentDescription: String? = null,
|
||||
tooltip: TooltipData? = null,
|
||||
readOnly: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
actions: (@Composable RowScope.() -> Unit)? = null,
|
||||
@@ -123,9 +138,11 @@ fun BitwardenSwitch(
|
||||
BitwardenSwitch(
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
subtext = subtext,
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
contentDescription = contentDescription,
|
||||
tooltip = tooltip,
|
||||
readOnly = readOnly,
|
||||
enabled = enabled,
|
||||
cardStyle = cardStyle,
|
||||
@@ -154,6 +171,7 @@ fun BitwardenSwitch(
|
||||
* @param onCheckedChange A lambda that is invoked when the switch's state changes.
|
||||
* @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 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
|
||||
@@ -170,6 +188,7 @@ fun BitwardenSwitch(
|
||||
onCheckedChange: ((Boolean) -> Unit)?,
|
||||
cardStyle: CardStyle?,
|
||||
modifier: Modifier = Modifier,
|
||||
subtext: String? = null,
|
||||
contentDescription: String? = null,
|
||||
readOnly: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
@@ -179,6 +198,7 @@ fun BitwardenSwitch(
|
||||
BitwardenSwitch(
|
||||
modifier = modifier,
|
||||
label = label.toAnnotatedString(),
|
||||
subtext = subtext,
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
contentDescription = contentDescription,
|
||||
@@ -198,7 +218,9 @@ fun BitwardenSwitch(
|
||||
* @param onCheckedChange A lambda that is invoked when the switch's state changes.
|
||||
* @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 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 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
|
||||
* comes with some additional visual changes.
|
||||
@@ -207,7 +229,7 @@ fun BitwardenSwitch(
|
||||
* defining the layout of the actions.
|
||||
* @param supportingContent A lambda containing content directly below the label.
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
fun BitwardenSwitch(
|
||||
label: AnnotatedString,
|
||||
@@ -215,7 +237,9 @@ fun BitwardenSwitch(
|
||||
onCheckedChange: ((Boolean) -> Unit)?,
|
||||
cardStyle: CardStyle?,
|
||||
modifier: Modifier = Modifier,
|
||||
subtext: String? = null,
|
||||
contentDescription: String? = null,
|
||||
tooltip: TooltipData? = null,
|
||||
readOnly: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
supportingContentPadding: PaddingValues = PaddingValues(vertical = 12.dp, horizontal = 16.dp),
|
||||
@@ -240,26 +264,50 @@ fun BitwardenSwitch(
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = 36.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
modifier = Modifier.defaultMinSize(minHeight = 36.dp),
|
||||
) {
|
||||
Spacer(modifier = Modifier.width(width = 16.dp))
|
||||
Row(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = BitwardenTheme.typography.bodyLarge,
|
||||
color = if (enabled) {
|
||||
BitwardenTheme.colorScheme.text.primary
|
||||
} else {
|
||||
BitwardenTheme.colorScheme.filledButton.foregroundDisabled
|
||||
},
|
||||
modifier = Modifier.testTag(tag = "SwitchText"),
|
||||
)
|
||||
|
||||
actions?.invoke(this)
|
||||
Column(modifier = Modifier.weight(weight = 1f, fill = false)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = label,
|
||||
style = BitwardenTheme.typography.bodyLarge,
|
||||
color = if (enabled) {
|
||||
BitwardenTheme.colorScheme.text.primary
|
||||
} else {
|
||||
BitwardenTheme.colorScheme.filledButton.foregroundDisabled
|
||||
},
|
||||
modifier = Modifier.testTag(tag = "SwitchText"),
|
||||
)
|
||||
tooltip?.let {
|
||||
ToolTip(
|
||||
tooltip = it,
|
||||
isVisible = subtext != null,
|
||||
size = 16.dp,
|
||||
)
|
||||
}
|
||||
}
|
||||
subtext?.let {
|
||||
Spacer(modifier = Modifier.height(height = 2.dp))
|
||||
Text(
|
||||
text = it,
|
||||
style = BitwardenTheme.typography.bodyMedium,
|
||||
color = if (enabled) {
|
||||
BitwardenTheme.colorScheme.text.secondary
|
||||
} else {
|
||||
BitwardenTheme.colorScheme.filledButton.foregroundDisabled
|
||||
},
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.testTag(tag = "SwitchSubtext"),
|
||||
)
|
||||
}
|
||||
}
|
||||
tooltip?.let { ToolTip(tooltip = it, isVisible = subtext == null) }
|
||||
}
|
||||
Spacer(modifier = Modifier.width(width = 16.dp))
|
||||
Switch(
|
||||
@@ -271,20 +319,13 @@ fun BitwardenSwitch(
|
||||
onCheckedChange = null,
|
||||
colors = bitwardenSwitchColors(),
|
||||
)
|
||||
actions?.let { BitwardenRowOfActions(actions = it) }
|
||||
Spacer(modifier = Modifier.width(width = if (actions == null) 16.dp else 4.dp))
|
||||
}
|
||||
supportingContent
|
||||
?.let { content ->
|
||||
Spacer(modifier = Modifier.height(height = 12.dp))
|
||||
BitwardenHorizontalDivider(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp),
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = 48.dp)
|
||||
.padding(paddingValues = supportingContentPadding),
|
||||
SupportingContent(
|
||||
paddingValues = supportingContentPadding,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -292,6 +333,45 @@ fun BitwardenSwitch(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.SupportingContent(
|
||||
paddingValues: PaddingValues,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(height = 12.dp))
|
||||
BitwardenHorizontalDivider(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = 48.dp)
|
||||
.padding(paddingValues = paddingValues),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RowScope.ToolTip(
|
||||
tooltip: TooltipData,
|
||||
isVisible: Boolean,
|
||||
size: Dp = 48.dp,
|
||||
) {
|
||||
if (!isVisible) return
|
||||
Spacer(modifier = Modifier.width(width = 8.dp))
|
||||
BitwardenStandardIconButton(
|
||||
vectorIconRes = R.drawable.ic_question_circle_small,
|
||||
contentDescription = tooltip.contentDescription,
|
||||
onClick = tooltip.onClick,
|
||||
contentColor = BitwardenTheme.colorScheme.icon.secondary,
|
||||
modifier = Modifier
|
||||
.size(size = size)
|
||||
.testTag(tag = "SwitchTooltip"),
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun BitwardenSwitch_preview() {
|
||||
@@ -314,22 +394,37 @@ private fun BitwardenSwitch_preview() {
|
||||
supportingText = "description",
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
tooltip = TooltipData(
|
||||
onClick = { },
|
||||
contentDescription = "content description",
|
||||
),
|
||||
actions = {
|
||||
BitwardenStandardIconButton(
|
||||
vectorIconRes = R.drawable.ic_question_circle,
|
||||
vectorIconRes = R.drawable.ic_generate,
|
||||
contentDescription = "content description",
|
||||
onClick = {},
|
||||
)
|
||||
},
|
||||
cardStyle = CardStyle.Middle(),
|
||||
)
|
||||
BitwardenSwitch(
|
||||
label = "Label",
|
||||
supportingText = "description",
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
tooltip = TooltipData(
|
||||
onClick = { },
|
||||
contentDescription = "content description",
|
||||
),
|
||||
cardStyle = CardStyle.Middle(),
|
||||
)
|
||||
BitwardenSwitch(
|
||||
label = "Label",
|
||||
isChecked = false,
|
||||
onCheckedChange = {},
|
||||
actions = {
|
||||
BitwardenStandardIconButton(
|
||||
vectorIconRes = R.drawable.ic_question_circle,
|
||||
vectorIconRes = R.drawable.ic_generate,
|
||||
contentDescription = "content description",
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
@@ -13,13 +13,12 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.field.BitwardenTextField
|
||||
import com.x8bit.bitwarden.ui.platform.components.header.BitwardenExpandingHeader
|
||||
import com.x8bit.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.TooltipData
|
||||
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
|
||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.x8bit.bitwarden.ui.platform.util.persistentListOfNotNull
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldType
|
||||
@@ -79,16 +78,12 @@ fun LazyListScope.vaultAddEditAdditionalOptions(
|
||||
label = stringResource(id = R.string.password_prompt),
|
||||
isChecked = commonState.masterPasswordReprompt,
|
||||
onCheckedChange = commonTypeHandlers.onToggleMasterPasswordReprompt,
|
||||
actions = {
|
||||
BitwardenStandardIconButton(
|
||||
vectorIconRes = R.drawable.ic_question_circle_small,
|
||||
contentDescription = stringResource(
|
||||
id = R.string.master_password_re_prompt_help,
|
||||
),
|
||||
onClick = commonTypeHandlers.onTooltipClick,
|
||||
contentColor = BitwardenTheme.colorScheme.icon.secondary,
|
||||
)
|
||||
},
|
||||
tooltip = TooltipData(
|
||||
onClick = commonTypeHandlers.onTooltipClick,
|
||||
contentDescription = stringResource(
|
||||
id = R.string.master_password_re_prompt_help,
|
||||
),
|
||||
),
|
||||
cardStyle = CardStyle.Full,
|
||||
modifier = Modifier
|
||||
.testTag(tag = "MasterPasswordRepromptToggle")
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
package com.x8bit.bitwarden.ui.vault.feature.addedit
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.cardStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenSelectionDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTextEntryDialog
|
||||
@@ -25,7 +20,6 @@ import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectB
|
||||
import com.x8bit.bitwarden.ui.platform.components.field.BitwardenPasswordField
|
||||
import com.x8bit.bitwarden.ui.platform.components.field.BitwardenTextField
|
||||
import com.x8bit.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenRowOfActions
|
||||
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldAction
|
||||
import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType
|
||||
@@ -155,38 +149,21 @@ private fun CustomFieldBoolean(
|
||||
cardStyle: CardStyle,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.semantics(mergeDescendants = true) {}
|
||||
.defaultMinSize(minHeight = 60.dp)
|
||||
.cardStyle(
|
||||
cardStyle = cardStyle,
|
||||
onClick = { onValueChanged(!value) },
|
||||
paddingEnd = 4.dp,
|
||||
paddingTop = 6.dp,
|
||||
paddingBottom = 6.dp,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = label,
|
||||
isChecked = value,
|
||||
onCheckedChange = null,
|
||||
cardStyle = null,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
|
||||
BitwardenRowOfActions(
|
||||
actions = {
|
||||
BitwardenStandardIconButton(
|
||||
vectorIconRes = R.drawable.ic_cog,
|
||||
contentDescription = stringResource(id = R.string.edit),
|
||||
onClick = onEditValue,
|
||||
modifier = Modifier.testTag("CustomFieldSettingsButton"),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
BitwardenSwitch(
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isChecked = value,
|
||||
onCheckedChange = onValueChanged,
|
||||
cardStyle = cardStyle,
|
||||
actions = {
|
||||
BitwardenStandardIconButton(
|
||||
vectorIconRes = R.drawable.ic_cog,
|
||||
contentDescription = stringResource(id = R.string.edit),
|
||||
onClick = onEditValue,
|
||||
modifier = Modifier.testTag(tag = "CustomFieldSettingsButton"),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user