misc: Add support for icons in buttons via BitwardenButtonData (#6682)

This commit is contained in:
David Perez
2026-03-17 11:12:48 -05:00
committed by GitHub
parent fcfa647806
commit 7666fb82b8
9 changed files with 48 additions and 20 deletions

View File

@@ -22,6 +22,7 @@ import com.bitwarden.ui.platform.components.appbar.BitwardenMediumTopAppBar
import com.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActionItem
import com.bitwarden.ui.platform.components.appbar.action.BitwardenSearchActionItem
import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent
import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
@@ -38,6 +39,7 @@ import com.bitwarden.ui.platform.composition.LocalIntentManager
import com.bitwarden.ui.platform.manager.IntentManager
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManager
import com.x8bit.bitwarden.data.platform.manager.util.RegisterScreenDataOnLifecycleEffect
@@ -194,7 +196,10 @@ fun SendScreen(
is SendState.ViewState.Error -> BitwardenErrorContent(
message = viewState.message(),
onButtonClick = { viewModel.trySendAction(SendAction.RefreshClick) },
buttonData = BitwardenButtonData(
label = BitwardenString.try_again.asText(),
onClick = { viewModel.trySendAction(SendAction.RefreshClick) },
),
modifier = modifier,
)

View File

@@ -25,6 +25,7 @@ import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActionItem
import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData
import com.bitwarden.ui.platform.components.button.BitwardenTextButton
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent
import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
@@ -39,6 +40,7 @@ import com.bitwarden.ui.platform.composition.LocalIntentManager
import com.bitwarden.ui.platform.manager.IntentManager
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultCardItemTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultCommonItemTypeHandlers
@@ -340,6 +342,7 @@ private fun VaultItemDialogs(
}
}
@Suppress("LongMethod")
@Composable
private fun VaultItemContent(
viewState: VaultItemState.ViewState,
@@ -353,7 +356,10 @@ private fun VaultItemContent(
when (viewState) {
is VaultItemState.ViewState.Error -> BitwardenErrorContent(
message = viewState.message(),
onButtonClick = vaultCommonItemTypeHandlers.onRefreshClick,
buttonData = BitwardenButtonData(
label = BitwardenString.try_again.asText(),
onClick = vaultCommonItemTypeHandlers.onRefreshClick,
),
modifier = modifier,
)

View File

@@ -27,6 +27,7 @@ import com.bitwarden.ui.platform.components.appbar.NavigationIcon
import com.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActionItem
import com.bitwarden.ui.platform.components.appbar.action.BitwardenSearchActionItem
import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent
import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
@@ -526,7 +527,10 @@ private fun VaultItemListingScaffold(
is VaultItemListingState.ViewState.Error -> {
BitwardenErrorContent(
message = state.viewState.message(),
onButtonClick = vaultItemListingHandlers.refreshClick,
buttonData = BitwardenButtonData(
label = BitwardenString.try_again.asText(),
onClick = vaultItemListingHandlers.refreshClick,
),
modifier = Modifier.fillMaxSize(),
)
}

View File

@@ -38,6 +38,7 @@ import com.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActio
import com.bitwarden.ui.platform.components.appbar.action.BitwardenSearchActionItem
import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData
import com.bitwarden.ui.platform.components.appbar.model.TopAppBarDividerStyle
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.bitwarden.ui.platform.components.card.actionCardExitAnimation
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
@@ -59,6 +60,7 @@ import com.bitwarden.ui.platform.manager.IntentManager
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenPlurals
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenMasterPasswordDialog
import com.x8bit.bitwarden.ui.platform.composition.LocalAppReviewManager
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
@@ -371,7 +373,10 @@ private fun VaultScreenScaffold(
is VaultState.ViewState.Error -> BitwardenErrorContent(
message = viewState.message(),
onButtonClick = vaultHandlers.tryAgainClick,
buttonData = BitwardenButtonData(
label = BitwardenString.try_again.asText(),
onClick = vaultHandlers.tryAgainClick,
),
modifier = Modifier.fillMaxSize(),
)
}

View File

@@ -29,6 +29,7 @@ import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActionItem
import com.bitwarden.ui.platform.components.appbar.action.BitwardenSearchActionItem
import com.bitwarden.ui.platform.components.appbar.model.OverflowMenuItemData
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent
import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
@@ -39,6 +40,7 @@ import com.bitwarden.ui.platform.components.scaffold.model.rememberBitwardenPull
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManager
import com.x8bit.bitwarden.data.platform.manager.util.RegisterScreenDataOnLifecycleEffect
@@ -148,7 +150,10 @@ fun VerificationCodeScreen(
is VerificationCodeState.ViewState.Error -> {
BitwardenErrorContent(
message = viewState.message.invoke(),
onButtonClick = verificationCodeHandler.refreshClick,
buttonData = BitwardenButtonData(
label = BitwardenString.try_again.asText(),
onClick = verificationCodeHandler.refreshClick,
),
modifier = Modifier.fillMaxSize(),
)
}

View File

@@ -1,16 +1,19 @@
package com.bitwarden.ui.platform.components.button.model
import androidx.compose.ui.graphics.painter.Painter
import com.bitwarden.ui.util.Text
/**
* Represents the data required to render a button.
*
* @param label The text to be displayed on the button.
* @param onClick A lambda function to be executed when the button is clicked.
* @param testTag A optional unique identifier for testing purposes.
* @property label The text to be displayed on the button.
* @property onClick A lambda function to be executed when the button is clicked.
* @property icon An optional icon to be displayed with the button.
* @property testTag A optional unique identifier for testing purposes.
*/
data class BitwardenButtonData(
val label: Text,
val onClick: () -> Unit,
val icon: Painter? = null,
val testTag: String? = null,
)

View File

@@ -142,6 +142,7 @@ fun BitwardenActionCard(
BitwardenTextButton(
label = it.label(),
onClick = it.onClick,
icon = it.icon,
modifier = Modifier
.padding(horizontal = 16.dp)
.nullableTestTag(tag = it.testTag)

View File

@@ -100,6 +100,7 @@ fun BitwardenEmptyContent(
BitwardenFilledButton(
label = it.label(),
onClick = it.onClick,
icon = it.icon,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
@@ -116,6 +117,7 @@ fun BitwardenEmptyContent(
BitwardenOutlinedButton(
label = it.label(),
onClick = it.onClick,
icon = it.icon,
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()

View File

@@ -14,13 +14,12 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.components.button.BitwardenTextButton
import com.bitwarden.ui.platform.components.button.BitwardenFilledButton
import com.bitwarden.ui.platform.components.button.model.BitwardenButtonData
import com.bitwarden.ui.platform.components.icon.BitwardenIcon
import com.bitwarden.ui.platform.components.icon.model.IconData
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
/**
@@ -29,17 +28,14 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme
* @param message The text content to display.
* @param modifier The [Modifier] to be applied to the layout.
* @param illustrationData Optional illustration to display above the text.
* @param buttonText The text to be displayed on the button. This will not be used if the
* [onButtonClick] is null.
* @param onButtonClick An optional callback to invoke when the button is clicked.
* @param buttonData Optional button to display below the text.
*/
@Composable
fun BitwardenErrorContent(
message: String,
modifier: Modifier = Modifier,
illustrationData: IconData? = null,
buttonText: String = stringResource(id = BitwardenString.try_again),
onButtonClick: (() -> Unit)? = null,
buttonData: BitwardenButtonData? = null,
) {
Column(
modifier = modifier.verticalScroll(rememberScrollState()),
@@ -62,11 +58,12 @@ fun BitwardenErrorContent(
.padding(horizontal = 16.dp)
.fillMaxWidth(),
)
onButtonClick?.let {
buttonData?.let {
Spacer(modifier = Modifier.height(16.dp))
BitwardenTextButton(
label = buttonText,
onClick = it,
BitwardenFilledButton(
label = it.label(),
onClick = it.onClick,
icon = it.icon,
modifier = Modifier.padding(horizontal = 16.dp),
)
}