diff --git a/app/src/main/java/org/mozilla/fenix/compose/Chip.kt b/app/src/main/java/org/mozilla/fenix/compose/Chip.kt new file mode 100644 index 000000000..09e2ccc9e --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/compose/Chip.kt @@ -0,0 +1,207 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.compose + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ChipDefaults.chipColors +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.mozilla.fenix.compose.annotation.LightDarkPreview +import org.mozilla.fenix.theme.FirefoxTheme + +/** + * Default layout for a clickable chip. + * + * @param text [String] displayed in this chip. + * @param modifier [Modifier] used to be applied to the layout of the chip. + * @param isSquare Optional [Boolean] to control whether the Chip's corners are square or rounded. + * @param backgroundColor Optional background [Color] for the chip. + * @param textColor Optional text [Color] for the chip. + * @param onClick Callback for when the user taps this chip. + */ +@OptIn(ExperimentalMaterialApi::class) +@Composable +private fun Chip( + text: String, + modifier: Modifier = Modifier, + isSquare: Boolean = false, + backgroundColor: Color = FirefoxTheme.colors.actionPrimary, + textColor: Color = FirefoxTheme.colors.textActionPrimary, + onClick: () -> Unit, +) { + androidx.compose.material.Chip( + onClick = onClick, + modifier = modifier, + shape = if (isSquare) RoundedCornerShape(4.dp) else RoundedCornerShape(25.dp), + colors = chipColors( + backgroundColor = backgroundColor, + ), + ) { + Text( + text = text, + color = textColor, + style = FirefoxTheme.typography.body2, + ) + } +} + +/** + * Default layout of a selectable chip. + * + * @param text [String] displayed in this chip. + * @param isSelected Whether this should be shown as selected. + * @param isSquare Optional [Boolean] to control whether the Chip's corners are square or rounded. + * @param selectableChipColors The color set defined by [SelectableChipColors] used to style the chip. + * @param onClick Callback for when the user taps this chip. + */ +@Composable +fun SelectableChip( + text: String, + isSelected: Boolean, + isSquare: Boolean = false, + selectableChipColors: SelectableChipColors = SelectableChipColors.buildColors(), + onClick: () -> Unit, +) { + var selected by remember { mutableStateOf(isSelected) } + + Chip( + text = text, + backgroundColor = if (selected) { + selectableChipColors.selectedBackgroundColor + } else { + selectableChipColors.unselectedBackgroundColor + }, + isSquare = isSquare, + textColor = if (selected) selectableChipColors.selectedTextColor else selectableChipColors.unselectedTextColor, + ) { + selected = !selected + onClick() + } +} + +/** + * Wrapper for the color parameters of [SelectableChip]. + * + * @param selectedBackgroundColor Background [Color] when the chip is selected. + * @param unselectedBackgroundColor Background [Color] when the chip is not selected. + * @param selectedTextColor Text [Color] when the chip is selected. + * @param unselectedTextColor Text [Color] when the chip is not selected. + */ +data class SelectableChipColors( + val selectedBackgroundColor: Color, + val unselectedBackgroundColor: Color, + val selectedTextColor: Color, + val unselectedTextColor: Color, +) { + companion object { + + /** + * Builder function used to construct an instance of [SelectableChipColors]. + */ + @Composable + fun buildColors( + selectedBackgroundColor: Color = FirefoxTheme.colors.actionPrimary, + unselectedBackgroundColor: Color = FirefoxTheme.colors.actionTertiary, + selectedTextColor: Color = FirefoxTheme.colors.textActionPrimary, + unselectedTextColor: Color = FirefoxTheme.colors.textActionTertiary, + ) = SelectableChipColors( + selectedBackgroundColor = selectedBackgroundColor, + unselectedBackgroundColor = unselectedBackgroundColor, + selectedTextColor = selectedTextColor, + unselectedTextColor = unselectedTextColor, + ) + } +} + +@Composable +@LightDarkPreview +private fun ChipPreview() { + FirefoxTheme { + Column( + modifier = Modifier + .background(FirefoxTheme.colors.layer1), + verticalArrangement = Arrangement.SpaceEvenly, + ) { + Chip( + text = "Chirp", + onClick = {}, + ) + + Chip( + text = "SquareChip", + isSquare = true, + onClick = {}, + ) + } + } +} + +@Composable +@Preview(name = "Selectable Chip", uiMode = Configuration.UI_MODE_NIGHT_YES) +@Preview(name = "Selectable Chip", uiMode = Configuration.UI_MODE_NIGHT_NO) +private fun SelectableChipPreview() { + FirefoxTheme { + Row( + modifier = Modifier + .fillMaxWidth() + .background(FirefoxTheme.colors.layer1), + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + SelectableChip(text = "ChirpOne", isSelected = false) {} + SelectableChip(text = "ChirpTwo", isSelected = true, isSquare = true) {} + } + } +} + +@Composable +@Preview(name = "Custom Colors", uiMode = Configuration.UI_MODE_NIGHT_YES) +@Preview(name = "Custom Colors", uiMode = Configuration.UI_MODE_NIGHT_NO) +private fun SelectableChipWithCustomColorsPreview() { + FirefoxTheme { + Row( + modifier = Modifier + .fillMaxWidth() + .background(FirefoxTheme.colors.layer1), + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + SelectableChip( + text = "Yellow", + isSelected = false, + selectableChipColors = SelectableChipColors( + selectedBackgroundColor = Color.Yellow, + unselectedBackgroundColor = Color.DarkGray, + selectedTextColor = Color.Black, + unselectedTextColor = Color.Gray, + ), + ) {} + + SelectableChip( + text = "Cyan", + isSelected = true, + selectableChipColors = SelectableChipColors( + selectedBackgroundColor = Color.Cyan, + unselectedBackgroundColor = Color.DarkGray, + selectedTextColor = Color.Red, + unselectedTextColor = Color.Gray, + ), + ) {} + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/compose/SelectableChip.kt b/app/src/main/java/org/mozilla/fenix/compose/SelectableChip.kt deleted file mode 100644 index fc80427d1..000000000 --- a/app/src/main/java/org/mozilla/fenix/compose/SelectableChip.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.compose - -import android.content.res.Configuration.UI_MODE_NIGHT_NO -import android.content.res.Configuration.UI_MODE_NIGHT_YES -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.selection.selectable -import androidx.compose.material.MaterialTheme -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.text.TextStyle -import androidx.compose.ui.text.capitalize -import androidx.compose.ui.text.intl.Locale -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import org.mozilla.fenix.compose.annotation.LightDarkPreview -import org.mozilla.fenix.theme.FirefoxTheme - -/** - * Default layout of a selectable chip. - * - * @param text [String] displayed in this chip. Ideally should only be one word. - * @param isSelected Whether this should be shown as selected. - * @param selectedTextColor Optional text [Color] when the chip is selected. - * @param unselectedTextColor Optional text [Color] when the chip is not selected. - * @param selectedBackgroundColor Optional background [Color] when the chip is selected. - * @param unselectedBackgroundColor Optional background [Color] when the chip is not selected. - * @param onClick Callback for when the user taps this. - */ -@Composable -fun SelectableChip( - text: String, - isSelected: Boolean, - selectedTextColor: Color? = null, - unselectedTextColor: Color? = null, - selectedBackgroundColor: Color? = null, - unselectedBackgroundColor: Color? = null, - onClick: () -> Unit, -) { - Box( - modifier = Modifier - .selectable(isSelected) { onClick() } - .clip(MaterialTheme.shapes.small) - .background( - color = if (isSelected) { - selectedBackgroundColor ?: FirefoxTheme.colors.actionPrimary - } else { - unselectedBackgroundColor ?: FirefoxTheme.colors.actionTertiary - }, - ) - .padding(horizontal = 16.dp, vertical = 10.dp), - ) { - Text( - text = text.capitalize(Locale.current), - style = TextStyle(fontSize = 14.sp), - color = if (isSelected) { - selectedTextColor ?: FirefoxTheme.colors.textActionPrimary - } else { - unselectedTextColor ?: FirefoxTheme.colors.textActionTertiary - }, - ) - } -} - -@Composable -@LightDarkPreview -private fun SelectableChipPreview() { - FirefoxTheme { - Row( - modifier = Modifier - .fillMaxWidth() - .background(FirefoxTheme.colors.layer1), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - SelectableChip(text = "Chirp", isSelected = false) { } - SelectableChip(text = "Chirp", isSelected = true) { } - } - } -} - -@Composable -@Preview(uiMode = UI_MODE_NIGHT_YES) -@Preview(uiMode = UI_MODE_NIGHT_NO) -private fun SelectableChipWithCustomColorsPreview() { - FirefoxTheme { - Row( - modifier = Modifier - .fillMaxWidth() - .background(FirefoxTheme.colors.layer1), - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - SelectableChip( - text = "Chirp", - isSelected = false, - unselectedTextColor = FirefoxTheme.colors.textSecondary, - unselectedBackgroundColor = Color.Cyan, - ) { } - SelectableChip( - text = "Chirp", - isSelected = true, - selectedTextColor = Color.Black, - selectedBackgroundColor = Color.Yellow, - ) { } - } - } -}