From b6bb13ebfdf5efed71b3778940475440a640980b Mon Sep 17 00:00:00 2001 From: stylianosgakis Date: Thu, 3 Sep 2026 11:10:59 +0200 Subject: [PATCH] design-system: round every button at every size Designers asked for all buttons in the app to be rounded, matching what the home screen already does. Corner radius stops being a per-size property and becomes one ButtonTokens.ContainerShape (CornerFull) that every button reads, so a button's radius is no longer a choice a call site can make. The radius tokens themselves are untouched and still used by cards, sheets, fields and the rest of the system. Only buttons lose the option. Drops the HedvigButton `shape` override and the buttonShape parameter that CrossSells threaded through five composables to reach it, since every caller that passed one was asking for the shape that is now the default. RoundedPrimary and RoundedLiquidGlass already resolved to CornerFull, so the home screen renders unchanged; the visual diff is in the other six styles. --- .../android/design/system/hedvig/Button.kt | 43 +++---------------- .../system/hedvig/tokens/ButtonTokens.kt | 16 ++++--- .../feature/home/home/ui/HomeDestination.kt | 3 -- .../hedvig/android/crosssells/CrossSells.kt | 12 ------ 4 files changed, 16 insertions(+), 58 deletions(-) diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Button.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Button.kt index fc0fe2599a..4cd57a80c0 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Button.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Button.kt @@ -31,7 +31,6 @@ import androidx.compose.ui.draw.dropShadow import androidx.compose.ui.draw.innerShadow import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.graphics.shadow.Shadow import androidx.compose.ui.semantics.Role @@ -44,6 +43,7 @@ import androidx.compose.ui.unit.dp import com.hedvig.android.compose.ui.LayoutWithoutPlacement import com.hedvig.android.compose.ui.withoutPlacement import com.hedvig.android.design.system.hedvig.ButtonDefaults.ButtonSize +import com.hedvig.android.design.system.hedvig.tokens.ButtonTokens import com.hedvig.android.design.system.hedvig.tokens.GhostStyleButtonTokens import com.hedvig.android.design.system.hedvig.tokens.LargeSizeButtonTokens import com.hedvig.android.design.system.hedvig.tokens.MediumSizeButtonTokens @@ -78,7 +78,6 @@ fun HedvigButton( border: Color? = null, onClickLabel: String? = null, isLoading: Boolean = false, - shape: Shape? = null, ) { HedvigButton( onClick = onClick, @@ -89,7 +88,6 @@ fun HedvigButton( interactionSource = interactionSource, border = border, onClickLabel = onClickLabel, - shape = shape, isLoading = isLoading, ) { val buttonColors = buttonStyle.style.buttonColors @@ -131,7 +129,6 @@ fun HedvigButton( interactionSource: MutableInteractionSource? = null, border: Color? = null, onClickLabel: String? = null, - shape: Shape? = null, isLoading: Boolean = false, content: @Composable RowScope.() -> Unit, ) { @@ -152,8 +149,7 @@ fun HedvigButton( }, ) - @Suppress("NAME_SHADOWING") - val shape = shape ?: size.shape + val shape = ButtonTokens.ContainerShape.value val glass = style.glassMaterial.takeIf { enabled } Surface( onClick = onClick, @@ -271,7 +267,7 @@ fun HedvigButtonGhostWithBorder( modifier = modifier.border( width = 1.dp, color = HedvigTheme.colorScheme.borderPrimary, - shape = size.size.shape, + shape = ButtonTokens.ContainerShape.value, ), buttonSize = size, interactionSource = interactionSource, @@ -351,8 +347,9 @@ private val ButtonSize.size: Size } /** - * The metrics this size takes on within [style]. The rounded styles get their own pill metrics at - * [ButtonSize.Large]; at every smaller size they fall back to the standard button metrics. + * The metrics this size takes on within [style]. The glass styles get their own tighter padding at + * [ButtonSize.Large]; at every smaller size they fall back to the standard button metrics. Corner + * radius is not part of this: every button is a pill, see [ButtonTokens.ContainerShape]. */ @Composable private fun ButtonSize.sizeIn(style: Style): Size = when { @@ -396,9 +393,6 @@ private sealed interface Size { @get:Composable val textStyle: TextStyle - @get:Composable - val shape: Shape - object Large : Size { override val contentPadding: PaddingValues = PaddingValues( top = LargeSizeButtonTokens.TopPadding, @@ -411,11 +405,6 @@ private sealed interface Size { @Composable @ReadOnlyComposable get() = LargeSizeButtonTokens.LabelTextFont.value - - override val shape: Shape - @Composable - @ReadOnlyComposable - get() = LargeSizeButtonTokens.ContainerShape.value } object LargeRounded : Size { @@ -430,11 +419,6 @@ private sealed interface Size { @Composable @ReadOnlyComposable get() = RoundedLargeSizeButtonTokens.LabelTextFont.value - - override val shape: Shape - @Composable - @ReadOnlyComposable - get() = RoundedLargeSizeButtonTokens.ContainerShape.value } object Medium : Size { @@ -449,11 +433,6 @@ private sealed interface Size { @Composable @ReadOnlyComposable get() = MediumSizeButtonTokens.LabelTextFont.value - - override val shape: Shape - @Composable - @ReadOnlyComposable - get() = MediumSizeButtonTokens.ContainerShape.value } object Small : Size { @@ -468,11 +447,6 @@ private sealed interface Size { @Composable @ReadOnlyComposable get() = SmallSizeButtonTokens.LabelTextFont.value - - override val shape: Shape - @Composable - @ReadOnlyComposable - get() = SmallSizeButtonTokens.ContainerShape.value } object Mini : Size { @@ -487,11 +461,6 @@ private sealed interface Size { @Composable @ReadOnlyComposable get() = MiniSizeButtonTokens.LabelTextFont.value - - override val shape: Shape - @Composable - @ReadOnlyComposable - get() = MiniSizeButtonTokens.ContainerShape.value } } diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/tokens/ButtonTokens.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/tokens/ButtonTokens.kt index bc6595345f..05c8be3329 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/tokens/ButtonTokens.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/tokens/ButtonTokens.kt @@ -2,6 +2,15 @@ package com.hedvig.android.design.system.hedvig.tokens import androidx.compose.ui.unit.dp +/** + * Every button is a pill at every size, so the corner radius is no longer a per-size or per-style + * choice and lives here instead of on the size tokens below. The radius tokens themselves stay in + * use by cards, sheets and the rest of the system. + */ +internal object ButtonTokens { + val ContainerShape = ShapeKeyTokens.CornerFull +} + internal object PrimaryStyleButtonTokens { val ContainerColor = ColorSchemeKeyTokens.ButtonPrimaryResting val ContentColor = ColorSchemeKeyTokens.TextNegative @@ -98,17 +107,15 @@ internal object LargeSizeButtonTokens { val HorizontalPadding = 32.dp val TopPadding = 15.dp val BottomPadding = 17.dp - val ContainerShape = ShapeKeyTokens.CornerLarge val LabelTextFont = TypographyKeyTokens.BodySmall } -// TODO: the rounded button styles are only designed at the large size. Every smaller size falls back to +// TODO: the glass button styles are only designed at the large size. Every smaller size falls back to // the standard button metrics above until design provides them. internal object RoundedLargeSizeButtonTokens { val HorizontalPadding = 20.dp val TopPadding = 12.dp val BottomPadding = 12.dp - val ContainerShape = ShapeKeyTokens.CornerFull val LabelTextFont = TypographyKeyTokens.BodySmall } @@ -116,7 +123,6 @@ internal object MediumSizeButtonTokens { val HorizontalPadding = 14.dp val TopPadding = 7.dp // todo look into if we use the right line heights to justify the offset introduced here val BottomPadding = 9.dp - val ContainerShape = ShapeKeyTokens.CornerMedium val LabelTextFont = TypographyKeyTokens.BodySmall } @@ -124,7 +130,6 @@ internal object SmallSizeButtonTokens { val HorizontalPadding = 12.dp val TopPadding = 6.5.dp val BottomPadding = 7.5.dp - val ContainerShape = ShapeKeyTokens.CornerSmall val LabelTextFont = TypographyKeyTokens.Label } @@ -132,6 +137,5 @@ internal object MiniSizeButtonTokens { val HorizontalPadding = 8.dp val TopPadding = 3.dp val BottomPadding = 3.dp - val ContainerShape = ShapeKeyTokens.CornerXSmall val LabelTextFont = TypographyKeyTokens.Label } diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt index 5f337228cc..70f13426ea 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt @@ -1334,7 +1334,6 @@ private fun QuoteCard( buttonStyle = Secondary, buttonSize = ButtonSize.Medium, enabled = true, - shape = HedvigTheme.shapes.cornerFull, modifier = Modifier.fillMaxWidth(), ) } @@ -1537,7 +1536,6 @@ private fun AddonsSection( imageLoader = imageLoader, modifier = Modifier.fillMaxWidth(), buttonSize = ButtonSize.Small, - buttonShape = HedvigTheme.shapes.cornerFull, ) } } @@ -1558,7 +1556,6 @@ private fun DiscoverInsurancesSection( imageLoader = imageLoader, buttonText = stringResource(string.HOME_DISCOVER_SEE_PRICE_BUTTON), buttonSize = ButtonSize.Small, - buttonShape = HedvigTheme.shapes.cornerFull, ) } diff --git a/app/ui/cross-sells/src/main/kotlin/com/hedvig/android/crosssells/CrossSells.kt b/app/ui/cross-sells/src/main/kotlin/com/hedvig/android/crosssells/CrossSells.kt index c569e7dc7c..975a6e8400 100644 --- a/app/ui/cross-sells/src/main/kotlin/com/hedvig/android/crosssells/CrossSells.kt +++ b/app/ui/cross-sells/src/main/kotlin/com/hedvig/android/crosssells/CrossSells.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.LocalLayoutDirection @@ -613,7 +612,6 @@ fun CrossSellsSection( title: String? = null, buttonText: String? = null, buttonSize: ButtonDefaults.ButtonSize = ButtonDefaults.ButtonSize.Medium, - buttonShape: Shape? = null, ) { Column(modifier) { if (withSubHeader) { @@ -632,7 +630,6 @@ fun CrossSellsSection( onSheetDismissed = onSheetDismissed, buttonText = crossSell.buttonText ?: buttonText, buttonSize = buttonSize, - buttonShape = buttonShape, ) } else { CrossSellItem( @@ -642,7 +639,6 @@ fun CrossSellsSection( imageLoader = imageLoader, buttonText = buttonText, buttonSize = buttonSize, - buttonShape = buttonShape, ) } if (index != crossSells.lastIndex) { @@ -690,7 +686,6 @@ private fun CrossSellItem( modifier: Modifier = Modifier, buttonText: String? = null, buttonSize: ButtonDefaults.ButtonSize = ButtonDefaults.ButtonSize.Medium, - buttonShape: Shape? = null, ) { CrossSellItem( crossSellTitle = crossSell.title, @@ -704,7 +699,6 @@ private fun CrossSellItem( onSheetDismissed = onSheetDismissed, buttonText = buttonText, buttonSize = buttonSize, - buttonShape = buttonShape, ) } @@ -721,7 +715,6 @@ private fun CrossSellItem( modifier: Modifier = Modifier, buttonText: String? = null, buttonSize: ButtonDefaults.ButtonSize = ButtonDefaults.ButtonSize.Medium, - buttonShape: Shape? = null, ) { PillowRow( title = crossSellTitle, @@ -737,7 +730,6 @@ private fun CrossSellItem( isLoading = isLoading, modifier = modifier, buttonSize = buttonSize, - buttonShape = buttonShape, ) } @@ -759,7 +751,6 @@ fun PillowRow( buttonStyle: ButtonDefaults.ButtonStyle = ButtonDefaults.ButtonStyle.Secondary, isLoading: Boolean = false, buttonSize: ButtonDefaults.ButtonSize = ButtonDefaults.ButtonSize.Medium, - buttonShape: Shape? = null, pillow: (@Composable () -> Unit)? = null, ) { val description = "$title $subtitle" @@ -823,7 +814,6 @@ fun PillowRow( onClickLabel = onButtonClickLabel, buttonSize = buttonSize, buttonStyle = buttonStyle, - shape = buttonShape, modifier = Modifier.hedvigPlaceholder( visible = isLoading, shape = HedvigTheme.shapes.cornerSmall, @@ -847,7 +837,6 @@ private fun CrossSellItemWithDiscounts( onSheetDismissed: () -> Unit, modifier: Modifier = Modifier, buttonSize: ButtonDefaults.ButtonSize = ButtonDefaults.ButtonSize.Medium, - buttonShape: Shape? = null, ) { val description = "$crossSellTitle $crossSellSubtitle" Row( @@ -908,7 +897,6 @@ private fun CrossSellItemWithDiscounts( onClickLabel = stringResource(Res.string.TALKBACK_OPEN_EXTERNAL_LINK), buttonSize = buttonSize, buttonStyle = ButtonDefaults.ButtonStyle.PrimaryAlt, - shape = buttonShape, modifier = Modifier.hedvigPlaceholder( visible = isLoading, shape = HedvigTheme.shapes.cornerSmall,