Skip to content
Open
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 @@ -49,15 +49,17 @@ internal inline fun <reified T> FunctionCall.Builder.annotatedStringArgument(nam
}

inline fun <reified T> FunctionCall.Builder.iconArgument(
name: String,
name: String?,
@DrawableRes resId: Int,
@StringRes contentDescriptionResId: Int? = null,
tinted: Boolean = true
tinted: Boolean = true,
noinline init: FunctionCall.Builder.() -> Unit = {}
) {
constructorCallArgument<T>(name) {
painterArgument(if (tinted) resId else R.drawable.ic_untinted_square)
contentDescriptionResId?.let { contentDescriptionArgument(it) }
if (!tinted) tintedArgument(tinted)
init()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.orange.ouds.app.R
import com.orange.ouds.app.ui.components.Component
import com.orange.ouds.app.ui.components.colorArgument
import com.orange.ouds.app.ui.components.contentDescriptionArgument
import com.orange.ouds.app.ui.components.iconArgument
import com.orange.ouds.app.ui.components.onClickArgument
import com.orange.ouds.app.ui.components.painterArgument
import com.orange.ouds.app.ui.components.topappbar.TopAppBarDemoState.Companion.ActionIconBadgeCount
Expand All @@ -37,6 +38,7 @@ import com.orange.ouds.app.ui.utilities.composable.CustomizationSwitchItem
import com.orange.ouds.app.ui.utilities.composable.CustomizationTextInput
import com.orange.ouds.app.ui.utilities.composable.DemoScreen
import com.orange.ouds.app.ui.utilities.nestedName
import com.orange.ouds.app.ui.utilities.rememberUntintedIconPainter
import com.orange.ouds.core.component.OudsCenterAlignedTopAppBar
import com.orange.ouds.core.component.OudsLargeTopAppBar
import com.orange.ouds.core.component.OudsMediumTopAppBar
Expand Down Expand Up @@ -102,10 +104,17 @@ private fun TopAppBarDemoBottomSheetContent(state: TopAppBarDemoState) {
CustomizationFilterChips(
applyTopPadding = true,
label = stringResource(R.string.app_components_topAppBar_lastActionIconBadge_tech),
chips = TopAppBarDemoState.ActionIconBadge.entries.map { CustomizationFilterChip(it.name, lastActionIconBadgeFilterChipsEnabled) },
chips = TopAppBarDemoState.ActionIconBadge.entries.map { CustomizationFilterChip(it.name, lastActionIconOptionsEnabled) },
selectedChipIndex = TopAppBarDemoState.ActionIconBadge.entries.indexOf(lastActionIconBadge),
onSelectionChange = { index -> lastActionIconBadge = TopAppBarDemoState.ActionIconBadge.entries[index] },
)
CustomizationFilterChips(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same question as on the "edge-to-edge preview" PR: why don't we use a boolean to be aligned with the API?

applyTopPadding = true,
label = stringResource(R.string.app_components_topAppBar_lastActionIcon_tech),
chips = TopAppBarDemoState.Icon.entries.map { CustomizationFilterChip(stringResource(it.labelRes), lastActionIconOptionsEnabled) },
selectedChipIndex = TopAppBarDemoState.Icon.entries.indexOf(lastActionIcon),
onSelectionChange = { index -> lastActionIcon = TopAppBarDemoState.Icon.entries[index] }
)
CustomizationFilterChips(
applyTopPadding = true,
label = stringResource(R.string.app_components_topAppBar_actionAvatar_tech),
Expand Down Expand Up @@ -157,10 +166,12 @@ private fun TopAppBarDemoContent(state: TopAppBarDemoState) {
val contentDescription = getActionContentDescriptionResId(index)?.let { stringResource(it) }.orEmpty()
when (action) {
TopAppBarDemoState.Action.Icon -> {
val tinted = lastActionIcon == TopAppBarDemoState.Icon.Tinted || index != lastActionIconIndex
OudsTopAppBarAction.Icon(
painter = painterResource(id = LocalThemeDrawableResources.current.tipsAndTricks),
painter = if (tinted) painterResource(id = themeDrawableResources.tipsAndTricks) else rememberUntintedIconPainter(),
contentDescription = contentDescription,
badge = if (index == lastActionIconIndex) lastTopAppBarActionIconBadge else null,
tinted = tinted,
onClick = {}
)
}
Expand Down Expand Up @@ -258,11 +269,12 @@ private fun Code.Builder.topAppBarDemoCodeSnippet(state: TopAppBarDemoState, the
val contentDescriptionResId = getActionContentDescriptionResId(index)
when (action) {
TopAppBarDemoState.Action.Icon -> {
constructorCallArgument<OudsTopAppBarAction.Icon>(null) {
painterArgument(themeDrawableResources.tipsAndTricks)
if (contentDescriptionResId != null) {
contentDescriptionArgument(contentDescriptionResId)
}
iconArgument<OudsTopAppBarAction.Icon>(
null,
themeDrawableResources.tipsAndTricks,
contentDescriptionResId,
lastActionIcon == TopAppBarDemoState.Icon.Tinted
) {
val lastActionIconIndex = actions.indexOfLast { it == TopAppBarDemoState.Action.Icon }
if (lastActionIconIndex == index && lastActionIconBadge != TopAppBarDemoState.ActionIconBadge.None) {
constructorCallArgument<OudsTopAppBarActionBadge>("badge") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fun rememberTopAppBarDemoState(
title: String = stringResource(id = R.string.app_components_topAppBar_title_label),
actionCount: Int = 2,
lastActionIconBadge: TopAppBarDemoState.ActionIconBadge = TopAppBarDemoState.ActionIconBadge.None,
lastActionIcon: TopAppBarDemoState.Icon = TopAppBarDemoState.Icon.Tinted,
actionAvatar: TopAppBarDemoState.ActionAvatar = TopAppBarDemoState.ActionAvatar.Image,
actionAvatarMonogram: Char = 'A'
) = rememberSaveable(
Expand All @@ -39,11 +40,12 @@ fun rememberTopAppBarDemoState(
title,
actionCount,
lastActionIconBadge,
lastActionIcon,
actionAvatar,
actionAvatarMonogram,
saver = TopAppBarDemoState.Saver
) {
TopAppBarDemoState(size, centerAligned, navigationIcon, title, actionCount, lastActionIconBadge, actionAvatar, actionAvatarMonogram)
TopAppBarDemoState(size, centerAligned, navigationIcon, title, actionCount, lastActionIconBadge, lastActionIcon, actionAvatar, actionAvatarMonogram)
}

class TopAppBarDemoState(
Expand All @@ -53,6 +55,7 @@ class TopAppBarDemoState(
title: String,
actionCount: Int,
lastActionIconBadge: ActionIconBadge,
lastActionIcon: Icon,
actionAvatar: ActionAvatar,
actionAvatarMonogram: Char
) {
Expand All @@ -72,6 +75,7 @@ class TopAppBarDemoState(
title,
actionCount,
lastActionIconBadge,
lastActionIcon,
actionAvatar,
actionAvatarMonogram
)
Expand All @@ -85,8 +89,9 @@ class TopAppBarDemoState(
list[3] as String,
list[4] as Int,
list[5] as ActionIconBadge,
list[6] as ActionAvatar,
list[7] as Char
list[6] as Icon,
list[7] as ActionAvatar,
list[8] as Char
)
}
)
Expand Down Expand Up @@ -117,14 +122,16 @@ class TopAppBarDemoState(

var lastActionIconBadge: ActionIconBadge by mutableStateOf(lastActionIconBadge)

var lastActionIcon: Icon by mutableStateOf(lastActionIcon)

var actionAvatar: ActionAvatar by mutableStateOf(actionAvatar)

var actionAvatarMonogram: Char by mutableStateOf(actionAvatarMonogram)

val centerAlignedSwitchEnabled: Boolean
get() = size == Size.Small

val lastActionIconBadgeFilterChipsEnabled: Boolean
val lastActionIconOptionsEnabled: Boolean
get() = actions.contains(Action.Icon)

val actionAvatarFilterChipsEnabled: Boolean
Expand Down Expand Up @@ -162,4 +169,9 @@ class TopAppBarDemoState(
Icon,
Avatar
}

enum class Icon(@StringRes val labelRes: Int) {
Tinted(R.string.app_components_common_tintedIcon_tech),
Untinted(R.string.app_components_common_untintedIcon_tech)
}
}
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@
<string name="app_components_topAppBar_title_tech" translatable="false">Title</string>
<string name="app_components_topAppBar_actionCount_tech" translatable="false">Action count</string>
<string name="app_components_topAppBar_lastActionIconBadge_tech" translatable="false">Last action icon badge</string>
<string name="app_components_topAppBar_lastActionIcon_tech" translatable="false">Last action icon</string>
<string name="app_components_topAppBar_actionAvatar_tech" translatable="false">Action avatar</string>
<string name="app_components_topAppBar_monogramActionAvatar_tech" translatable="false">Monogram</string>
<string name="app_components_topAppBar_actionAvatarMonogram_tech" translatable="false">Action avatar monogram</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import org.junit.runners.Parameterized


@RunWith(Enclosed::class)
internal class OudsTopAppBarTest() {
internal class OudsTopAppBarTest {

@RunWith(Parameterized::class)
class Default(parameter: Any) : OudsComponentSnapshotTest(
Expand Down Expand Up @@ -76,4 +76,10 @@ internal class OudsTopAppBarTest() {
internal fun data() = OudsPreviewableComponent.TopAppBar.Large.parameters
}
}

class WithUntintedIcon : OudsComponentSnapshotTest(
OudsPreviewableComponent.TopAppBar.WithUntintedIcon,
parameter = null,
OudsComponentTestSuite.theme
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import com.orange.ouds.core.utilities.CheckerboardPainter
import com.orange.ouds.core.utilities.OudsPreview
import com.orange.ouds.core.utilities.OudsPreviewLightDark
import com.orange.ouds.core.utilities.getPreviewTheme
import com.orange.ouds.core.utilities.rememberRainbowHeartPainter
import com.orange.ouds.foundation.utilities.BasicPreviewParameterProvider
import com.orange.ouds.theme.OudsThemeContract

Expand Down Expand Up @@ -104,6 +105,8 @@ import com.orange.ouds.theme.OudsThemeContract
* scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
*
* @sample com.orange.ouds.core.component.samples.OudsTopAppBarSample
*
* @sample com.orange.ouds.core.component.samples.OudsTopAppBarWithUntintedIconSample
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -177,6 +180,8 @@ fun OudsTopAppBar(
* scrolls. See [TopAppBarScrollBehavior.nestedScrollConnection].
*
* @sample com.orange.ouds.core.component.samples.OudsCenterAlignedTopAppBarSample
*
* @sample com.orange.ouds.core.component.samples.OudsTopAppBarWithUntintedIconSample
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -260,6 +265,8 @@ fun OudsCenterAlignedTopAppBar(
* [collapsedHeight]
*
* @sample com.orange.ouds.core.component.samples.OudsMediumTopAppBarSample
*
* @sample com.orange.ouds.core.component.samples.OudsTopAppBarWithUntintedIconSample
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -345,6 +352,8 @@ fun OudsMediumTopAppBar(
* [collapsedHeight]
*
* @sample com.orange.ouds.core.component.samples.OudsLargeTopAppBarSample
*
* @sample com.orange.ouds.core.component.samples.OudsTopAppBarWithUntintedIconSample
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -515,6 +524,7 @@ sealed interface OudsTopAppBarAction : OudsPolymorphicComponentContent {
graphicsObject: Any,
contentDescription: String,
badge: OudsTopAppBarActionBadge?,
override val tinted: Boolean,
onClick: () -> Unit
) : OudsTopAppBarAction, OudsComponentIcon<Nothing, Icon>(Nothing::class.java, { graphicsObject }, { contentDescription }, onClick) {

Expand All @@ -535,44 +545,59 @@ sealed interface OudsTopAppBarAction : OudsPolymorphicComponentContent {
* @param painter Painter of the icon.
* @param contentDescription The content description associated with this [OudsTopAppBarAction.Icon].
* @param badge Optional badge displayed on the icon.
* @param tinted Controls whether the icon should be tinted with the theme color. Defaults to `true`.
* When set to `false`, the icon is displayed with its original colors (e.g., for multi-color icons).
* Note that untinted icons must ensure sufficient contrast with the background for accessibility reasons.
* @param onClick Callback invoked when the icon is clicked.
*/
@JvmOverloads
constructor(
painter: Painter,
contentDescription: String,
badge: OudsTopAppBarActionBadge? = null,
tinted: Boolean = true,
onClick: () -> Unit
) : this(painter as Any, contentDescription, badge, onClick)
) : this(painter as Any, contentDescription, badge, tinted, onClick)

/**
* Creates an instance of [OudsTopAppBarAction.Icon].
*
* @param imageVector Image vector of the icon.
* @param contentDescription The content description associated with this [OudsTopAppBarAction.Icon].
* @param badge Optional badge displayed on the icon.
* @param tinted Controls whether the icon should be tinted with the theme color. Defaults to `true`.
* When set to `false`, the icon is displayed with its original colors (e.g., for multi-color icons).
* Note that untinted icons must ensure sufficient contrast with the background for accessibility reasons.
* @param onClick Callback invoked when the icon is clicked.
*/
@JvmOverloads
constructor(
imageVector: ImageVector,
contentDescription: String,
badge: OudsTopAppBarActionBadge? = null,
tinted: Boolean = true,
onClick: () -> Unit
) : this(imageVector as Any, contentDescription, badge, onClick)
) : this(imageVector as Any, contentDescription, badge, tinted, onClick)

/**
* Creates an instance of [OudsTopAppBarAction.Icon].
*
* @param bitmap Image bitmap of the icon.
* @param contentDescription The content description associated with this [OudsTopAppBarAction.Icon].
* @param badge Optional badge displayed on the icon.
* @param tinted Controls whether the icon should be tinted with the theme color. Defaults to `true`.
* When set to `false`, the icon is displayed with its original colors (e.g., for multi-color icons).
* Note that untinted icons must ensure sufficient contrast with the background for accessibility reasons.
* @param onClick Callback invoked when the icon is clicked.
*/
@JvmOverloads
constructor(
bitmap: ImageBitmap,
contentDescription: String,
badge: OudsTopAppBarActionBadge? = null,
tinted: Boolean = true,
onClick: () -> Unit
) : this(bitmap as Any, contentDescription, badge, onClick)
) : this(bitmap as Any, contentDescription, badge, tinted, onClick)
}

/**
Expand Down Expand Up @@ -769,13 +794,28 @@ internal fun PreviewOudsLargeTopAppBar(
}
}

@OudsPreview
@Composable
@Suppress("PreviewShouldNotBeCalledRecursively")
private fun PreviewOudsTopAppBarWithUntintedIcon() = PreviewOudsTopAppBarWithUntintedIcon(getPreviewTheme())

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun PreviewOudsTopAppBarWithUntintedIcon(theme: OudsThemeContract) = OudsPreview(theme = theme) {
OudsTopAppBar(
title = "Title",
navigationIcon = OudsTopAppBarNavigationIcon.Back(onClick = {}),
actions = listOf(OudsTopAppBarAction.Icon(painter = rememberRainbowHeartPainter(), contentDescription = "", tinted = false, onClick = {}))
)
}

internal data class OudsTopAppBarPreviewParameter(
val title: String = "Title",
val navigationIcon: OudsTopAppBarNavigationIcon? = null,
val actions: List<OudsTopAppBarAction> = emptyList()
)

internal class OudsTopAppBarPreviewParameterProvider() : BasicPreviewParameterProvider<OudsTopAppBarPreviewParameter>(*previewParameterValues.toTypedArray())
internal class OudsTopAppBarPreviewParameterProvider : BasicPreviewParameterProvider<OudsTopAppBarPreviewParameter>(*previewParameterValues.toTypedArray())

private val previewParameterValues: List<OudsTopAppBarPreviewParameter>
get() = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.orange.ouds.core.component.OudsTopAppBar
import com.orange.ouds.core.component.OudsTopAppBarAction
import com.orange.ouds.core.component.OudsTopAppBarNavigationIcon
import com.orange.ouds.core.utilities.OudsPreview
import com.orange.ouds.core.utilities.rememberRainbowHeartPainter

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -78,6 +79,23 @@ internal fun OudsLargeTopAppBarSample() {
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun OudsTopAppBarWithUntintedIconSample() {
OudsTopAppBar(
title = "Title",
navigationIcon = OudsTopAppBarNavigationIcon.Back {},
actions = listOf(
OudsTopAppBarAction.Icon(
painter = rememberRainbowHeartPainter(),
contentDescription = "",
tinted = false,
onClick = {}
)
)
)
}

@PreviewLightDark
@Composable
private fun PreviewOudsTopAppBarSample() = OudsPreview {
Expand All @@ -101,3 +119,9 @@ private fun PreviewOudsMediumTopAppBarSample() = OudsPreview {
private fun PreviewOudsLargeTopAppBarSample() = OudsPreview {
OudsLargeTopAppBarSample()
}

@PreviewLightDark
@Composable
private fun PreviewOudsTopAppBarWithUntintedIconSample() = OudsPreview {
OudsTopAppBarWithUntintedIconSample()
}
Loading