summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-09-29 17:04:17 +0200
committerJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-10-18 08:54:17 +0200
commit4bdd28f8de9850df69c541586c60cf5e114b7fb0 (patch)
tree19b44631334897712a1bf6564f0569be348a977b
parentdd18767b98f4650ae130492db71e70cf8556b805 (diff)
downloadmullvadvpn-4bdd28f8de9850df69c541586c60cf5e114b7fb0.tar.xz
mullvadvpn-4bdd28f8de9850df69c541586c60cf5e114b7fb0.zip
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
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ActionButton.kt51
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt149
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt15
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt71
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadButton.kt207
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/RedeemVoucherButton.kt20
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SitePaymentButton.kt21
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt38
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomPortCell.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ChangelogDialog.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialog.kt33
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceRemovalDialog.kt49
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt101
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt49
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt27
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ReportProblemNoEmailDialog.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt28
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt5
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt24
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt22
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt32
-rw-r--r--android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/color/Color.kt12
-rw-r--r--android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/dimensions/Dimensions.kt3
29 files changed, 499 insertions, 547 deletions
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 faf7052d4f..0000000000
--- 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 23c17f1075..e80e17e444 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 0000000000..7ba80f09d8
--- /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 8abe879082..376172e632 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 0000000000..3dd7068389
--- /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 c95c1bf82d..57532a8d42 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 59292a9aa6..93b5c77125 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 c76166d548..2feabcfaf3 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 9e2d002f84..8219aa9984 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 faa65de250..75888a8579 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 b22ff378ec..087ba3daf4 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 083aedd217..52f11babe7 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<String>, 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 32e8df77a7..a5d886de2e 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 1ac8873fc3..e08a82d694 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 cce0bb7356..4312b239af 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 48599da15a..e57e9be563 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 beca8a9f43..82773f079d 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 3753b4d2e6..0848b89594 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 7417d6ae7c..8415acbf4b 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 71f79e55b5..a8726fd0bb 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 2c2e9d7abc..806c7c93fa 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 5230575600..42ab9faef0 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 f7a15c2fea..102911ae36 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 bdce1c1660..d1c64b6c5a 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 a7d220c4e4..a772a45750 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 4fd2b2719e..f78b54f989 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 6dc34937d5..f5346fbc7d 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 f81c0b4409..e2cb7da499 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 bb56f7df48..1307b2fae2 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,