Skip to content

Commit

Permalink
Update OudsButton according to design specifications
Browse files Browse the repository at this point in the history
  • Loading branch information
florentmaitre committed Nov 28, 2024
1 parent 0e1b5b0 commit b799b30
Show file tree
Hide file tree
Showing 18 changed files with 1,033 additions and 103 deletions.
2 changes: 2 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ app/src/main/res/drawable-night-xxxhdpi/il_tokens_grid_min_width.png
app/src/prod/res/drawable/ic_launcher_background.xml
app/src/prod/res/drawable/ic_launcher_foreground.xml

core/src/main/res/drawable/loading_indicator_circular.xml

docs/images/favicon-16x16.png
docs/images/orange-logo.svg

Expand Down
556 changes: 516 additions & 40 deletions core/src/main/java/com/orange/ouds/core/component/button/OudsButton.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.component.button

import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.orange.ouds.core.component.icon.OudsIcon

@Composable
internal fun OudsIconButton(
onClick: () -> Unit,
graphicsObject: Any,
contentDescription: String,
modifier: Modifier = Modifier,
enabled: Boolean = true,
tint: Color = OudsIconButtonDefaults.tint,
) {
IconButton(onClick = onClick, modifier = modifier, enabled = enabled) {
OudsIcon(graphicsObject = graphicsObject, contentDescription = contentDescription, tint = tint, enabled = enabled)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.component.button

import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

internal object OudsIconButtonDefaults {

val tint: Color
@Composable
get() = LocalContentColor.current
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.component.content

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import com.orange.ouds.foundation.extensions.asOrNull
import com.orange.ouds.foundation.extensions.orElse


internal val localExtraParametersByClass =
mutableMapOf<Class<out OudsComponentContent.ExtraParameters>, ProvidableCompositionLocal<out OudsComponentContent.ExtraParameters>>()

internal fun <T> getLocalExtraParameters(clazz: Class<T>): ProvidableCompositionLocal<T> where T : OudsComponentContent.ExtraParameters {
return localExtraParametersByClass[clazz]?.asOrNull<ProvidableCompositionLocal<T>>().orElse {
staticCompositionLocalOf<T> { error("CompositionLocal LocalExtraParameters for class ${clazz.name} not present") }.also { compositionLocal ->
localExtraParametersByClass[clazz] = compositionLocal
}
}
}

/**
* The content of a component.
*
* Subclasses of [OudsComponentContent] should be used instead of composable methods when passing parameters to components.
* This prevents using generic composable methods that can encapsulate any kind of views and thus helps developers to follow UI guidelines more easily.
* This also allows to group parameters that are related to the same content inside a component.
* For instance it is possible to create an `Icon` subclass to replace both `icon: @Composable () -> Unit` and `onIconClick: () -> Unit` parameters with a single `icon: Icon` parameter.
*
* @param extraParametersClass The extra parameters class.
* @param T The type of extra parameters.
*/
abstract class OudsComponentContent<T> internal constructor(private val extraParametersClass: Class<T>) where T : OudsComponentContent.ExtraParameters {

/**
* Extra parameters that can be passed to the `Content` method when other parameters than those provided by the user are needed to layout the component.
*/
abstract class ExtraParameters

/**
* The extra parameters.
*/
protected val extraParameters: T
@Composable
get() = getLocalExtraParameters(extraParametersClass).current

/**
* The Jetpack Compose UI for this component content.
*
* Calls `Content(Modifier)` with the default `Modifier`.
*/
@Composable
internal fun Content() = Content(modifier = Modifier)

/**
* The Jetpack Compose UI for this component content.
*
* Calls `Content(Modifier, T)` with the default `Modifier`.
*
* @param extraParameters The extra parameters for this content.
*/
@Composable
internal fun Content(extraParameters: T) = Content(modifier = Modifier, extraParameters = extraParameters)

/**
* The Jetpack Compose UI for this component content.
*
* @param modifier The modifier for this content.
* @param extraParameters The extra parameters for this content.
*/
@Composable
internal fun Content(modifier: Modifier, extraParameters: T) {
CompositionLocalProvider(getLocalExtraParameters(extraParametersClass) provides extraParameters) {
Content(modifier = modifier)
}
}

/**
* The Jetpack Compose UI for this component content.
* Subclasses must implement this method to provide content.
*
* @param modifier The modifier for this content.
*/
@Composable
internal abstract fun Content(modifier: Modifier)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.component.content

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
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 com.orange.ouds.core.component.button.OudsIconButton
import com.orange.ouds.core.component.icon.OudsIcon
import com.orange.ouds.core.component.icon.OudsIconDefaults
import com.orange.ouds.foundation.extensions.orElse

/**
* An icon in a component.
*/
abstract class OudsComponentIcon<T> protected constructor(
extraParametersClass: Class<T>,
private val graphicsObject: Any,
private val contentDescription: String,
private var enabled: Boolean = true,
private val onClick: (() -> Unit)? = null,
) : OudsComponentContent<T>(extraParametersClass) where T : OudsComponentContent.ExtraParameters {

val painter: Painter? = graphicsObject as? Painter
val imageVector: ImageVector? = graphicsObject as? ImageVector
val bitmap: ImageBitmap? = graphicsObject as? ImageBitmap

protected open val tint: Color?
@Composable
get() = null

protected constructor(
extraParametersClass: Class<T>,
painter: Painter,
contentDescription: String,
enabled: Boolean = true,
onClick: (() -> Unit)? = null,
) : this(extraParametersClass, painter as Any, contentDescription, enabled, onClick)

protected constructor(
extraParametersClass: Class<T>,
imageVector: ImageVector,
contentDescription: String,
enabled: Boolean = true,
onClick: (() -> Unit)? = null
) : this(extraParametersClass, imageVector as Any, contentDescription, enabled, onClick)

protected constructor(
extraParametersClass: Class<T>,
bitmap: ImageBitmap,
contentDescription: String,
enabled: Boolean = true,
onClick: (() -> Unit)? = null
) : this(extraParametersClass, bitmap as Any, contentDescription, enabled, onClick)

@Composable
override fun Content(modifier: Modifier) {
val tint = tint.orElse { OudsIconDefaults.tint }
onClick?.let { onClick ->
OudsIconButton(
onClick = onClick,
graphicsObject = graphicsObject,
contentDescription = contentDescription,
tint = tint,
modifier = modifier,
enabled = enabled
)
}.orElse {
OudsIcon(
graphicsObject = graphicsObject,
contentDescription = contentDescription,
modifier = modifier,
tint = tint,
enabled = enabled
)
}
}
}
39 changes: 39 additions & 0 deletions core/src/main/java/com/orange/ouds/core/component/icon/OudsIcon.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.component.icon

import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
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 com.orange.ouds.core.extensions.enabled

@Composable
internal fun OudsIcon(
graphicsObject: Any,
contentDescription: String,
modifier: Modifier = Modifier,
tint: Color = OudsIconDefaults.tint,
enabled: Boolean = true,
) {
val iconTint = tint.enabled(enabled = enabled)
when (graphicsObject) {
is Painter -> Icon(painter = graphicsObject, contentDescription = contentDescription, modifier = modifier, tint = iconTint)
is ImageVector -> Icon(imageVector = graphicsObject, contentDescription = contentDescription, modifier = modifier, tint = iconTint)
is ImageBitmap -> Icon(bitmap = graphicsObject, contentDescription = contentDescription, modifier = modifier, tint = iconTint)
else -> {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.component.icon

import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

internal object OudsIconDefaults {

val tint: Color
@Composable
get() = LocalContentColor.current
}
19 changes: 19 additions & 0 deletions core/src/main/java/com/orange/ouds/core/extensions/ColorExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.extensions

import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

@Composable
internal fun Color.enabled(enabled: Boolean) = if (enabled) this else copy(alpha = 0.38f)
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

package com.orange.ouds.core.extensions

import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember

internal enum class InteractionState {
None, Focused, Hovered, Pressed
}

@Composable
internal fun InteractionSource.collectInteractionStateAsState(): State<InteractionState> {
val isFocused by collectIsFocusedAsState()
val isHovered by collectIsHoveredAsState()
val isPressed by collectIsPressedAsState()

return remember {
derivedStateOf {
when {
isFocused -> InteractionState.Focused
isHovered -> InteractionState.Hovered
isPressed -> InteractionState.Pressed
else -> InteractionState.None
}
}
}
}
Loading

0 comments on commit b799b30

Please sign in to comment.