Minor design tweaks for action cards (#5934)

This commit is contained in:
David Perez 2025-09-24 12:17:46 -05:00 committed by GitHub
parent e91ba77105
commit 89ad7818f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -4,6 +4,7 @@ import android.content.res.Configuration
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -14,11 +15,18 @@ import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInParent
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.base.util.toDp
import com.bitwarden.ui.platform.components.badge.NotificationBadge import com.bitwarden.ui.platform.components.badge.NotificationBadge
import com.bitwarden.ui.platform.components.button.BitwardenFilledButton import com.bitwarden.ui.platform.components.button.BitwardenFilledButton
import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
@ -39,6 +47,7 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme
* @param leadingContent Optional content to display on the leading side of the * @param leadingContent Optional content to display on the leading side of the
* [cardTitle] [Text]. * [cardTitle] [Text].
*/ */
@Suppress("LongMethod")
@Composable @Composable
fun BitwardenActionCard( fun BitwardenActionCard(
cardTitle: String, cardTitle: String,
@ -56,19 +65,47 @@ fun BitwardenActionCard(
elevation = CardDefaults.elevatedCardElevation(), elevation = CardDefaults.elevatedCardElevation(),
border = BorderStroke(width = 1.dp, color = BitwardenTheme.colorScheme.stroke.border), border = BorderStroke(width = 1.dp, color = BitwardenTheme.colorScheme.stroke.border),
) { ) {
Row(modifier = Modifier.fillMaxWidth()) { var rowBottomPx by remember { mutableIntStateOf(0) }
Spacer(Modifier.width(16.dp)) var titleBottomPx by remember { mutableIntStateOf(0) }
Row(modifier = Modifier.padding(top = 16.dp)) { Row(
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned {
rowBottomPx = it.positionInParent().y.toInt() + it.size.height
},
) {
Spacer(modifier = Modifier.width(width = 16.dp))
Row(
modifier = Modifier
.padding(top = 16.dp)
.weight(weight = 1f),
) {
leadingContent?.let { leadingContent?.let {
it() it()
Spacer(Modifier.width(12.dp)) Spacer(modifier = Modifier.width(width = 12.dp))
}
Column(
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = cardTitle,
style = BitwardenTheme.typography.titleMedium,
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned {
titleBottomPx = it.positionInParent().y.toInt() + it.size.height
},
)
cardSubtitle?.let {
Spacer(modifier = Modifier.height(height = 4.dp))
Text(
text = it,
style = BitwardenTheme.typography.bodyMedium,
modifier = Modifier.fillMaxWidth(),
)
}
} }
Text(
text = cardTitle,
style = BitwardenTheme.typography.titleMedium,
)
} }
Spacer(Modifier.weight(1f))
onDismissClick?.let { onDismissClick?.let {
BitwardenStandardIconButton( BitwardenStandardIconButton(
painter = rememberVectorPainter(id = BitwardenDrawable.ic_close), painter = rememberVectorPainter(id = BitwardenDrawable.ic_close),
@ -77,17 +114,17 @@ fun BitwardenActionCard(
) )
} }
} }
cardSubtitle?.let { if (cardSubtitle == null && rowBottomPx > titleBottomPx) {
Spacer(Modifier.height(4.dp)) // When the subtitle is missing, we want to ensure that the filled button is 16dp below
Text( // the title but the close button can be taller than the title which will push the
text = it, // button further down. So we measure the difference and use that to offset the spacer
style = BitwardenTheme.typography.bodyMedium, // size.
modifier = Modifier Spacer(
.padding(horizontal = 16.dp) modifier = Modifier.height(height = 16.dp - (rowBottomPx - titleBottomPx).toDp()),
.fillMaxWidth(),
) )
} else {
Spacer(modifier = Modifier.height(height = 16.dp))
} }
Spacer(Modifier.height(16.dp))
BitwardenFilledButton( BitwardenFilledButton(
label = actionText, label = actionText,
onClick = onActionClick, onClick = onActionClick,
@ -95,7 +132,7 @@ fun BitwardenActionCard(
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
.fillMaxWidth(), .fillMaxWidth(),
) )
Spacer(Modifier.height(16.dp)) Spacer(modifier = Modifier.height(height = 16.dp))
} }
} }