Skip to content

Commit

Permalink
Merge pull request #336 from Orange-OpenSource/305-update-the-chips-c…
Browse files Browse the repository at this point in the history
…ustomization

305 - update the chips customization
  • Loading branch information
florentmaitre authored Nov 24, 2022
2 parents 186b3c8 + 5a0fe87 commit b783dc5
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 24 deletions.
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- \[Demo\] Add Snackbar component ([#114](https://github.com/Orange-OpenSource/ods-android/issues/114))
- \[Lib\] Add `OdsSnackbar` and `OdsSnackbarHost` composable to manage snackbars display ([#114](https://github.com/Orange-OpenSource/ods-android/issues/114))
- \[ThemeConfigurationContract\] Add `outlinedChips` boolean in the theme contract to allow to choose between outlined or filled chips in a custom theme ([#305](https://github.com/Orange-OpenSource/ods-android/issues/305))

### Changed

Expand All @@ -19,10 +20,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- \[Demo\] Add customization bottom sheets for buttons ([#303](https://github.com/Orange-OpenSource/ods-android/issues/303))
- \[Demo\] Replace action buttons switches by a counter in cards customization bottom sheet ([#327](https://github.com/Orange-OpenSource/ods-android/issues/327))
- \[Demo\] Add customization bottom sheets for sliders ([#307](https://github.com/Orange-OpenSource/ods-android/issues/307))
- \[Demo\] Demonstrate outlined or filled chips according theme configuration ([#305](https://github.com/Orange-OpenSource/ods-android/issues/305))
- \[Lib\] Allow to add side icons to `OdsSliderLockups` ([#307](https://github.com/Orange-OpenSource/ods-android/issues/307))
- \[Lib\] Use `OptIn` annotation instead of propagating `ExperimentalMaterialApi` and `ExperimentalPagerApi` ([#320](https://github.com/Orange-OpenSource/ods-android/issues/320))
- \[Lib\] Use multipreview annotation instead of duplicating `Preview` annotations ([#324](https://github.com/Orange-OpenSource/ods-android/issues/324))
- \[Lib\] Change `OdsIconToggleButton` display ([#303](https://github.com/Orange-OpenSource/ods-android/issues/303))
- \[ThemeInnovationCup\] Use filled chips ([#305](https://github.com/Orange-OpenSource/ods-android/issues/305))

### Fixed

- \[Lib\] Fix filter chips display for custom themes ([#305](https://github.com/Orange-OpenSource/ods-android/issues/305))

### Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ import com.orange.ods.compose.component.chip.OdsChoiceChip
import com.orange.ods.compose.component.chip.OdsChoiceChipsFlowRow
import com.orange.ods.compose.text.OdsTextBody2
import com.orange.ods.demo.R
import com.orange.ods.demo.ui.LocalMainThemeManager
import com.orange.ods.demo.ui.components.chips.ChipCustomizationState.ChipType
import com.orange.ods.demo.ui.components.chips.ChipCustomizationState.LeadingElement
import com.orange.ods.demo.ui.components.utilities.ComponentCustomizationBottomSheetScaffold
import com.orange.ods.demo.ui.components.utilities.clickOnElement
import com.orange.ods.demo.ui.utilities.composable.CheckboxListItem
import com.orange.ods.demo.ui.utilities.composable.Subtitle
import com.orange.ods.theme.OdsComponentCustomizations.Companion.ChipStyle

@OptIn(ExperimentalMaterialApi::class)
@Composable
Expand Down Expand Up @@ -68,7 +70,6 @@ fun Chip() {
chipCustomizationState.resetLeadingElement()
}

CheckboxListItem(labelRes = R.string.component_state_outlined, checked = chipCustomizationState.outlinedChecked)
CheckboxListItem(labelRes = R.string.component_state_disabled, checked = chipCustomizationState.disabledChecked)

}) {
Expand Down Expand Up @@ -98,12 +99,13 @@ fun ChipTypeDemo(chipType: ChipType, content: @Composable () -> Unit) {
@Composable
private fun Chip(chipCustomizationState: ChipCustomizationState) {
val context = LocalContext.current
val outlinedChips = LocalMainThemeManager.current.currentThemeConfiguration.components.chipStyle == ChipStyle.Outlined
val cancelCrossLabel = stringResource(id = R.string.component_element_cancel_cross)
val chipLabel = stringResource(id = R.string.component_chip)

with(chipCustomizationState) {
if (isChoiceChip) {
OdsChoiceChipsFlowRow(selectedChip = choiceChipIndexSelected, outlinedChips = isOutlined) {
OdsChoiceChipsFlowRow(selectedChip = choiceChipIndexSelected, outlinedChips = outlinedChips) {
for (index in 1..4) {
OdsChoiceChip(
text = "${stringResource(id = chipType.value.nameRes)} $index",
Expand All @@ -116,7 +118,7 @@ private fun Chip(chipCustomizationState: ChipCustomizationState) {
OdsChip(
text = stringResource(id = R.string.component_chip_type, stringResource(id = chipType.value.nameRes)),
onClick = { clickOnElement(context, chipLabel) },
outlined = outlinedChecked.value,
outlined = outlinedChips,
leadingIcon = if (isActionChip || hasLeadingIcon) painterResource(id = R.drawable.ic_heart) else null,
leadingAvatar = if (hasLeadingAvatar) painterResource(id = R.drawable.placeholder_small) else null,
enabled = !disabledChecked.value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,16 @@ fun rememberChipCustomizationState(
chipType: MutableState<ChipType> = rememberSaveable { mutableStateOf(ChipType.Input) },
leadingElement: MutableState<LeadingElement> = rememberSaveable { mutableStateOf(LeadingElement.None) },
disabledChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(false) },
outlinedChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(false) },
choiceChipIndexSelected: MutableState<Int?> = rememberSaveable { mutableStateOf(null) }
) =
remember(chipType, leadingElement, disabledChecked, outlinedChecked, choiceChipIndexSelected) {
ChipCustomizationState(chipType, leadingElement, disabledChecked, outlinedChecked, choiceChipIndexSelected)
remember(chipType, leadingElement, disabledChecked, choiceChipIndexSelected) {
ChipCustomizationState(chipType, leadingElement, disabledChecked, choiceChipIndexSelected)
}

class ChipCustomizationState(
val chipType: MutableState<ChipType>,
val leadingElement: MutableState<LeadingElement>,
val disabledChecked: MutableState<Boolean>,
val outlinedChecked: MutableState<Boolean>,
val choiceChipIndexSelected: MutableState<Int?>
) {

Expand All @@ -50,7 +48,7 @@ class ChipCustomizationState(
Choice -> R.string.component_chip_type_choice
Filter -> R.string.component_chip_type_filter
}

val descriptionRes: Int
get() = when (this) {
Input -> R.string.component_chip_type_input_description
Expand Down Expand Up @@ -82,9 +80,6 @@ class ChipCustomizationState(
val isEnabled
get() = !disabledChecked.value

val isOutlined
get() = outlinedChecked.value

fun resetLeadingElement() {
leadingElement.value = LeadingElement.None
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ import com.orange.ods.compose.component.chip.OdsChoiceChip
import com.orange.ods.compose.component.chip.OdsChoiceChipsFlowRow
import com.orange.ods.compose.component.chip.OdsFilterChip
import com.orange.ods.demo.R
import com.orange.ods.demo.ui.LocalMainThemeManager
import com.orange.ods.demo.ui.components.utilities.ComponentCustomizationBottomSheetScaffold
import com.orange.ods.demo.ui.utilities.composable.CheckboxListItem
import com.orange.ods.demo.ui.utilities.composable.Subtitle
import com.orange.ods.theme.OdsComponentCustomizations.Companion.ChipStyle

@OptIn(ExperimentalMaterialApi::class)
@Composable
Expand All @@ -49,7 +51,6 @@ fun ChipFilter() {
OdsChoiceChip(textRes = R.string.component_element_avatar, value = ChipCustomizationState.LeadingElement.Avatar)
}

CheckboxListItem(labelRes = R.string.component_state_outlined, checked = chipCustomizationState.outlinedChecked)
CheckboxListItem(labelRes = R.string.component_state_disabled, checked = chipCustomizationState.disabledChecked)

}) {
Expand All @@ -65,13 +66,14 @@ fun ChipFilter() {

@Composable
private fun FilterChip(index: Int, customizationState: ChipCustomizationState) {
val outlinedChips = LocalMainThemeManager.current.currentThemeConfiguration.components.chipStyle == ChipStyle.Outlined
val selected = rememberSaveable { mutableStateOf(false) }
OdsFilterChip(
text = "${stringResource(id = R.string.component_chip_type_filter)} $index",
leadingAvatar = if (customizationState.hasLeadingAvatar) painterResource(id = R.drawable.placeholder_small) else null,
onClick = { selected.value = !selected.value },
outlined = outlinedChips,
selected = selected.value,
outlined = customizationState.outlinedChecked.value,
enabled = !customizationState.disabledChecked.value,
)
}
1 change: 0 additions & 1 deletion demo/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
<string name="component_state_disabled">Disabled</string>
<string name="component_state_error">Error</string>
<string name="component_state_default">Default</string>
<string name="component_state_outlined">Outlined</string>
<string name="component_state_expanded">Expanded</string>
<string name="component_state_collapsed">Collapsed</string>
<string name="component_on_click_toast">Click on %s</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import com.orange.ods.utilities.extension.noRippleClickable
* @param text Text to display in the chip.
* @param onClick called when the chip is clicked.
* @param modifier Modifier to be applied to the chip
* @param outlined If set to true, a border will be drawn around the chip.
* @param outlined If true, a border will be drawn around the chip otherwise a filled chip will be displayed.
* @param enabled When disabled, chip will not respond to user input. It will also appear visually
* disabled and disabled to accessibility services.
* @param selected When selected the chip is highlighted (useful for choice chips).
Expand All @@ -72,7 +72,7 @@ fun OdsChip(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
outlined: Boolean = false,
outlined: Boolean = true,
enabled: Boolean = true,
selected: Boolean = false,
leadingIcon: Painter? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ internal object OdsChipDefaults {
*/
internal const val SurfaceOverlayOpacity = 0.12f

/**
* The color opacity used for a selected chip's leading icon or content overlay.
*/
private const val SelectedOverlayOpacity = 0.16f

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun chipColors(
Expand Down Expand Up @@ -53,14 +58,32 @@ internal object OdsChipDefaults {
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun filterChipColors(
backgroundColor: Color = OdsTheme.colors.onSurface.copy(alpha = SurfaceOverlayOpacity)
.compositeOver(OdsTheme.colors.surface),
backgroundColor: Color = OdsTheme.colors.onSurface.copy(alpha = SurfaceOverlayOpacity).compositeOver(OdsTheme.colors.surface),
contentColor: Color = OdsTheme.colors.onSurface.copy(alpha = ChipDefaults.ContentOpacity),
leadingIconColor: Color = contentColor.copy(alpha = ChipDefaults.LeadingIconOpacity)
) = ChipDefaults.filterChipColors(
backgroundColor = backgroundColor,
contentColor = contentColor,
leadingIconColor = contentColor.copy(alpha = ChipDefaults.LeadingIconOpacity),
leadingIconColor = leadingIconColor,
selectedBackgroundColor = OdsTheme.colors.onSurface.copy(alpha = SurfaceOverlayOpacity).compositeOver(backgroundColor),
selectedContentColor = OdsTheme.colors.onSurface.copy(alpha = SelectedOverlayOpacity).compositeOver(contentColor),
selectedLeadingIconColor = OdsTheme.colors.onSurface.copy(alpha = SelectedOverlayOpacity).compositeOver(leadingIconColor),
disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled)
)

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun outlinedFilterChipColors(
backgroundColor: Color = OdsTheme.colors.surface,
contentColor: Color = OdsTheme.colors.onSurface.copy(alpha = ChipDefaults.ContentOpacity),
leadingIconColor: Color = contentColor.copy(alpha = ChipDefaults.LeadingIconOpacity)
) = ChipDefaults.outlinedFilterChipColors(
backgroundColor = backgroundColor,
contentColor = contentColor,
leadingIconColor = leadingIconColor,
selectedBackgroundColor = OdsTheme.colors.onSurface.copy(alpha = SurfaceOverlayOpacity).compositeOver(backgroundColor),
selectedContentColor = OdsTheme.colors.onSurface.copy(alpha = SelectedOverlayOpacity).compositeOver(contentColor),
selectedLeadingIconColor = OdsTheme.colors.onSurface.copy(alpha = SelectedOverlayOpacity).compositeOver(leadingIconColor),
disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ import com.orange.ods.compose.component.utilities.UiModePreviews
*
* @param selectedChip The selected chips value state.
* @param modifier Modifier to be applied to the flow row.
* @param outlinedChips If set to true, a border will be drawn around [FlowRow] chips.
* @param outlinedChips If true, a border will be drawn around [FlowRow] chips. Otherwise chips will be filled.
* @param content The content of the choice chips [FlowRow].
*/
@Composable
@OdsComponentApi
fun <T> OdsChoiceChipsFlowRow(
selectedChip: MutableState<T>,
modifier: Modifier = Modifier,
outlinedChips: Boolean = false,
outlinedChips: Boolean = true,
content: @Composable OdsChoiceChipsFlowRowScope<T>.() -> Unit
) {
FlowRow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import com.orange.ods.compose.theme.OdsTheme
* @param text Text to display in the chip.
* @param onClick called when the chip is clicked.
* @param modifier Modifier to be applied to the chip
* @param outlined If set to true, a border will be drawn around the chip.
* @param outlined If true, a border will be drawn around the chip otherwise the chip will be filled.
* @param enabled When disabled, chip will not respond to user input. It will also appear visually
* disabled and disabled to accessibility services.
* @param selected Highlight the chip and display a selected icon if set to true.
Expand All @@ -69,7 +69,7 @@ fun OdsFilterChip(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
outlined: Boolean = false,
outlined: Boolean = true,
enabled: Boolean = true,
selected: Boolean = false,
leadingAvatar: Painter? = null,
Expand All @@ -86,7 +86,7 @@ fun OdsFilterChip(
} else null,
enabled = enabled,
interactionSource = if (enabled) remember { MutableInteractionSource() } else remember { DisabledInteractionSource() },
colors = OdsChipDefaults.filterChipColors(),
colors = odsFilterChipColors(outlined = outlined),
leadingIcon = when {
leadingAvatar != null -> {
{
Expand Down Expand Up @@ -122,6 +122,10 @@ fun OdsFilterChip(
}
}

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun odsFilterChipColors(outlined: Boolean) = if (outlined) OdsChipDefaults.outlinedFilterChipColors() else OdsChipDefaults.filterChipColors()

@Composable
private fun OdsChipSelectedIcon(tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)) {
Icon(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
*
* Copyright 2021 Orange
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
* /
*/

package com.orange.ods.theme

/**
* Contains all the allowed components customizations.
* This class can be extended to override default appearances.
*/
open class OdsComponentCustomizations {

companion object {
enum class ChipStyle {
Filled, Outlined
}
}

/**
* By default the chips are outlined. If your theme needs to use filled chips, set this parameter to `ChipStyle.Filled`.
*/
open val chipStyle: ChipStyle = ChipStyle.Outlined
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ interface OdsThemeConfigurationContract : Parcelable {
val shapes: Shapes
get() = Shapes()

/**
* Customization of the ODS components if needed
*/
val components: OdsComponentCustomizations
get() = OdsComponentCustomizations()

/**
* Demo Guideline definition
* By default a guideline typography is generated based on the theme configuration typography defined.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ package com.orange.ods.theme.innovationcup
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes
import androidx.compose.ui.unit.dp
import com.orange.ods.theme.OdsComponentCustomizations
import com.orange.ods.theme.OdsComponentCustomizations.Companion.ChipStyle
import com.orange.ods.theme.OdsThemeColors
import com.orange.ods.theme.OdsThemeConfigurationContract
import kotlinx.parcelize.Parcelize
Expand All @@ -33,4 +35,10 @@ class InnovationCupThemeConfiguration : OdsThemeConfigurationContract {
large = RoundedCornerShape(4.dp)
)

override val components: OdsComponentCustomizations
get() = object : OdsComponentCustomizations() {
override val chipStyle: ChipStyle
get() = ChipStyle.Filled
}

}

0 comments on commit b783dc5

Please sign in to comment.