From 4bdd28f8de9850df69c541586c60cf5e114b7fb0 Mon Sep 17 00:00:00 2001 From: Jonatan Rhodin Date: Fri, 29 Sep 2023 17:04:17 +0200 Subject: [PATCH] Unify button appearance - Make almost all button depend on 3 standard buttons - Replace surface and onSurface with our own custom theme color - Set button standard height to material design default - Support bigger font sizes for buttons --- .../mullvadvpn/compose/button/ActionButton.kt | 51 ----- .../compose/button/ConnectionButton.kt | 149 ++++++++----- .../button/DeviceRevokedLoginButton.kt | 15 ++ .../compose/button/ExternalActionButton.kt | 71 +++--- .../compose/button/MullvadButton.kt | 207 ++++++++++++++++++ .../compose/button/RedeemVoucherButton.kt | 20 +- .../compose/button/SitePaymentButton.kt | 21 +- .../compose/button/SwitchLocationButton.kt | 38 +--- .../mullvadvpn/compose/cell/CustomPortCell.kt | 3 +- .../compose/cell/RelayLocationCell.kt | 3 +- .../mullvadvpn/compose/cell/SelectableCell.kt | 3 +- .../compose/dialog/ChangelogDialog.kt | 12 +- .../compose/dialog/CustomPortDialog.kt | 33 +-- .../compose/dialog/DeviceRemovalDialog.kt | 49 +---- .../mullvadvpn/compose/dialog/DnsDialog.kt | 101 ++++----- .../mullvadvpn/compose/dialog/InfoDialog.kt | 10 +- .../mullvadvpn/compose/dialog/MtuDialog.kt | 49 +---- .../compose/dialog/RedeemVoucherDialog.kt | 27 +-- .../dialog/ReportProblemNoEmailDialog.kt | 18 +- .../compose/screen/AccountScreen.kt | 28 +-- .../compose/screen/ConnectScreen.kt | 5 +- .../compose/screen/DeviceListScreen.kt | 24 +- .../compose/screen/DeviceRevokedScreen.kt | 22 +- .../mullvadvpn/compose/screen/LoginScreen.kt | 18 +- .../compose/screen/OutOfTimeScreen.kt | 10 +- .../compose/screen/PrivacyDisclaimerScreen.kt | 12 +- .../compose/screen/ReportProblemScreen.kt | 32 +-- .../mullvadvpn/lib/theme/color/Color.kt | 12 + .../lib/theme/dimensions/Dimensions.kt | 3 +- 29 files changed, 499 insertions(+), 547 deletions(-) delete mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ActionButton.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadButton.kt diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ActionButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ActionButton.kt deleted file mode 100644 index faf7052d4fa4..000000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ActionButton.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.mullvad.mullvadvpn.compose.button - -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonColors -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import net.mullvad.mullvadvpn.lib.theme.Dimens - -@Composable -fun ActionButton( - onClick: () -> Unit, - colors: ButtonColors, - modifier: Modifier = Modifier, - text: String = "", - isEnabled: Boolean = true, - content: @Composable RowScope.() -> Unit = { - Text( - text = text, - textAlign = TextAlign.Center, - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) - } -) { - Button( - onClick = onClick, - enabled = isEnabled, - // Required along with defaultMinSize to control size and padding. - contentPadding = PaddingValues(0.dp), - modifier = - modifier - .height(Dimens.buttonHeight) - .defaultMinSize(minWidth = 0.dp, minHeight = Dimens.buttonHeight) - .fillMaxWidth(), - colors = colors, - shape = MaterialTheme.shapes.small - ) { - content() - } -} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt index 23c17f107534..e80e17e444fd 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt @@ -1,33 +1,43 @@ package net.mullvad.mullvadvpn.compose.button -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CornerSize import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +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 androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisconnectButton +import net.mullvad.mullvadvpn.lib.theme.color.onVariant +import net.mullvad.mullvadvpn.lib.theme.color.variant import net.mullvad.mullvadvpn.model.TunnelState @Composable @@ -42,14 +52,14 @@ fun ConnectionButton( ) { val containerColor = if (state is TunnelState.Disconnected) { - MaterialTheme.colorScheme.surface + MaterialTheme.colorScheme.variant } else { MaterialTheme.colorScheme.error.copy(alpha = AlphaDisconnectButton) } val contentColor = if (state is TunnelState.Disconnected) { - MaterialTheme.colorScheme.onSurface + MaterialTheme.colorScheme.onVariant } else { MaterialTheme.colorScheme.onError } @@ -108,11 +118,12 @@ private fun PreviewConnectionButton() { containerColor = MaterialTheme.colorScheme.error.copy(alpha = AlphaDisconnectButton), contentColor = MaterialTheme.colorScheme.onError, reconnectClick = {}, - isReconnectButtonEnabled = false + isReconnectButtonEnabled = true ) } } +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ConnectionButton( text: String, @@ -122,62 +133,98 @@ private fun ConnectionButton( containerColor: Color, contentColor: Color, modifier: Modifier = Modifier, - height: Dp = Dimens.connectButtonHeight, reconnectButtonTestTag: String = "" ) { - Row(modifier = modifier.height(height)) { - Button( - onClick = mainClick, - shape = - MaterialTheme.shapes.small.copy( - topEnd = CornerSize(percent = 0), - bottomEnd = CornerSize(percent = 0) - ), - colors = - ButtonDefaults.buttonColors( - containerColor = containerColor, - contentColor = contentColor - ), - modifier = Modifier.weight(1f).height(height) - ) { - // Offset to compensate for the reconnect button. - val paddingOffset = - if (isReconnectButtonEnabled) { - height + Dimens.listItemDivider - } else { - 0.dp - } - Text( - text = text, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(start = paddingOffset) - ) - } + ConstraintLayout(modifier = modifier.fillMaxWidth()) { + // initial height set at 0.dp + var componentHeight by remember { mutableStateOf(0.dp) } - if (isReconnectButtonEnabled) { - Spacer(modifier = Modifier.width(Dimens.listItemDivider)) + // get local density from composable + val density = LocalDensity.current - FilledIconButton( + val (connectionButton, reconnectButton) = createRefs() + CompositionLocalProvider( + LocalMinimumInteractiveComponentEnforcement provides false, + ) { + val dividerSize = Dimens.listItemDivider + + Button( + onClick = mainClick, shape = - MaterialTheme.shapes.small.copy( - topStart = CornerSize(percent = 0), - bottomStart = CornerSize(percent = 0) - ), + if (isReconnectButtonEnabled) { + MaterialTheme.shapes.small.copy( + topEnd = CornerSize(percent = 0), + bottomEnd = CornerSize(percent = 0) + ) + } else { + MaterialTheme.shapes.small + }, colors = - IconButtonDefaults.filledIconButtonColors( + ButtonDefaults.buttonColors( containerColor = containerColor, contentColor = contentColor ), - onClick = reconnectClick, modifier = - Modifier.height(height).aspectRatio(1f, true).testTag(reconnectButtonTestTag) + Modifier.constrainAs(connectionButton) { + start.linkTo(parent.start) + if (isReconnectButtonEnabled) { + end.linkTo(reconnectButton.start) + } else { + end.linkTo(parent.end) + } + width = Dimension.fillToConstraints + height = Dimension.wrapContent + } + .onGloballyPositioned { + componentHeight = with(density) { it.size.height.toDp() } + } ) { - Icon( - painter = painterResource(id = R.drawable.icon_reload), - contentDescription = null + // Offset to compensate for the reconnect button. + Text( + text = text, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = + if (isReconnectButtonEnabled) { + Modifier.padding(start = componentHeight + Dimens.listItemDivider) + } else { + Modifier + } ) } + + if (isReconnectButtonEnabled) { + FilledIconButton( + shape = + MaterialTheme.shapes.small.copy( + topStart = CornerSize(percent = 0), + bottomStart = CornerSize(percent = 0) + ), + colors = + IconButtonDefaults.filledIconButtonColors( + containerColor = containerColor, + contentColor = contentColor + ), + onClick = reconnectClick, + modifier = + Modifier.testTag(reconnectButtonTestTag) + .constrainAs(reconnectButton) { + start.linkTo(connectionButton.end, margin = dividerSize) + top.linkTo(connectionButton.top) + bottom.linkTo(connectionButton.bottom) + end.linkTo(parent.end) + height = Dimension.fillToConstraints + } + .aspectRatio(1f, true) + ) { + Icon( + painter = painterResource(id = R.drawable.icon_reload), + contentDescription = null + ) + } + } } } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt new file mode 100644 index 000000000000..7ba80f09d8a4 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt @@ -0,0 +1,15 @@ +package net.mullvad.mullvadvpn.compose.button + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState + +@Composable +fun DeviceRevokedLoginButton(onClick: () -> Unit, state: DeviceRevokedUiState) { + if (state == DeviceRevokedUiState.SECURED) { + NegativeButton(text = stringResource(id = R.string.go_to_login), onClick = onClick) + } else { + VariantButton(text = stringResource(id = R.string.go_to_login), onClick = onClick) + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt index 8abe8790828e..376172e63208 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt @@ -1,70 +1,51 @@ package net.mullvad.mullvadvpn.compose.button -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ButtonColors -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.constraintlayout.compose.ConstraintLayout import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.lib.theme.AppTheme -import net.mullvad.mullvadvpn.lib.theme.Dimens -import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled -import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible @Preview @Composable -private fun PreviewExternalActionButton() { +private fun PreviewExternalButtonEnabled() { + AppTheme { ExternalButton(onClick = {}, text = "Button", isEnabled = true) } +} + +@Preview +@Composable +private fun PreviewExternalButtonDisabled() { + AppTheme { ExternalButton(onClick = {}, text = "Button", isEnabled = false) } +} + +@Preview +@Composable +private fun PreviewExternalButtonLongText() { AppTheme { - ExternalActionButton(onClick = {}, colors = ButtonDefaults.buttonColors(), text = "Button") + ExternalButton( + onClick = {}, + text = "Button text is long and is trying to take up space that is large", + isEnabled = true + ) } } @Composable -fun ExternalActionButton( +fun ExternalButton( onClick: () -> Unit, - colors: ButtonColors, text: String, modifier: Modifier = Modifier, isEnabled: Boolean = true, ) { - ActionButton( + VariantButton( + text = text, onClick = onClick, - colors = colors, modifier = modifier, isEnabled = isEnabled, - ) { - ConstraintLayout(modifier = Modifier.fillMaxSize()) { - val (title, logo) = createRefs() - Text( - text = text, - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodyMedium, - modifier = - Modifier.constrainAs(title) { - end.linkTo(logo.start) - centerTo(parent) - } - ) - Image( - painter = painterResource(id = R.drawable.icon_extlink), - contentDescription = null, - modifier = - Modifier.constrainAs(logo) { - centerVerticallyTo(parent) - end.linkTo(parent.end) - } - .padding(horizontal = Dimens.smallPadding) - .alpha(if (isEnabled) AlphaVisible else AlphaDisabled) - ) - } - } + icon = { + Icon(painter = painterResource(id = R.drawable.icon_extlink), contentDescription = null) + }, + ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadButton.kt new file mode 100644 index 000000000000..3dd7068389f3 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadButton.kt @@ -0,0 +1,207 @@ +package net.mullvad.mullvadvpn.compose.button + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.compositeOver +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import net.mullvad.mullvadvpn.lib.theme.AppTheme +import net.mullvad.mullvadvpn.lib.theme.Dimens +import net.mullvad.mullvadvpn.lib.theme.color.Alpha20 +import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled +import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive +import net.mullvad.mullvadvpn.lib.theme.color.AlphaInvisible +import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.theme.color.onVariant +import net.mullvad.mullvadvpn.lib.theme.color.variant + +@Preview +@Composable +private fun PreviewNegativeButtonEnabled() { + AppTheme { NegativeButton(onClick = {}, text = "Negative Button") } +} + +@Preview +@Composable +private fun PreviewNegativeButtonDisabled() { + AppTheme { NegativeButton(onClick = {}, text = "Negative Button", isEnabled = false) } +} + +@Preview +@Composable +private fun PreviewVariantButtonEnabled() { + AppTheme { VariantButton(onClick = {}, text = "Variant Button") } +} + +@Preview +@Composable +private fun PreviewVariantButtonDisabled() { + AppTheme { VariantButton(onClick = {}, text = "Variant Button", isEnabled = false) } +} + +@Preview +@Composable +private fun PreviewPrimaryButtonEnabled() { + AppTheme { PrimaryButton(onClick = {}, text = "Primary Button") } +} + +@Preview +@Composable +private fun PreviewPrimaryButtonDisabled() { + AppTheme { PrimaryButton(onClick = {}, text = "Primary Button", isEnabled = false) } +} + +@Composable +fun NegativeButton( + onClick: () -> Unit, + text: String, + modifier: Modifier = Modifier, + colors: ButtonColors = + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.error, + contentColor = MaterialTheme.colorScheme.onError, + disabledContentColor = + MaterialTheme.colorScheme.onError + .copy(alpha = AlphaInactive) + .compositeOver(MaterialTheme.colorScheme.background), + disabledContainerColor = + MaterialTheme.colorScheme.error + .copy(alpha = AlphaInactive) + .compositeOver(MaterialTheme.colorScheme.background), + ), + isEnabled: Boolean = true, + icon: @Composable (() -> Unit)? = null +) { + BaseButton( + onClick = onClick, + colors = colors, + text = text, + modifier = modifier, + isEnabled = isEnabled, + icon = icon + ) +} + +@Composable +fun VariantButton( + onClick: () -> Unit, + text: String, + modifier: Modifier = Modifier, + background: Color = MaterialTheme.colorScheme.background, + colors: ButtonColors = + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.variant, + contentColor = MaterialTheme.colorScheme.onVariant, + disabledContentColor = + MaterialTheme.colorScheme.onVariant + .copy(alpha = AlphaInactive) + .compositeOver(background), + disabledContainerColor = + MaterialTheme.colorScheme.variant + .copy(alpha = AlphaInactive) + .compositeOver(background), + ), + isEnabled: Boolean = true, + icon: @Composable (() -> Unit)? = null +) { + BaseButton( + onClick = onClick, + colors = colors, + text = text, + modifier = modifier, + isEnabled = isEnabled, + icon = icon + ) +} + +@Composable +fun PrimaryButton( + onClick: () -> Unit, + text: String, + modifier: Modifier = Modifier, + colors: ButtonColors = + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + disabledContentColor = + MaterialTheme.colorScheme.onPrimary + .copy(alpha = Alpha20) + .compositeOver(MaterialTheme.colorScheme.background), + disabledContainerColor = + MaterialTheme.colorScheme.primary + .copy(alpha = AlphaInactive) + .compositeOver(MaterialTheme.colorScheme.background), + ), + isEnabled: Boolean = true, + icon: @Composable (() -> Unit)? = null +) { + BaseButton( + onClick = onClick, + colors = colors, + text = text, + modifier = modifier, + isEnabled = isEnabled, + icon = icon, + ) +} + +@Composable +private fun BaseButton( + onClick: () -> Unit, + colors: ButtonColors, + text: String, + modifier: Modifier = Modifier, + isEnabled: Boolean = true, + icon: @Composable (() -> Unit)? = null +) { + Button( + onClick = onClick, + colors = colors, + enabled = isEnabled, + contentPadding = + icon?.let { PaddingValues(horizontal = 0.dp, vertical = Dimens.buttonVerticalPadding) } + ?: ButtonDefaults.ContentPadding, + modifier = modifier.wrapContentHeight().fillMaxWidth(), + shape = MaterialTheme.shapes.small + ) { + // Used to center the text + icon?.let { + Box( + modifier = Modifier.padding(horizontal = Dimens.smallPadding).alpha(AlphaInvisible) + ) { + icon() + } + } + Text( + text = text, + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f) + ) + icon?.let { + Box( + modifier = + Modifier.padding(horizontal = Dimens.smallPadding) + .alpha(if (isEnabled) AlphaVisible else AlphaDisabled) + ) { + icon() + } + } + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/RedeemVoucherButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/RedeemVoucherButton.kt index c95c1bf82d5d..57532a8d429a 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/RedeemVoucherButton.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/RedeemVoucherButton.kt @@ -1,18 +1,14 @@ package net.mullvad.mullvadvpn.compose.button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.compose.component.SpacedColumn import net.mullvad.mullvadvpn.lib.theme.AppTheme -import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive @Preview @Composable @@ -32,23 +28,11 @@ fun RedeemVoucherButton( onClick: () -> Unit, isEnabled: Boolean ) { - ActionButton( + VariantButton( + background = background, text = stringResource(id = R.string.redeem_voucher), onClick = onClick, modifier = modifier, - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.surface, - disabledContentColor = - MaterialTheme.colorScheme.onPrimary - .copy(alpha = AlphaInactive) - .compositeOver(background), - disabledContainerColor = - MaterialTheme.colorScheme.surface - .copy(alpha = AlphaDisabled) - .compositeOver(background) - ), isEnabled = isEnabled ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SitePaymentButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SitePaymentButton.kt index 59292a9aa61e..93b5c7712595 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SitePaymentButton.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SitePaymentButton.kt @@ -1,20 +1,15 @@ package net.mullvad.mullvadvpn.compose.button import androidx.compose.foundation.background -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.compose.component.SpacedColumn import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens -import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive @Preview @Composable @@ -35,24 +30,10 @@ fun SitePaymentButton( onClick: () -> Unit, isEnabled: Boolean, modifier: Modifier = Modifier, - background: Color = MaterialTheme.colorScheme.background, ) { - ExternalActionButton( + ExternalButton( onClick = onClick, modifier = modifier, - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.surface, - disabledContentColor = - MaterialTheme.colorScheme.onPrimary - .copy(alpha = AlphaInactive) - .compositeOver(background), - disabledContainerColor = - MaterialTheme.colorScheme.surface - .copy(alpha = AlphaDisabled) - .compositeOver(background) - ), isEnabled = isEnabled, text = stringResource(id = R.string.buy_credit) ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt index c76166d54833..2feabcfaf3fe 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt @@ -1,23 +1,15 @@ package net.mullvad.mullvadvpn.compose.button -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -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.painterResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.compose.component.SpacedColumn import net.mullvad.mullvadvpn.lib.theme.AppTheme -import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.Alpha20 @Preview @@ -38,29 +30,23 @@ fun SwitchLocationButton( showChevron: Boolean, onClick: () -> Unit, ) { - ActionButton( + PrimaryButton( onClick = onClick, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.inverseSurface.copy(alpha = Alpha20), contentColor = MaterialTheme.colorScheme.inverseSurface ), - modifier = modifier - ) { - Box(modifier = Modifier.fillMaxWidth().fillMaxHeight().padding(all = Dimens.smallPadding)) { - Text( - text = text, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold, - modifier = Modifier.align(Alignment.Center) - ) + modifier = modifier, + text = text, + icon = if (showChevron) { - Icon( - painter = painterResource(id = R.drawable.icon_chevron), - contentDescription = null, - modifier = Modifier.align(Alignment.CenterEnd) - ) - } - } - } + { + Icon( + painter = painterResource(id = R.drawable.icon_chevron), + contentDescription = null + ) + } + } else null + ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomPortCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomPortCell.kt index 9e2d002f8490..8219aa998431 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomPortCell.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomPortCell.kt @@ -30,6 +30,7 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.AlphaInvisible import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.theme.color.selected @Preview @Composable @@ -66,7 +67,7 @@ fun CustomPortCell( .weight(1f) .background( if (isSelected) { - MaterialTheme.colorScheme.surface + MaterialTheme.colorScheme.selected } else { MaterialTheme.colorScheme.secondaryContainer } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt index faa65de250cb..75888a857982 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt @@ -35,6 +35,7 @@ import net.mullvad.mullvadvpn.lib.theme.color.Alpha40 import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive import net.mullvad.mullvadvpn.lib.theme.color.AlphaInvisible import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.theme.color.selected import net.mullvad.mullvadvpn.model.GeographicLocationConstraint import net.mullvad.mullvadvpn.relaylist.Relay import net.mullvad.mullvadvpn.relaylist.RelayCity @@ -150,7 +151,7 @@ private fun PreviewRelayLocationCell() { fun RelayLocationCell( relay: RelayItem, modifier: Modifier = Modifier, - activeColor: Color = MaterialTheme.colorScheme.surface, + activeColor: Color = MaterialTheme.colorScheme.selected, inactiveColor: Color = MaterialTheme.colorScheme.error, selectedItem: RelayItem? = null, onSelectRelay: (item: RelayItem) -> Unit = {} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt index b22ff378ec81..087ba3daf451 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt @@ -18,6 +18,7 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.AlphaInvisible import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.theme.color.selected @Preview @Composable @@ -47,7 +48,7 @@ fun SelectableCell( }, titleStyle: TextStyle = MaterialTheme.typography.labelLarge, startPadding: Dp = Dimens.cellStartPadding, - selectedColor: Color = MaterialTheme.colorScheme.surface, + selectedColor: Color = MaterialTheme.colorScheme.selected, backgroundColor: Color = MaterialTheme.colorScheme.secondaryContainer, onCellClicked: () -> Unit = {}, testTag: String = "" diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ChangelogDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ChangelogDialog.kt index 083aedd217f0..52f11babe71c 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ChangelogDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ChangelogDialog.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -18,7 +17,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens @@ -51,14 +50,9 @@ fun ChangelogDialog(changesList: List, version: String, onDismiss: () -> } }, confirmButton = { - ActionButton( + PrimaryButton( text = stringResource(R.string.changes_dialog_dismiss_button), - onClick = onDismiss, - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ) + onClick = onDismiss ) }, containerColor = MaterialTheme.colorScheme.background, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialog.kt index 32e8df77a7ed..a5d886de2e7b 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialog.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -16,14 +15,13 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.NegativeButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.compose.test.CUSTOM_PORT_DIALOG_INPUT_TEST_TAG import net.mullvad.mullvadvpn.compose.textfield.CustomPortTextField import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.AlphaDescription -import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive import net.mullvad.mullvadvpn.model.PortRange import net.mullvad.mullvadvpn.util.asString import net.mullvad.mullvadvpn.util.isPortInValidRanges @@ -63,40 +61,21 @@ fun CustomPortDialog( }, confirmButton = { Column { - ActionButton( + PrimaryButton( text = stringResource(id = R.string.custom_port_dialog_submit), onClick = { onSave(port.value) }, - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - disabledContentColor = - MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaInactive), - disabledContainerColor = - MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaDisabled) - ), isEnabled = port.value.isNotEmpty() && allowedPortRanges.isPortInValidRanges(port.value.toIntOrNull() ?: 0) ) if (showReset) { - ActionButton( + NegativeButton( text = stringResource(R.string.custom_port_dialog_remove), - onClick = { onReset() }, + onClick = onReset, modifier = Modifier.padding(top = Dimens.mediumPadding), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError, - ) ) } - ActionButton( - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), + PrimaryButton( text = stringResource(id = R.string.cancel), modifier = Modifier.padding(top = Dimens.mediumPadding), onClick = onDismissRequest diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceRemovalDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceRemovalDialog.kt index 1ac8873fc3d3..e08a82d69491 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceRemovalDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceRemovalDialog.kt @@ -2,17 +2,12 @@ package net.mullvad.mullvadvpn.compose.dialog import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -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.width import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -24,9 +19,10 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.button.NegativeButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.compose.component.HtmlText import net.mullvad.mullvadvpn.compose.component.textResource -import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.model.Device @Preview @@ -42,7 +38,7 @@ private fun PreviewShowDeviceRemovalDialog() { @Composable fun ShowDeviceRemovalDialog(onDismiss: () -> Unit, onConfirm: () -> Unit, device: Device) { AlertDialog( - onDismissRequest = { onDismiss() }, + onDismissRequest = onDismiss, title = { Column( horizontalAlignment = Alignment.CenterHorizontally, @@ -62,40 +58,17 @@ fun ShowDeviceRemovalDialog(onDismiss: () -> Unit, onConfirm: () -> Unit, device HtmlText(htmlFormattedString = htmlFormattedDialogText, textSize = 16.sp.value) }, dismissButton = { - Button( - modifier = - Modifier.height(Dimens.buttonHeight) - .defaultMinSize(minWidth = 0.dp, minHeight = Dimens.buttonHeight) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError - ), + NegativeButton( onClick = onConfirm, - shape = MaterialTheme.shapes.small - ) { - Text(text = stringResource(id = R.string.confirm_removal), fontSize = 18.sp) - } + text = stringResource(id = R.string.confirm_removal) + ) }, confirmButton = { - Button( - contentPadding = PaddingValues(0.dp), - modifier = - Modifier.focusRequester(FocusRequester()) - .height(Dimens.buttonHeight) - .defaultMinSize(minWidth = 0.dp, minHeight = Dimens.buttonHeight) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary - ), - onClick = { onDismiss() }, - shape = MaterialTheme.shapes.small - ) { - Text(text = stringResource(id = R.string.back), fontSize = 18.sp) - } + PrimaryButton( + modifier = Modifier.focusRequester(FocusRequester()), + onClick = onDismiss, + text = stringResource(id = R.string.back) + ) }, containerColor = MaterialTheme.colorScheme.background ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt index cce0bb7356b8..4312b239af85 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt @@ -4,12 +4,9 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -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.wrapContentSize -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -24,21 +21,17 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.compose.textfield.DnsTextField import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens -import net.mullvad.mullvadvpn.lib.theme.color.MullvadBlue import net.mullvad.mullvadvpn.lib.theme.color.MullvadRed -import net.mullvad.mullvadvpn.lib.theme.color.MullvadWhite -import net.mullvad.mullvadvpn.lib.theme.color.MullvadWhite20 -import net.mullvad.mullvadvpn.lib.theme.color.MullvadWhite60 import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem import net.mullvad.mullvadvpn.viewmodel.StagedDns @Preview @Composable -private fun PreviewDnsDialog() { +private fun PreviewDnsDialogNew() { AppTheme { DnsDialog( stagedDns = @@ -52,6 +45,46 @@ private fun PreviewDnsDialog() { } } +@Preview +@Composable +private fun PreviewDnsDialogEdit() { + AppTheme { + DnsDialog( + stagedDns = + StagedDns.EditDns( + CustomDnsItem("1.1.1.1", false), + StagedDns.ValidationResult.Success, + 0 + ), + isAllowLanEnabled = true, + onIpAddressChanged = {}, + onAttemptToSave = {}, + onRemove = {}, + onDismiss = {} + ) + } +} + +@Preview +@Composable +private fun PreviewDnsDialogEditAllowLanDisabled() { + AppTheme { + DnsDialog( + stagedDns = + StagedDns.EditDns( + CustomDnsItem(address = "1.1.1.1", isLocal = true), + StagedDns.ValidationResult.Success, + 0 + ), + isAllowLanEnabled = false, + onIpAddressChanged = {}, + onAttemptToSave = {}, + onRemove = {}, + onDismiss = {} + ) + } +} + @Composable fun DnsDialog( stagedDns: StagedDns, @@ -61,7 +94,6 @@ fun DnsDialog( onRemove: () -> Unit, onDismiss: () -> Unit ) { - val buttonSize = Dimens.buttonHeight val mediumPadding = Dimens.mediumPadding val dialogPadding = 20.dp val midPadding = 10.dp @@ -72,7 +104,7 @@ fun DnsDialog( Dialog( // Fix for https://issuetracker.google.com/issues/221643630 properties = DialogProperties(usePlatformDefaultWidth = false), - onDismissRequest = { onDismiss() }, + onDismissRequest = onDismiss, content = { Column( Modifier @@ -136,53 +168,24 @@ fun DnsDialog( ) } - ActionButton( - modifier = - Modifier.padding(top = mediumPadding) - .height(buttonSize) - .defaultMinSize(minHeight = buttonSize) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MullvadBlue, - contentColor = MullvadWhite, - disabledContentColor = MullvadWhite60, - disabledContainerColor = MullvadWhite20 - ), - onClick = { onAttemptToSave() }, + PrimaryButton( + modifier = Modifier.padding(top = mediumPadding), + onClick = onAttemptToSave, isEnabled = stagedDns.isValid(), text = stringResource(id = R.string.submit_button), ) if (stagedDns is StagedDns.EditDns) { - ActionButton( - modifier = - Modifier.padding(top = mediumPadding) - .height(buttonSize) - .defaultMinSize(minHeight = buttonSize) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MullvadBlue, - contentColor = MullvadWhite - ), - onClick = { onRemove() }, + PrimaryButton( + modifier = Modifier.padding(top = mediumPadding), + onClick = onRemove, text = stringResource(id = R.string.remove_button) ) } - ActionButton( - modifier = - Modifier.padding(top = mediumPadding) - .height(buttonSize) - .defaultMinSize(minHeight = buttonSize) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MullvadBlue, - contentColor = Color.White - ), - onClick = { onDismiss() }, + PrimaryButton( + modifier = Modifier.padding(top = mediumPadding), + onClick = onDismiss, text = stringResource(id = R.string.cancel) ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt index 48599da15a00..e57e9be563c5 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -19,7 +18,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.window.DialogProperties import androidx.core.text.HtmlCompat import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.compose.extensions.toAnnotatedString import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens @@ -76,14 +75,9 @@ fun InfoDialog(message: String, additionalInfo: String? = null, onDismiss: () -> } }, confirmButton = { - ActionButton( + PrimaryButton( modifier = Modifier.wrapContentHeight().fillMaxWidth(), text = stringResource(R.string.changes_dialog_dismiss_button), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), onClick = onDismiss, ) }, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt index beca8a9f434e..82773f079df3 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt @@ -4,12 +4,9 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -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.wrapContentSize -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -24,15 +21,13 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.compose.textfield.MtuTextField import net.mullvad.mullvadvpn.constant.MTU_MAX_VALUE import net.mullvad.mullvadvpn.constant.MTU_MIN_VALUE import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.AlphaDescription -import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive import net.mullvad.mullvadvpn.util.isValidMtu @Preview @@ -115,20 +110,8 @@ fun MtuDialog( modifier = Modifier.padding(top = smallPadding) ) - ActionButton( - modifier = - Modifier.padding(top = Dimens.mediumPadding) - .height(Dimens.buttonHeight) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - disabledContentColor = - MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaInactive), - disabledContainerColor = - MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaDisabled) - ), + PrimaryButton( + modifier = Modifier.padding(top = Dimens.mediumPadding).fillMaxWidth(), isEnabled = isValidMtu, text = stringResource(R.string.submit_button), onClick = { @@ -139,32 +122,14 @@ fun MtuDialog( } ) - ActionButton( - modifier = - Modifier.padding(top = Dimens.mediumPadding) - .height(Dimens.buttonHeight) - .defaultMinSize(minHeight = Dimens.buttonHeight) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), + PrimaryButton( + modifier = Modifier.padding(top = Dimens.mediumPadding).fillMaxWidth(), text = stringResource(R.string.reset_to_default_button), onClick = onRestoreDefaultValue ) - ActionButton( - modifier = - Modifier.padding(top = Dimens.mediumPadding) - .height(Dimens.buttonHeight) - .defaultMinSize(minHeight = Dimens.buttonHeight) - .fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), + PrimaryButton( + modifier = Modifier.padding(top = Dimens.mediumPadding).fillMaxWidth(), text = stringResource(R.string.cancel), onClick = onDismiss ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt index 3753b4d2e6aa..0848b895945d 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -30,7 +29,8 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton +import net.mullvad.mullvadvpn.compose.button.VariantButton import net.mullvad.mullvadvpn.compose.state.VoucherDialogState import net.mullvad.mullvadvpn.compose.state.VoucherDialogUiState import net.mullvad.mullvadvpn.compose.textfield.GroupedTextField @@ -40,7 +40,6 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.lib.theme.color.AlphaDescription import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive import org.joda.time.DateTimeConstants @Preview(device = Devices.TV_720p) @@ -113,32 +112,14 @@ fun RedeemVoucherDialog( confirmButton = { Column { if (uiState.voucherViewModelState !is VoucherDialogState.Success) { - ActionButton( + VariantButton( text = stringResource(id = R.string.redeem), onClick = { onRedeem(uiState.voucherInput) }, modifier = Modifier.padding(bottom = Dimens.mediumPadding), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.surface, - contentColor = MaterialTheme.colorScheme.onSurface, - disabledContentColor = - MaterialTheme.colorScheme.onSurface - .copy(alpha = AlphaInactive) - .compositeOver(MaterialTheme.colorScheme.surface), - disabledContainerColor = - MaterialTheme.colorScheme.surface - .copy(alpha = AlphaDisabled) - .compositeOver(MaterialTheme.colorScheme.surface) - ), isEnabled = uiState.voucherInput.length == VOUCHER_LENGTH ) } - ActionButton( - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), + PrimaryButton( text = stringResource( id = diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ReportProblemNoEmailDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ReportProblemNoEmailDialog.kt index 7417d6ae7c21..8415acbf4bb5 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ReportProblemNoEmailDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ReportProblemNoEmailDialog.kt @@ -3,7 +3,6 @@ package net.mullvad.mullvadvpn.compose.dialog import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -14,7 +13,8 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.NegativeButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens @@ -49,25 +49,15 @@ fun ReportProblemNoEmailDialog(onDismiss: () -> Unit, onConfirm: () -> Unit) { ) }, dismissButton = { - ActionButton( + NegativeButton( modifier = Modifier.fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError, - ), onClick = onConfirm, text = stringResource(id = R.string.send_anyway) ) }, confirmButton = { - ActionButton( + PrimaryButton( modifier = Modifier.fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), onClick = { onDismiss() }, text = stringResource(id = R.string.back) ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt index 71f79e55b5e4..a8726fd0bbb0 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -29,7 +28,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.ExternalButton +import net.mullvad.mullvadvpn.compose.button.NegativeButton +import net.mullvad.mullvadvpn.compose.button.RedeemVoucherButton import net.mullvad.mullvadvpn.compose.component.CopyableObfuscationView import net.mullvad.mullvadvpn.compose.component.InformationView import net.mullvad.mullvadvpn.compose.component.MissingPolicy @@ -150,7 +151,7 @@ fun AccountScreen( Spacer(modifier = Modifier.weight(1f)) if (IS_PLAY_BUILD.not()) { - ActionButton( + ExternalButton( text = stringResource(id = R.string.manage_account), onClick = onManageAccountClick, modifier = @@ -158,17 +159,11 @@ fun AccountScreen( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.screenVerticalMargin - ), - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.surface ) ) } - ActionButton( - text = stringResource(id = R.string.redeem_voucher), + RedeemVoucherButton( onClick = onRedeemVoucherClick, modifier = Modifier.padding( @@ -176,14 +171,10 @@ fun AccountScreen( end = Dimens.sideMargin, bottom = Dimens.screenVerticalMargin ), - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.surface - ) + isEnabled = true ) - ActionButton( + NegativeButton( text = stringResource(id = R.string.log_out), onClick = onLogoutClick, modifier = @@ -191,11 +182,6 @@ fun AccountScreen( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.screenVerticalMargin - ), - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.error ) ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt index 2c2e9d7abc14..806c7c93fa0b 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt @@ -212,7 +212,6 @@ fun ConnectScreen( SwitchLocationButton( modifier = Modifier.fillMaxWidth() - .height(Dimens.selectLocationButtonHeight) .padding(horizontal = Dimens.sideMargin) .testTag(SELECT_LOCATION_BUTTON_TEST_TAG), onClick = onSwitchLocationClick, @@ -228,9 +227,7 @@ fun ConnectScreen( ConnectionButton( state = uiState.tunnelUiState, modifier = - Modifier.fillMaxWidth() - .height(Dimens.connectButtonHeight) - .padding(horizontal = Dimens.sideMargin) + Modifier.padding(horizontal = Dimens.sideMargin) .testTag(CONNECT_BUTTON_TEST_TAG), disconnectClick = onDisconnectClick, reconnectClick = { handleThrottledAction(onReconnectClick) }, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt index 5230575600ac..42ab9faef08a 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -24,7 +23,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton +import net.mullvad.mullvadvpn.compose.button.VariantButton import net.mullvad.mullvadvpn.compose.component.ListItem import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar import net.mullvad.mullvadvpn.compose.dialog.ShowDeviceRemovalDialog @@ -33,7 +33,6 @@ import net.mullvad.mullvadvpn.compose.state.DeviceListUiState import net.mullvad.mullvadvpn.lib.common.util.parseAsDateTime import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive import net.mullvad.mullvadvpn.lib.theme.color.AlphaTopBar import net.mullvad.mullvadvpn.model.Device import net.mullvad.mullvadvpn.util.formatDate @@ -229,29 +228,16 @@ fun DeviceListScreen( bottom = Dimens.screenVerticalMargin ) ) { - ActionButton( + VariantButton( text = stringResource(id = R.string.continue_login), onClick = onContinueWithLogin, isEnabled = state.hasTooManyDevices.not() && state.isLoading.not(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.inversePrimary, - contentColor = MaterialTheme.colorScheme.onPrimary, - disabledContentColor = - MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaInactive), - disabledContainerColor = - MaterialTheme.colorScheme.inversePrimary.copy(alpha = AlphaInactive) - ) + background = MaterialTheme.colorScheme.secondary ) - ActionButton( + PrimaryButton( text = stringResource(id = R.string.back), onClick = onBackClick, - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), modifier = Modifier.padding(top = Dimens.mediumPadding) ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt index f7a15c2feae0..102911ae365a 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt @@ -8,13 +8,11 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -24,11 +22,10 @@ import androidx.compose.ui.unit.sp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.DeviceRevokedLoginButton import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState import net.mullvad.mullvadvpn.lib.theme.AppTheme -import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisconnectButton @Preview @Composable @@ -121,22 +118,7 @@ fun DeviceRevokedScreen( width = Dimension.fillToConstraints } ) { - ActionButton( - text = stringResource(id = R.string.go_to_login), - onClick = onGoToLoginClicked, - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = - if (state == DeviceRevokedUiState.SECURED) { - MaterialTheme.colorScheme.error - .copy(alpha = AlphaDisconnectButton) - .compositeOver(MaterialTheme.colorScheme.background) - } else { - MaterialTheme.colorScheme.primary - } - ) - ) + DeviceRevokedLoginButton(onClick = onGoToLoginClicked, state = state) } } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt index bdce1c1660ab..d1c64b6c5a15 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -54,7 +53,8 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton +import net.mullvad.mullvadvpn.compose.button.VariantButton import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar import net.mullvad.mullvadvpn.compose.state.LoginError import net.mullvad.mullvadvpn.compose.state.LoginState @@ -227,14 +227,9 @@ private fun LoginContent( } Spacer(modifier = Modifier.size(Dimens.largePadding)) - ActionButton( + VariantButton( isEnabled = uiState.loginButtonEnabled, onClick = { onLoginClick(uiState.accountNumberInput) }, - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.surface - ), text = stringResource(id = R.string.login_title), modifier = Modifier.padding(bottom = Dimens.mediumPadding) ) @@ -361,15 +356,10 @@ private fun CreateAccountPanel(onCreateAccountClick: () -> Unit, isEnabled: Bool text = stringResource(id = R.string.dont_have_an_account), color = MaterialTheme.colorScheme.onPrimary, ) - ActionButton( + PrimaryButton( modifier = Modifier.fillMaxWidth(), text = stringResource(id = R.string.create_account), isEnabled = isEnabled, - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.primary - ), onClick = onCreateAccountClick ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt index a7d220c4e445..a772a45750fd 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -24,7 +23,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.NegativeButton import net.mullvad.mullvadvpn.compose.button.RedeemVoucherButton import net.mullvad.mullvadvpn.compose.button.SitePaymentButton import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBarAndDeviceName @@ -179,13 +178,8 @@ fun OutOfTimeScreen( Spacer(modifier = Modifier.weight(1f).defaultMinSize(minHeight = Dimens.verticalSpace)) // Button area if (uiState.tunnelState.showDisconnectButton()) { - ActionButton( + NegativeButton( onClick = onDisconnectClick, - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError - ), text = stringResource(id = R.string.disconnect), modifier = Modifier.padding( diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt index 4fd2b2719e48..f78b54f9897f 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.ClickableText -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -29,7 +28,7 @@ import androidx.compose.ui.unit.sp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens @@ -119,14 +118,9 @@ fun PrivacyDisclaimerScreen( width = Dimension.fillToConstraints } ) { - ActionButton( + PrimaryButton( text = stringResource(id = R.string.agree_and_continue), - onClick = onAcceptClicked::invoke, - colors = - ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onPrimary, - containerColor = MaterialTheme.colorScheme.primary - ) + onClick = onAcceptClicked::invoke ) } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt index 6dc34937d512..f5346fbc7d35 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt @@ -9,7 +9,6 @@ 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.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -33,7 +32,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.button.ActionButton +import net.mullvad.mullvadvpn.compose.button.PrimaryButton +import net.mullvad.mullvadvpn.compose.button.VariantButton import net.mullvad.mullvadvpn.compose.component.NavigateBackIconButton import net.mullvad.mullvadvpn.compose.component.ScaffoldWithMediumTopBar import net.mullvad.mullvadvpn.compose.dialog.ReportProblemNoEmailDialog @@ -163,22 +163,12 @@ fun ReportProblemScreen( colors = mullvadWhiteTextFieldColors() ) - ActionButton( - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary - ), + PrimaryButton( onClick = onNavigateToViewLogs, text = stringResource(id = R.string.view_logs) ) - ActionButton( - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.surface, - contentColor = MaterialTheme.colorScheme.onSurface - ), + VariantButton( onClick = { onSendReport(email, description) }, isEnabled = description.isNotEmpty(), text = stringResource(id = R.string.send) @@ -277,23 +267,13 @@ private fun ColumnScope.ErrorContent(retry: () -> Unit, onDismiss: () -> Unit) { modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.weight(1f)) - ActionButton( + PrimaryButton( modifier = Modifier.fillMaxWidth().padding(vertical = Dimens.mediumPadding), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), onClick = onDismiss, text = stringResource(id = R.string.edit_message) ) - ActionButton( + VariantButton( modifier = Modifier.fillMaxWidth(), - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.surface, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), onClick = retry, text = stringResource(id = R.string.try_again) ) diff --git a/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/color/Color.kt b/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/color/Color.kt index f81c0b4409f4..e2cb7da4994f 100644 --- a/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/color/Color.kt +++ b/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/color/Color.kt @@ -1,5 +1,8 @@ package net.mullvad.mullvadvpn.lib.theme.color +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color internal val MullvadBlue20 = Color(0x33294D73) @@ -48,3 +51,12 @@ const val AlphaDisconnectButton = 0.6f const val AlphaScrollbar = 0.6f const val AlphaTopBar = 0.8f const val AlphaInvisible = 0f + +// Custom colors, they only link to normal material 3 colors for now +val ColorScheme.variant: Color + @Composable get() = MaterialTheme.colorScheme.surface +val ColorScheme.onVariant: Color + @Composable get() = MaterialTheme.colorScheme.onSurface + +val ColorScheme.selected: Color + @Composable get() = MaterialTheme.colorScheme.surface diff --git a/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/dimensions/Dimensions.kt b/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/dimensions/Dimensions.kt index bb56f7df4888..1307b2fae239 100644 --- a/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/dimensions/Dimensions.kt +++ b/android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/dimensions/Dimensions.kt @@ -7,6 +7,7 @@ data class Dimensions( val backButtonSideMargin: Dp = 30.dp, val buttonHeight: Dp = 44.dp, val buttonSeparation: Dp = 18.dp, + val buttonVerticalPadding: Dp = 8.dp, val cellEndPadding: Dp = 16.dp, val cellFooterTopPadding: Dp = 6.dp, val cellHeight: Dp = 52.dp, @@ -16,7 +17,6 @@ data class Dimensions( val cellVerticalSpacing: Dp = 14.dp, val chevronMargin: Dp = 4.dp, val cityRowPadding: Dp = 34.dp, - val connectButtonHeight: Dp = 50.dp, val countryRowPadding: Dp = 18.dp, val customPortBoxMinWidth: Dp = 80.dp, val dialogIconHeight: Dp = 44.dp, @@ -49,7 +49,6 @@ data class Dimensions( val searchFieldHeight: Dp = 42.dp, val searchFieldHorizontalPadding: Dp = 22.dp, val searchIconSize: Dp = 24.dp, - val selectLocationButtonHeight: Dp = 50.dp, val selectLocationTitlePadding: Dp = 12.dp, val selectableCellTextMargin: Dp = 12.dp, val sideMargin: Dp = 22.dp,