Skip to content

Commit

Permalink
[#294] Add OdsIconButton demo
Browse files Browse the repository at this point in the history
  • Loading branch information
florentmaitre committed Dec 14, 2022
1 parent 2671b66 commit b8179a8
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,15 @@ sealed class Component(
R.drawable.il_buttons,
R.drawable.il_buttons_small,
R.string.component_buttons_description,
listOf(Variant.ButtonsPrimary, Variant.ButtonsDefault, Variant.ButtonsOutlined, Variant.ButtonsText, Variant.ButtonsFunctional, Variant.ButtonsToggle)
listOf(
Variant.ButtonsPrimary,
Variant.ButtonsDefault,
Variant.ButtonsOutlined,
Variant.ButtonsText,
Variant.ButtonsFunctional,
Variant.ButtonsToggle,
Variant.ButtonsIcon,
)
)

object Cards : Component(
Expand Down Expand Up @@ -184,6 +192,7 @@ sealed class Variant(
object ButtonsText : Variant(R.string.component_buttons_low_emphasis, OdsComponent.OdsTextButton.name)
object ButtonsFunctional : Variant(R.string.component_buttons_functional, "${OdsComponent.OdsButton.name} with a functional style")
object ButtonsToggle : Variant(R.string.component_buttons_toggle, OdsComponent.OdsIconToggleButton.name)
object ButtonsIcon : Variant(R.string.component_buttons_icon, OdsComponent.OdsIconButton.name)

object CardImageFirst : Variant(R.string.component_card_image_first, OdsComponent.OdsImageFirstCard.name)
object CardTitleFirst : Variant(R.string.component_card_title_first, OdsComponent.OdsTitleFirstCard.name)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
*
* 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.demo.ui.components.buttons

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import com.orange.ods.compose.component.button.OdsIconButton
import com.orange.ods.compose.theme.OdsDisplaySurface
import com.orange.ods.demo.R
import com.orange.ods.demo.ui.components.utilities.ComponentCustomizationBottomSheetScaffold
import com.orange.ods.demo.ui.utilities.composable.SwitchListItem

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ButtonsIcon() {
val buttonCustomizationState = rememberButtonCustomizationState()

with(buttonCustomizationState) {
ComponentCustomizationBottomSheetScaffold(
bottomSheetScaffoldState = rememberBottomSheetScaffoldState(),
bottomSheetContent = {
SwitchListItem(labelRes = R.string.component_state_disabled, checked = disabled)
}) {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(vertical = dimensionResource(id = R.dimen.screen_vertical_margin))
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
OdsIconButton(
onClick = {},
painter = painterResource(id = R.drawable.ic_info),
contentDescription = "",
enabled = isEnabled
)
}

Spacer(modifier = Modifier.padding(top = dimensionResource(R.dimen.spacing_s)))

if (isSystemInDarkTheme()) {
LightSurface(horizontalAlignment = Alignment.CenterHorizontally) {
OdsIconButton(
onClick = {},
painter = painterResource(id = R.drawable.ic_info),
contentDescription = "",
enabled = isEnabled,
displaySurface = OdsDisplaySurface.Light
)
}
} else {
DarkSurface(horizontalAlignment = Alignment.CenterHorizontally) {
OdsIconButton(
onClick = {},
painter = painterResource(id = R.drawable.ic_info),
contentDescription = "",
enabled = isEnabled,
displaySurface = OdsDisplaySurface.Dark
)
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.dimensionResource
Expand All @@ -37,22 +38,27 @@ fun ComponentButtons(variant: Variant) {
Variant.ButtonsText -> ButtonsText()
Variant.ButtonsFunctional -> ButtonsContained(OdsButtonStyle.FunctionalPositive)
Variant.ButtonsToggle -> ButtonsToggle()
Variant.ButtonsIcon -> ButtonsIcon()
else -> {}
}
}

@Composable
fun DarkSurface(content: @Composable ColumnScope.() -> Unit) {
ForcedBackgroundColumn(darkSurface = true, content = content)
fun DarkSurface(horizontalAlignment: Alignment.Horizontal = Alignment.Start, content: @Composable ColumnScope.() -> Unit) {
ForcedBackgroundColumn(horizontalAlignment = horizontalAlignment, darkSurface = true, content = content)
}

@Composable
fun LightSurface(content: @Composable ColumnScope.() -> Unit) {
ForcedBackgroundColumn(darkSurface = false, content = content)
fun LightSurface(horizontalAlignment: Alignment.Horizontal = Alignment.Start, content: @Composable ColumnScope.() -> Unit) {
ForcedBackgroundColumn(horizontalAlignment = horizontalAlignment, darkSurface = false, content = content)
}

@Composable
private fun ForcedBackgroundColumn(darkSurface: Boolean, content: @Composable ColumnScope.() -> Unit) {
private fun ForcedBackgroundColumn(
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
darkSurface: Boolean,
content: @Composable ColumnScope.() -> Unit
) {
val backgroundColor: Color
@StringRes val textRes: Int
val displaySurface: OdsDisplaySurface
Expand All @@ -70,12 +76,15 @@ private fun ForcedBackgroundColumn(darkSurface: Boolean, content: @Composable Co
modifier = Modifier
.fillMaxWidth()
.background(color = backgroundColor)
.padding(bottom = dimensionResource(R.dimen.spacing_m))
.padding(bottom = dimensionResource(R.dimen.spacing_m)),
horizontalAlignment = horizontalAlignment
) {
OdsTextBody2(
modifier = Modifier
.padding(horizontal = dimensionResource(id = R.dimen.spacing_m))
.padding(top = dimensionResource(id = R.dimen.spacing_s)),
.padding(top = dimensionResource(id = R.dimen.spacing_s))
.fillMaxWidth()
.align(Alignment.Start),
text = stringResource(id = textRes),
displaySurface = displaySurface
)
Expand Down
1 change: 1 addition & 0 deletions demo/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<string name="component_buttons_toggle_count">Toggle count</string>
<string name="component_buttons_toggle_remove">Remove toggle</string>
<string name="component_buttons_toggle_add">Add toggle</string>
<string name="component_buttons_icon">Icon buttons</string>
<string name="component_button_variable_width">Variable width</string>
<string name="component_button_style_primary">Primary</string>
<string name="component_button_style_default">Default</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@

package com.orange.ods.compose.component.button

import androidx.compose.foundation.background
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.ripple.LocalRippleTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
Expand All @@ -24,7 +27,12 @@ import androidx.compose.ui.res.painterResource
import com.orange.ods.compose.component.OdsComponentApi
import com.orange.ods.compose.component.utilities.Preview
import com.orange.ods.compose.component.utilities.UiModePreviews
import com.orange.ods.compose.theme.OdsDarkRippleTheme
import com.orange.ods.compose.theme.OdsDisplaySurface
import com.orange.ods.compose.theme.OdsLightRippleTheme
import com.orange.ods.compose.theme.OdsRippleTheme
import com.orange.ods.compose.theme.OdsTheme
import com.orange.ods.theme.OdsColors

/**
* OdsIconButton is a clickable icon, used to represent actions. An OdsIconButton has an overall minimum
Expand All @@ -40,7 +48,7 @@ import com.orange.ods.compose.theme.OdsTheme
* @param modifier optional [Modifier] for this IconButton
* @param enabled whether or not this OdsIconButton will handle input events and appear enabled for
* semantics purposes, true by default
* @param tint the icon tint, onSurface by default
* @param tint the icon tint
*/
@Composable
@OdsComponentApi
Expand All @@ -50,13 +58,58 @@ fun OdsIconButton(
contentDescription: String,
modifier: Modifier = Modifier,
enabled: Boolean = true,
tint: Color = OdsTheme.colors.onSurface
tint: Color
) {
IconButton(onClick = onClick, modifier = modifier, enabled = enabled) {
Icon(painter = painter, contentDescription = contentDescription, tint = getIconColor(tint = tint, enabled = enabled))
}
}

/**
* OdsIconButton is a clickable icon, used to represent actions. An OdsIconButton has an overall minimum
* touch target size of 48 x 48dp, to meet accessibility guidelines. It contains an [Icon] centered
* inside the OdsIconButton.
* If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp.
*
* This component is typically used inside an App Bar for the navigation icon / actions.
*
* @param onClick the lambda to be invoked when this icon is pressed
* @param painter the painter to be drawn inside the IconButton
* @param contentDescription the content description associated to this OdsIconButton.
* @param modifier optional [Modifier] for this IconButton
* @param enabled whether or not this OdsIconButton will handle input events and appear enabled for
* semantics purposes, true by default
* @param displaySurface optional allow to force the button display on a dark or light
* surface. By default the appearance applied is based on the system night mode value.
*/
@Composable
@OdsComponentApi
fun OdsIconButton(
onClick: () -> Unit,
painter: Painter,
contentDescription: String,
modifier: Modifier = Modifier,
enabled: Boolean = true,
displaySurface: OdsDisplaySurface = OdsDisplaySurface.Default
) {
CompositionLocalProvider(
LocalRippleTheme provides when (displaySurface) {
OdsDisplaySurface.Default -> OdsRippleTheme
OdsDisplaySurface.Light -> OdsLightRippleTheme
OdsDisplaySurface.Dark -> OdsDarkRippleTheme
}
) {
OdsIconButton(
onClick = onClick,
painter = painter,
contentDescription = contentDescription,
modifier = modifier.background(color = OdsTheme.colors.iconButtonBackgroundColor(displaySurface = displaySurface)),
enabled = enabled,
tint = OdsTheme.colors.iconButtonIconColor(displaySurface = displaySurface)
)
}
}

/**
* OdsIconButton is a clickable icon, used to represent actions. An OdsIconButton has an overall minimum
* touch target size of 48 x 48dp, to meet accessibility guidelines. It contains an [Icon] centered
Expand All @@ -71,7 +124,7 @@ fun OdsIconButton(
* @param modifier optional [Modifier] for this IconButton
* @param enabled whether or not this OdsIconButton will handle input events and appear enabled for
* semantics purposes, true by default
* @param tint the icon tint, onSurface by default
* @param tint the icon tint
*/
@Composable
@OdsComponentApi
Expand All @@ -81,16 +134,78 @@ fun OdsIconButton(
contentDescription: String,
modifier: Modifier = Modifier,
enabled: Boolean = true,
tint: Color = OdsTheme.colors.onSurface
tint: Color
) {
IconButton(onClick = onClick, modifier = modifier, enabled = enabled) {
Icon(imageVector = imageVector, contentDescription = contentDescription, tint = getIconColor(tint = tint, enabled = enabled))
}
}

/**
* OdsIconButton is a clickable icon, used to represent actions. An OdsIconButton has an overall minimum
* touch target size of 48 x 48dp, to meet accessibility guidelines. It contains an [Icon] centered
* inside the OdsIconButton.
* If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp.
*
* This component is typically used inside an App Bar for the navigation icon / actions.
*
* @param onClick the lambda to be invoked when this icon is pressed
* @param imageVector the ImageVector to be drawn inside the IconButton
* @param contentDescription the content description associated to this OdsIconButton.
* @param modifier optional [Modifier] for this IconButton
* @param enabled whether or not this OdsIconButton will handle input events and appear enabled for
* semantics purposes, true by default
* @param displaySurface optional allow to force the button display on a dark or light
* surface. By default the appearance applied is based on the system night mode value.
*/
@Composable
@OdsComponentApi
fun OdsIconButton(
onClick: () -> Unit,
imageVector: ImageVector,
contentDescription: String,
modifier: Modifier = Modifier,
enabled: Boolean = true,
displaySurface: OdsDisplaySurface = OdsDisplaySurface.Default
) {
CompositionLocalProvider(
LocalRippleTheme provides when (displaySurface) {
OdsDisplaySurface.Default -> OdsRippleTheme
OdsDisplaySurface.Light -> OdsLightRippleTheme
OdsDisplaySurface.Dark -> OdsDarkRippleTheme
}
) {
OdsIconButton(
onClick = onClick,
imageVector = imageVector,
contentDescription = contentDescription,
modifier = modifier.background(color = OdsTheme.colors.iconButtonBackgroundColor(displaySurface = displaySurface)),
enabled = enabled,
tint = OdsTheme.colors.iconButtonIconColor(displaySurface = displaySurface)
)
}
}

@Composable
private fun getIconColor(tint: Color, enabled: Boolean) = if (enabled) tint else tint.copy(alpha = ContentAlpha.disabled)

@Composable
private fun OdsColors.iconButtonBackgroundColor(displaySurface: OdsDisplaySurface) =
when (displaySurface) {
OdsDisplaySurface.Default -> Color.Unspecified
OdsDisplaySurface.Dark -> OdsTheme.darkThemeColors.surface
OdsDisplaySurface.Light -> OdsTheme.lightThemeColors.surface
}

@Composable
private fun OdsColors.iconButtonIconColor(displaySurface: OdsDisplaySurface) =
when (displaySurface) {
OdsDisplaySurface.Default -> OdsTheme.colors.onSurface
OdsDisplaySurface.Dark -> OdsTheme.darkThemeColors.onSurface
OdsDisplaySurface.Light -> OdsTheme.lightThemeColors.onSurface
}


@UiModePreviews.Default
@Composable
private fun PreviewOdsIconButtonWithPainter() = Preview {
Expand Down

0 comments on commit b8179a8

Please sign in to comment.