Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

package com.orange.ouds.core.component

import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.isSystemInDarkTheme
Expand Down Expand Up @@ -205,9 +204,9 @@ fun OudsTriStateCheckboxItem(
ToggleableState.Off -> "Unselected"
ToggleableState.Indeterminate -> "Indeterminate"
},
backgroundColor = backgroundColor.value,
modifier = modifier
.then(toggleableModifier)
.background(color = backgroundColor.value)
.semantics(mergeDescendants = true) {},
handleHighContrastMode = true
)
Expand Down
183 changes: 117 additions & 66 deletions core/src/main/java/com/orange/ouds/core/component/OudsControlItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@

package com.orange.ouds.core.component

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
Expand All @@ -31,6 +34,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.error
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -69,6 +73,7 @@ internal fun OudsControlItem(
indicatorPosition: OudsControlItemIndicatorPosition,
checkedContentComponentName: String,
checkedContentSelectionStatus: String,
backgroundColor: Color,
modifier: Modifier = Modifier,
additionalLabel: String? = null,
handleHighContrastMode: Boolean = false
Expand All @@ -91,77 +96,79 @@ internal fun OudsControlItem(
) {
val controlItemTokens = OudsTheme.componentsTokens.controlItem

val itemIcon: (@Composable () -> Unit)? = icon?.let {
{
icon.Content(
extraParameters = OudsControlItemIcon.ExtraParameters(
tint = if (state == OudsControlItemState.Disabled) OudsTheme.colorScheme.content.disabled else OudsTheme.colorScheme.content.default
val itemIcon: (@Composable () -> Unit)? = if (error != null) {
{ ErrorIcon(state = state) }
} else {
icon?.let {
{
icon.Content(
extraParameters = OudsControlItemIcon.ExtraParameters(
tint = if (state == OudsControlItemState.Disabled) OudsTheme.colorScheme.content.disabled else OudsTheme.colorScheme.content.default
)
)
)
}
}
}

val leadingElement: (@Composable () -> Unit)? = if (indicatorPosition == OudsControlItemIndicatorPosition.Start) indicator else itemIcon
val trailingElement: (@Composable () -> Unit)? = if (indicatorPosition == OudsControlItemIndicatorPosition.Start) itemIcon else indicator

val filteredModifier = modifier.filter { it !is EdgeToEdgePaddingElement }
Box(
modifier = filteredModifier
.height(IntrinsicSize.Min)
.heightIn(min = controlItemTokens.sizeMinHeight.dp)
.widthIn(min = controlItemTokens.sizeMinWidth.dp)
.outerBorder(state = state, handleHighContrastMode = handleHighContrastMode)
.run {
error?.description?.let { description ->
semantics {
error(description)
}
}.orElse {
this
}
},
contentAlignment = Alignment.BottomCenter
) {
val edgeToEdgePaddingModifier = modifier.filter { it is EdgeToEdgePaddingElement }
Row(

Column(modifier = filteredModifier) {
Box(
modifier = Modifier
.padding(vertical = controlItemTokens.spacePaddingBlockDefault.value)
.edgeToEdgePadding(true)
.then(edgeToEdgePaddingModifier) // Override edgeToEdgePadding setting
.run {
// Apply default horizontal padding if edgeToEdgePadding is disabled
val element = edgeToEdgePaddingModifier.last() as? EdgeToEdgePaddingElement
if (element?.enabled == false) padding(horizontal = controlItemTokens.spacePaddingBlockDefault.value) else this
},
horizontalArrangement = Arrangement.spacedBy(controlItemTokens.spaceColumnGap.value)
.height(IntrinsicSize.Min)
.heightIn(min = controlItemTokens.sizeMinHeight.dp)
.widthIn(min = controlItemTokens.sizeMinWidth.dp)
.background(color = backgroundColor)
.outerBorder(state = state, handleHighContrastMode = handleHighContrastMode),
contentAlignment = Alignment.BottomCenter
) {
leadingElement?.let { LeadingTrailingBox(leadingElement) }
Column(
val edgeToEdgePaddingModifier = modifier.filter { it is EdgeToEdgePaddingElement }
Row(
modifier = Modifier
.weight(1f)
.align(Alignment.CenterVertically),
verticalArrangement = Arrangement.spacedBy(controlItemTokens.spaceRowGap.value)
.padding(vertical = controlItemTokens.spacePaddingBlockDefault.value)
.edgeToEdgePadding(true)
.then(edgeToEdgePaddingModifier) // Override edgeToEdgePadding setting
.run {
// Apply default horizontal padding if edgeToEdgePadding is disabled
val element = edgeToEdgePaddingModifier.last() as? EdgeToEdgePaddingElement
if (element?.enabled == false) padding(horizontal = controlItemTokens.spacePaddingBlockDefault.value) else this
},
horizontalArrangement = Arrangement.spacedBy(controlItemTokens.spaceColumnGap.value)
) {
Text(text = label, style = OudsTheme.typography.label.default.large, color = labelColor(state = state, error = error))
if (!additionalLabel.isNullOrBlank()) {
Text(
text = additionalLabel,
style = OudsTheme.typography.label.strong.medium,
color = additionalLabelColor(state = state)
)
}
if (!helperText.isNullOrBlank()) {
Text(
text = helperText,
style = OudsTheme.typography.label.default.medium,
color = helperTextColor(state = state)
)
leadingElement?.let { LeadingTrailingBox(leadingElement) }
Column(
modifier = Modifier
.weight(1f)
.align(Alignment.CenterVertically),
verticalArrangement = Arrangement.spacedBy(controlItemTokens.spaceRowGap.value)
) {
Text(text = label, style = OudsTheme.typography.label.default.large, color = labelColor(state = state, error = error))
if (!additionalLabel.isNullOrBlank()) {
Text(
text = additionalLabel,
style = OudsTheme.typography.label.strong.medium,
color = additionalLabelColor(state = state)
)
}
if (!helperText.isNullOrBlank()) {
Text(
text = helperText,
style = OudsTheme.typography.label.default.medium,
color = helperTextColor(state = state)
)
}
}
trailingElement?.let { LeadingTrailingBox(trailingElement) }
}
if (divider) {
OudsHorizontalDivider(color = dividerColor(state = state, error = error))
}
trailingElement?.let { LeadingTrailingBox(trailingElement) }
}
if (divider) {
OudsHorizontalDivider()
if (error != null && error.description.isNotBlank()) {
ErrorDescriptionText(text = error.description)
}
}
}
Expand Down Expand Up @@ -269,6 +276,38 @@ private fun LeadingTrailingBox(content: @Composable () -> Unit) {
}
}

@Composable
private fun ErrorDescriptionText(text: String) {
with(OudsTheme.componentsTokens.controlItem) {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(top = spacePaddingBlockTopErrorText.value)
.padding(horizontal = spacePaddingInline.value)
.semantics {
error(text)
},
text = text,
style = OudsTheme.typography.label.default.medium,
color = OudsTheme.colorScheme.content.status.negative
)
}
}

@Composable
private fun ErrorIcon(state: OudsControlItemState) {
with(OudsTheme.componentsTokens.controlItem) {
Icon(
modifier = Modifier
.padding(spacePaddingInlineErrorIcon.value)
.size(sizeErrorIcon.value),
painter = painterResource(id = OudsTheme.drawableResources.alertImportant),
contentDescription = null,
tint = errorColor(state = state)
)
}
}

@Composable
private fun backgroundColor(state: OudsControlItemState): Color {
return with(OudsTheme.componentsTokens.controlItem) {
Expand All @@ -281,22 +320,34 @@ private fun backgroundColor(state: OudsControlItemState): Color {
}
}

@Composable
private fun dividerColor(state: OudsControlItemState, error: OudsError?) =
if (error != null) {
errorColor(state = state)
} else {
OudsTheme.colorScheme.border.default
}

@Composable
private fun labelColor(state: OudsControlItemState, error: OudsError?) =
if (error != null) {
with(OudsTheme.colorScheme.action.negative) {
when (state) {
OudsControlItemState.Enabled -> enabled
OudsControlItemState.Hovered -> hover
OudsControlItemState.Pressed -> pressed
OudsControlItemState.Focused -> focus
OudsControlItemState.Disabled, OudsControlItemState.ReadOnly -> Color.Unspecified // Not allowed, exception thrown at the beginning of each control item
}
}
errorColor(state = state)
} else {
if (state == OudsControlItemState.Disabled) OudsTheme.colorScheme.content.disabled else OudsTheme.colorScheme.content.default
}

@Composable
private fun errorColor(state: OudsControlItemState) =
with(OudsTheme.colorScheme.action.negative) {
when (state) {
OudsControlItemState.Enabled -> enabled
OudsControlItemState.Hovered -> hover
OudsControlItemState.Pressed -> pressed
OudsControlItemState.Focused -> focus
OudsControlItemState.Disabled, OudsControlItemState.ReadOnly -> Color.Unspecified // Not allowed, exception thrown at the beginning of each control item
}
}

@Composable
private fun additionalLabelColor(state: OudsControlItemState) =
if (state == OudsControlItemState.Disabled) OudsTheme.colorScheme.content.disabled else OudsTheme.colorScheme.content.default
Expand Down Expand Up @@ -342,7 +393,7 @@ private fun <T, S> getPreviewParameterValues(values: List<T>, extraParameters: L
when (index) {
0 -> this
1 -> copy(hasIcon = true, additionalLabel = additionalLabel, helperText = helperText)
else -> copy(helperText = helperText, divider = true, error = OudsError(""))
else -> copy(helperText = helperText, divider = true, error = OudsError("This field can't be activated"))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fun OudsHorizontalDivider(
modifier: Modifier = Modifier,
color: OudsDividerColor = OudsDividerDefaults.Color
) {
HorizontalDivider(modifier = modifier, color = color.value, thickness = OudsTheme.componentsTokens.divider.borderWidth.value)
OudsHorizontalDivider(color = color.value, modifier = modifier)
}

/**
Expand Down Expand Up @@ -83,6 +83,14 @@ fun OudsVerticalDivider(
VerticalDivider(modifier = modifier, color = color.value, thickness = OudsTheme.componentsTokens.divider.borderWidth.value)
}

@Composable
internal fun OudsHorizontalDivider(
color: Color,
modifier: Modifier = Modifier,
) {
HorizontalDivider(modifier = modifier, color = color, thickness = OudsTheme.componentsTokens.divider.borderWidth.value)
}

/**
* Default values for an [OudsHorizontalDivider] or an [OudsVerticalDivider].
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

package com.orange.ouds.core.component

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
Expand Down Expand Up @@ -133,9 +132,9 @@ fun OudsRadioButtonItem(
indicatorPosition = if (reversed) OudsControlItemIndicatorPosition.End else OudsControlItemIndicatorPosition.Start,
checkedContentComponentName = "OudsRadioButtonItem",
checkedContentSelectionStatus = if (selected) "Selected" else "Unselected",
backgroundColor = backgroundColor.value,
modifier = modifier
.then(selectableModifier)
.background(color = backgroundColor.value)
.border(outlined = outlined, selected = selected, error = error, state = state)
.semantics(mergeDescendants = true) {},
handleHighContrastMode = true
Expand All @@ -146,7 +145,7 @@ fun OudsRadioButtonItem(
private fun Modifier.border(outlined: Boolean, selected: Boolean, error: OudsError?, state: OudsControlItemState): Modifier {
val borderColor = outlineBorderColor(state, selected, error)
val width = OudsTheme.borders.width.default.takeUnlessHairline

return if (outlined && borderColor != null && width != null) {
border(width = width, color = borderColor)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

package com.orange.ouds.core.component

import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.isSystemInDarkTheme
Expand Down Expand Up @@ -125,9 +124,9 @@ fun OudsSwitchItem(
indicatorPosition = if (reversed) OudsControlItemIndicatorPosition.Start else OudsControlItemIndicatorPosition.End,
checkedContentComponentName = "OudsSwitchItem",
checkedContentSelectionStatus = if (checked) "Selected" else "Unselected",
backgroundColor = backgroundColor.value,
modifier = modifier
.then(toggleableModifier)
.background(color = backgroundColor.value)
.semantics(mergeDescendants = true) {}
)
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading