From 9a965e420dd97d8e02409c2f3888f8eec4c8305e Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Wed, 4 May 2022 22:54:34 -0400 Subject: [PATCH] For #25119 - Add Secondary, Tertiary and Destructive Button composable components --- .../mozilla/fenix/compose/button/Button.kt | 192 ++++++++++++++---- .../recentsyncedtabs/view/RecentSyncedTab.kt | 41 ++-- .../CustomizeHomeButtonViewHolder.kt | 66 +----- .../org/mozilla/fenix/theme/FirefoxTheme.kt | 9 + app/src/main/res/values-night/colors.xml | 2 + app/src/main/res/values/colors.xml | 8 + 6 files changed, 199 insertions(+), 119 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/compose/button/Button.kt b/app/src/main/java/org/mozilla/fenix/compose/button/Button.kt index bd3ebc662..302b24179 100644 --- a/app/src/main/java/org/mozilla/fenix/compose/button/Button.kt +++ b/app/src/main/java/org/mozilla/fenix/compose/button/Button.kt @@ -4,25 +4,23 @@ package org.mozilla.fenix.compose.button +import android.content.res.Configuration import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer 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.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -30,11 +28,60 @@ import org.mozilla.fenix.R import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.Theme +/** + * Base component for buttons. + * + * @param text The button text to be displayed. + * @param textColor [Color] to apply to the button text. + * @param backgroundColor The background [Color] of the button. + * @param icon Optional [Painter] used to display a [Icon] before the button text. + * @param tint Tint [Color] to be applied to the icon. + * @param onClick Invoked when the user clicks on the button. + */ +@Composable +fun Button( + text: String, + textColor: Color, + backgroundColor: Color, + icon: Painter? = null, + tint: Color, + onClick: () -> Unit, +) { + androidx.compose.material.Button( + onClick = onClick, + modifier = Modifier + .fillMaxWidth() + .height(36.dp), + elevation = ButtonDefaults.elevation(defaultElevation = 0.dp, pressedElevation = 0.dp), + colors = ButtonDefaults.outlinedButtonColors( + backgroundColor = backgroundColor, + ), + ) { + icon?.let { painter -> + Icon( + painter = painter, + contentDescription = null, + tint = tint, + ) + + Spacer(modifier = Modifier.width(8.dp)) + } + + Text( + text = text, + color = textColor, + fontSize = 14.sp, + letterSpacing = 0.25.sp, + maxLines = 1, + ) + } +} + /** * Primary button. * * @param text The button text to be displayed. - * @param icon Optional button icon to be displayed. + * @param icon Optional [Painter] used to display an [Icon] before the button text. * @param onClick Invoked when the user clicks on the button. */ @Composable @@ -44,42 +91,115 @@ fun PrimaryButton( onClick: () -> Unit, ) { Button( + text = text, + textColor = FirefoxTheme.colors.textActionPrimary, + backgroundColor = FirefoxTheme.colors.actionPrimary, + icon = icon, + tint = FirefoxTheme.colors.iconActionPrimary, onClick = onClick, - modifier = Modifier - .clip(RoundedCornerShape(size = 4.dp)) - .fillMaxWidth() - .height(36.dp), - elevation = ButtonDefaults.elevation(defaultElevation = 0.dp, pressedElevation = 0.dp), - colors = ButtonDefaults.outlinedButtonColors(backgroundColor = FirefoxTheme.colors.actionPrimary), - ) { - if (icon != null) { - Icon( - painter = icon, - contentDescription = null, - tint = FirefoxTheme.colors.iconOnColor, - ) + ) +} - Spacer(modifier = Modifier.width(8.dp)) - } +/** + * Secondary button. + * + * @param text The button text to be displayed. + * @param icon Optional [Painter] used to display an [Icon] before the button text. + * @param onClick Invoked when the user clicks on the button. + */ +@Composable +fun SecondaryButton( + text: String, + icon: Painter? = null, + onClick: () -> Unit, +) { + Button( + text = text, + textColor = FirefoxTheme.colors.textActionSecondary, + backgroundColor = FirefoxTheme.colors.actionSecondary, + icon = icon, + tint = FirefoxTheme.colors.iconActionSecondary, + onClick = onClick, + ) +} - Text( - text = text, - color = FirefoxTheme.colors.textOnColorPrimary, - fontSize = 14.sp, - fontFamily = FontFamily(Font(R.font.metropolis_semibold)), - letterSpacing = 0.sp, - maxLines = 2 - ) - } +/** + * Tertiary button. + * + * @param text The button text to be displayed. + * @param icon Optional [Painter] used to display an [Icon] before the button text. + * @param onClick Invoked when the user clicks on the button. + */ +@Composable +fun TertiaryButton( + text: String, + icon: Painter? = null, + onClick: () -> Unit, +) { + Button( + text = text, + textColor = FirefoxTheme.colors.textActionTertiary, + backgroundColor = FirefoxTheme.colors.actionTertiary, + icon = icon, + tint = FirefoxTheme.colors.iconActionTertiary, + onClick = onClick, + ) +} + +/** + * Destructive button. + * + * @param text The button text to be displayed. + * @param icon Optional [Painter] used to display an [Icon] before the button text. + * @param onClick Invoked when the user clicks on the button. + */ +@Composable +fun DestructiveButton( + text: String, + icon: Painter? = null, + onClick: () -> Unit, +) { + Button( + text = text, + textColor = FirefoxTheme.colors.textWarningButton, + backgroundColor = FirefoxTheme.colors.actionSecondary, + icon = icon, + tint = FirefoxTheme.colors.iconWarningButton, + onClick = onClick, + ) } @Composable -@Preview -private fun PrimaryButtonPreview() { +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) +private fun ButtonPreview() { FirefoxTheme(theme = Theme.getTheme(isPrivate = false)) { - Box(Modifier.background(FirefoxTheme.colors.layer1)) { + Column( + modifier = Modifier + .background(FirefoxTheme.colors.layer1) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { PrimaryButton( - text = stringResource(R.string.recent_tabs_show_all), + text = "Label", + icon = painterResource(R.drawable.ic_tab_collection), + onClick = {}, + ) + + SecondaryButton( + text = "Label", + icon = painterResource(R.drawable.ic_tab_collection), + onClick = {}, + ) + + TertiaryButton( + text = "Label", + icon = painterResource(R.drawable.ic_tab_collection), + onClick = {}, + ) + + DestructiveButton( + text = "Label", icon = painterResource(R.drawable.ic_tab_collection), onClick = {}, ) diff --git a/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt b/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt index de77351f0..89a149a95 100644 --- a/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt +++ b/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTab.kt @@ -20,17 +20,13 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults import androidx.compose.material.Card -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -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 @@ -40,6 +36,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.compose.PrimaryText import org.mozilla.fenix.compose.SecondaryText import org.mozilla.fenix.compose.ThumbnailCard +import org.mozilla.fenix.compose.button.Button import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTab import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.Theme @@ -134,30 +131,20 @@ fun RecentSyncedTab( Spacer(modifier = Modifier.height(32.dp)) Button( + text = if (tab != null) { + stringResource(R.string.recent_tabs_see_all_synced_tabs_button_text) + } else { + "" + }, + textColor = FirefoxTheme.colors.textActionSecondary, + backgroundColor = if (tab == null) { + FirefoxTheme.colors.layer3 + } else { + FirefoxTheme.colors.actionSecondary + }, + tint = FirefoxTheme.colors.iconActionSecondary, onClick = onSeeAllSyncedTabsButtonClick, - colors = ButtonDefaults.outlinedButtonColors( - backgroundColor = if (tab == null) { - FirefoxTheme.colors.layer3 - } else { - FirefoxTheme.colors.actionSecondary - } - ), - elevation = ButtonDefaults.elevation( - defaultElevation = 0.dp, - pressedElevation = 0.dp - ), - modifier = Modifier - .height(36.dp) - .fillMaxWidth() - ) { - if (tab != null) { - Text( - text = stringResource(R.string.recent_tabs_see_all_synced_tabs_button_text), - textAlign = TextAlign.Center, - color = FirefoxTheme.colors.textActionSecondary - ) - } - } + ) } } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CustomizeHomeButtonViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CustomizeHomeButtonViewHolder.kt index b86416e97..dee7cca37 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CustomizeHomeButtonViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CustomizeHomeButtonViewHolder.kt @@ -7,28 +7,17 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders import android.view.View import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.ButtonDefaults.outlinedButtonColors -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.lifecycle.LifecycleOwner import org.mozilla.fenix.R import org.mozilla.fenix.compose.ComposeViewHolder +import org.mozilla.fenix.compose.button.TertiaryButton import org.mozilla.fenix.home.sessioncontrol.CustomizeHomeIteractor -import org.mozilla.fenix.theme.FirefoxTheme -import org.mozilla.fenix.theme.Theme class CustomizeHomeButtonViewHolder( composeView: ComposeView, @@ -40,56 +29,21 @@ class CustomizeHomeButtonViewHolder( val LAYOUT_ID = View.generateViewId() } + init { + val horizontalPadding = + composeView.resources.getDimensionPixelSize(R.dimen.home_item_horizontal_margin) + composeView.setPadding(horizontalPadding, 0, horizontalPadding, 0) + } + @Composable override fun Content() { Column { Spacer(modifier = Modifier.height(68.dp)) - CustomizeHomeButton( - onButtonClick = { interactor.openCustomizeHomePage() } + TertiaryButton( + text = stringResource(R.string.browser_menu_customize_home_1), + onClick = interactor::openCustomizeHomePage, ) } } } - -/** - * A "Customize homepage" button. - * - * @param onButtonClick Invoked when the user clicks on the button. - */ -@Composable -fun CustomizeHomeButton( - onButtonClick: () -> Unit -) { - Button( - onClick = { onButtonClick() }, - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .height(36.dp), - elevation = ButtonDefaults.elevation(defaultElevation = 0.dp, pressedElevation = 0.dp), - colors = outlinedButtonColors( - backgroundColor = FirefoxTheme.colors.actionTertiary, - contentColor = FirefoxTheme.colors.textActionTertiary - ) - ) { - Text( - text = stringResource(R.string.browser_menu_customize_home_1), - fontSize = 14.sp, - fontFamily = FontFamily(Font(R.font.metropolis_semibold)), - letterSpacing = 0.5.sp, - lineHeight = 16.sp, - maxLines = 1 - ) - } -} - -@Composable -@Preview -fun CustomizeHomeButtonPreview() { - FirefoxTheme(theme = Theme.getTheme(isPrivate = false)) { - CustomizeHomeButton( - onButtonClick = {} - ) - } -} diff --git a/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt b/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt index 94d84b4f9..5b3ce44ab 100644 --- a/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt +++ b/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt @@ -132,6 +132,7 @@ private val privateColorPalette = FirefoxColors( iconAccentYellow = PhotonColors.Yellow20, iconActionPrimary = PhotonColors.LightGrey05, iconActionSecondary = PhotonColors.DarkGrey90, + iconActionTertiary = PhotonColors.LightGrey05, iconGradientStart = PhotonColors.Violet20, iconGradientEnd = PhotonColors.Blue20, borderPrimary = PhotonColors.DarkGrey05, @@ -197,6 +198,7 @@ private val darkColorPalette = FirefoxColors( iconAccentYellow = PhotonColors.Yellow20, iconActionPrimary = PhotonColors.LightGrey05, iconActionSecondary = PhotonColors.DarkGrey90, + iconActionTertiary = PhotonColors.LightGrey05, iconGradientStart = PhotonColors.Violet20, iconGradientEnd = PhotonColors.Blue20, borderPrimary = PhotonColors.DarkGrey05, @@ -262,6 +264,7 @@ private val lightColorPalette = FirefoxColors( iconAccentYellow = PhotonColors.Yellow60, iconActionPrimary = PhotonColors.LightGrey05, iconActionSecondary = PhotonColors.DarkGrey90, + iconActionTertiary = PhotonColors.DarkGrey90, iconGradientStart = PhotonColors.Violet50, iconGradientEnd = PhotonColors.Blue60, borderPrimary = PhotonColors.LightGrey30, @@ -332,6 +335,7 @@ class FirefoxColors( iconAccentYellow: Color, iconActionPrimary: Color, iconActionSecondary: Color, + iconActionTertiary: Color, iconGradientStart: Color, iconGradientEnd: Color, borderPrimary: Color, @@ -507,6 +511,9 @@ class FirefoxColors( // Action secondary icon var iconActionSecondary by mutableStateOf(iconActionSecondary) private set + // Action tertiary icon + var iconActionTertiary by mutableStateOf(iconActionTertiary) + private set // Reader, ETP Shield var iconGradientStart by mutableStateOf(iconGradientStart) private set @@ -590,6 +597,7 @@ class FirefoxColors( iconAccentYellow = other.iconAccentYellow iconActionPrimary = other.iconActionPrimary iconActionSecondary = other.iconActionSecondary + iconActionTertiary = other.iconActionTertiary iconGradientStart = other.iconGradientStart iconGradientEnd = other.iconGradientEnd borderPrimary = other.borderPrimary @@ -655,6 +663,7 @@ class FirefoxColors( iconAccentYellow = iconAccentYellow, iconActionPrimary = iconActionPrimary, iconActionSecondary = iconActionSecondary, + iconActionTertiary = iconActionTertiary, iconGradientStart = iconGradientStart, iconGradientEnd = iconGradientEnd, borderPrimary = borderPrimary, diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 1d4f865ef..e0891dc73 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -107,6 +107,8 @@ @color/photonLightGrey05 @color/photonDarkGrey90 + + @color/photonLightGrey05 @color/photonViolet20 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 6989ab96d..61352760c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -107,6 +107,8 @@ @color/photonLightGrey05 @color/photonDarkGrey90 + + @color/photonDarkGrey90 @color/photonViolet50 @@ -232,6 +234,12 @@ @color/photonPink20 @color/photonGreen20 @color/photonYellow20 + + @color/photonLightGrey05 + + @color/photonDarkGrey90 + + @color/photonLightGrey05 @color/photonViolet20