From 5f1b1c7a5b2adfbd243f1a96f6b5e60040a959c2 Mon Sep 17 00:00:00 2001
From: Florent Maitre <florent.maitre@orange.com>
Date: Thu, 7 Sep 2023 15:53:22 +0200
Subject: [PATCH 1/5] [#597] Update OdsHorizontalCard, OdsSmallCard,
 OdsVerticalHeaderFirstCard and OdsVerticalImageFirstCard APIs

---
 .../ods/app/ui/components/ComponentsScreen.kt |  16 +-
 .../cards/CardCustomizationState.kt           |  22 +--
 .../app/ui/components/cards/CardHorizontal.kt |  56 +++---
 .../ods/app/ui/components/cards/CardSmall.kt  |  21 ++-
 .../cards/CardVerticalHeaderFirst.kt          |  49 ++++--
 .../cards/CardVerticalImageFirst.kt           |  48 +++--
 .../app/ui/components/cards/ComponentCard.kt  |  10 +-
 .../ods/app/ui/guidelines/GuidelinesScreen.kt |  16 +-
 .../composable/CodeImplementation.kt          |  12 +-
 changelog.md                                  |   6 +
 docs/components/Cards.md                      |  83 +++++----
 .../appbar/top/OdsTopAppBarsCommon.kt         |  12 +-
 .../ods/compose/component/banner/OdsBanner.kt |  26 ++-
 .../bottomnavigation/OdsBottomNavigation.kt   |   6 +-
 .../component/button/OdsButtonsCommon.kt      |  12 +-
 .../button/OdsIconToggleButtonsRow.kt         |   6 +-
 .../ods/compose/component/card/OdsCard.kt     |  31 ----
 .../compose/component/card/OdsCardsCommon.kt  | 164 ++++++++++++++++++
 .../component/card/OdsHorizontalCard.kt       | 119 +++++--------
 .../compose/component/card/OdsSmallCard.kt    |  35 +---
 .../card/OdsVerticalHeaderFirstCard.kt        |  80 +++------
 .../card/OdsVerticalImageFirstCard.kt         |  70 ++------
 .../content/OdsComponentCircleImage.kt        |  62 +++++++
 .../component/content/OdsComponentIcon.kt     |   2 +-
 .../component/content/OdsComponentImage.kt    |  35 +++-
 25 files changed, 566 insertions(+), 433 deletions(-)
 delete mode 100644 lib/src/main/java/com/orange/ods/compose/component/card/OdsCard.kt
 create mode 100644 lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt
 create mode 100644 lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt

diff --git a/app/src/main/java/com/orange/ods/app/ui/components/ComponentsScreen.kt b/app/src/main/java/com/orange/ods/app/ui/components/ComponentsScreen.kt
index 019b92276..8b2fcf4e1 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/ComponentsScreen.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/ComponentsScreen.kt
@@ -30,6 +30,7 @@ import androidx.compose.ui.res.stringResource
 import com.orange.ods.app.R
 import com.orange.ods.app.ui.LocalMainTopAppBarManager
 import com.orange.ods.app.ui.utilities.DrawableManager
+import com.orange.ods.compose.component.card.OdsCardImage
 import com.orange.ods.compose.component.card.OdsSmallCard
 import com.orange.ods.extension.orElse
 
@@ -67,12 +68,13 @@ private fun RowScope.ComponentCard(component: Component, onComponentClick: (Long
     OdsSmallCard(
         modifier = Modifier.weight(0.5f),
         title = stringResource(id = component.titleRes),
-        image = painterResource(id = smallImageResId.orElse { imageResId }),
-        imageBackgroundColor = Color(Component.ImageBackgroundColor),
-        imageContentScale = ContentScale.Fit,
-        imageAlignment = component.imageAlignment,
-        onCardClick = {
-            onComponentClick(component.id)
-        },
+        image = OdsCardImage(
+            painterResource(id = smallImageResId.orElse { imageResId }),
+            "",
+            component.imageAlignment,
+            ContentScale.Fit,
+            Color(Component.ImageBackgroundColor)
+        ),
+        onClick = { onComponentClick(component.id) },
     )
 }
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardCustomizationState.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardCustomizationState.kt
index e0b8c0684..e319f1032 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardCustomizationState.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardCustomizationState.kt
@@ -23,12 +23,12 @@ fun rememberCardCustomizationState(
     thumbnailChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(true) },
     textChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(true) },
     subtitleChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(true) },
-    actionButtonCount: MutableState<Int> = rememberSaveable { mutableStateOf(CardCustomizationState.MinActionButtonCount) },
+    buttonCount: MutableState<Int> = rememberSaveable { mutableStateOf(CardCustomizationState.MinButtonCount) },
     dividerChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(true) },
     imagePosition: MutableState<OdsHorizontalCardImagePosition> = rememberSaveable { mutableStateOf(OdsHorizontalCardImagePosition.Start) }
 ) =
-    remember(clickable, thumbnailChecked, textChecked, subtitleChecked, actionButtonCount, dividerChecked, imagePosition) {
-        CardCustomizationState(clickable, thumbnailChecked, textChecked, subtitleChecked, actionButtonCount, dividerChecked, imagePosition)
+    remember(clickable, thumbnailChecked, textChecked, subtitleChecked, buttonCount, dividerChecked, imagePosition) {
+        CardCustomizationState(clickable, thumbnailChecked, textChecked, subtitleChecked, buttonCount, dividerChecked, imagePosition)
     }
 
 class CardCustomizationState(
@@ -36,14 +36,14 @@ class CardCustomizationState(
     val thumbnailChecked: MutableState<Boolean>,
     val textChecked: MutableState<Boolean>,
     val subtitleChecked: MutableState<Boolean>,
-    val actionButtonCount: MutableState<Int>,
+    val buttonCount: MutableState<Int>,
     val dividerChecked: MutableState<Boolean>,
     val imagePosition: MutableState<OdsHorizontalCardImagePosition>
 ) {
 
     companion object {
-        const val MinActionButtonCount = 0
-        const val MaxActionButtonCount = 2
+        const val MinButtonCount = 0
+        const val MaxButtonCount = 2
     }
 
     val isClickable
@@ -58,12 +58,12 @@ class CardCustomizationState(
     val hasSubtitle
         get() = subtitleChecked.value
 
-    val hasButton1
-        get() = actionButtonCount.value > 0
+    val hasFirstButton
+        get() = buttonCount.value > 0
 
-    val hasButton2
-        get() = actionButtonCount.value > 1
+    val hasSecondButton
+        get() = buttonCount.value > 1
 
     val hasDivider
-        get() = if (!hasButton1) false else dividerChecked.value
+        get() = if (!hasFirstButton) false else dividerChecked.value
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt
index 4112debd3..1ab38d816 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt
@@ -31,6 +31,8 @@ import com.orange.ods.app.ui.utilities.DrawableManager
 import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
 import com.orange.ods.app.ui.utilities.composable.FunctionCallCode
 import com.orange.ods.compose.OdsComposable
+import com.orange.ods.compose.component.card.OdsCardButton
+import com.orange.ods.compose.component.card.OdsCardImage
 import com.orange.ods.compose.component.card.OdsHorizontalCard
 
 @Composable
@@ -38,7 +40,7 @@ fun CardHorizontal(customizationState: CardCustomizationState) {
     val context = LocalContext.current
     val recipes = LocalRecipes.current
     val recipe = rememberSaveable { recipes.filter { it.description.isNotBlank() }.random() }
-    
+
     with(customizationState) {
         Column(
             modifier = Modifier
@@ -46,28 +48,29 @@ fun CardHorizontal(customizationState: CardCustomizationState) {
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
                 .verticalScroll(state = rememberScrollState()),
         ) {
-            val button1Text = stringResource(id = R.string.component_element_first_button)
-            val button2Text = stringResource(id = R.string.component_element_second_button)
+            val firstButtonText = stringResource(id = R.string.component_element_first_button)
+            val secondButtonText = stringResource(id = R.string.component_element_second_button)
             val cardText = stringResource(id = R.string.component_card_element_card)
 
             OdsHorizontalCard(
                 title = recipe.title,
-                image = rememberAsyncImagePainter(
-                    model = recipe.imageUrl,
-                    placeholder = painterResource(id = DrawableManager.getPlaceholderResId()),
-                    error = painterResource(id = DrawableManager.getPlaceholderResId(error = true))
+                image = OdsCardImage(
+                    rememberAsyncImagePainter(
+                        model = recipe.imageUrl,
+                        placeholder = painterResource(id = DrawableManager.getPlaceholderResId()),
+                        error = painterResource(id = DrawableManager.getPlaceholderResId(error = true))
+                    ),
+                    ""
                 ),
                 subtitle = if (hasSubtitle) recipe.subtitle else null,
                 text = if (hasText) recipe.description else null,
-                onCardClick = if (isClickable) {
+                onClick = if (isClickable) {
                     { clickOnElement(context, cardText) }
                 } else null,
-                button1Text = if (hasButton1) button1Text else null,
-                onButton1Click = { clickOnElement(context, button1Text) },
-                button2Text = if (hasButton2) button2Text else null,
-                onButton2Click = { clickOnElement(context, button2Text) },
+                firstButton = if (hasFirstButton) OdsCardButton(firstButtonText) { clickOnElement(context, firstButtonText) } else null,
+                secondButton = if (hasSecondButton) OdsCardButton(secondButtonText) { clickOnElement(context, secondButtonText) } else null,
                 imagePosition = imagePosition.value,
-                dividerEnabled = hasDivider
+                divider = hasDivider
             )
 
             Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
@@ -77,21 +80,28 @@ fun CardHorizontal(customizationState: CardCustomizationState) {
                     name = OdsComposable.OdsHorizontalCard.name,
                     exhaustiveParameters = false,
                     parameters = {
-                        simple("imagePosition", imagePosition.value.name)
                         title(recipe.title)
-                        image()
+                        classInstance("image", OdsCardImage::class.java) {
+                            painter()
+                            contentDescription("")
+                        }
                         if (hasSubtitle) subtitle(recipe.subtitle)
                         if (hasText) cardText()
-                        if (isClickable) onCardClick()
-                        if (hasButton1) {
-                            button1Text(button1Text)
-                            onButton1Click()
+                        if (isClickable) onClick()
+                        if (hasFirstButton) {
+                            classInstance("firstButton", OdsCardButton::class.java) {
+                                text(firstButtonText)
+                                onClick()
+                            }
                         }
-                        if (hasButton2) {
-                            button2Text(button2Text)
-                            onButton2Click()
+                        if (hasSecondButton) {
+                            classInstance("secondButton", OdsCardButton::class.java) {
+                                text(secondButtonText)
+                                onClick()
+                            }
                         }
-                        if (!hasDivider && (hasButton1 || hasButton2)) stringRepresentation("dividerEnabled", hasDivider)
+                        simple("imagePosition", imagePosition.value.name)
+                        if (!hasDivider && (hasFirstButton || hasSecondButton)) stringRepresentation("divider", hasDivider)
                     }
                 )
             }
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt
index 44129eb7b..f525f3db5 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt
@@ -34,6 +34,7 @@ import com.orange.ods.app.ui.utilities.DrawableManager
 import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
 import com.orange.ods.app.ui.utilities.composable.FunctionCallCode
 import com.orange.ods.compose.OdsComposable
+import com.orange.ods.compose.component.card.OdsCardImage
 import com.orange.ods.compose.component.card.OdsSmallCard
 
 @Composable
@@ -58,14 +59,17 @@ fun CardSmall(customizationState: CardCustomizationState) {
 
                 OdsSmallCard(
                     modifier = Modifier.weight(0.5f),
-                    image = rememberAsyncImagePainter(
-                        model = recipe.imageUrl,
-                        placeholder = painterResource(id = DrawableManager.getPlaceholderResId()),
-                        error = painterResource(id = DrawableManager.getPlaceholderResId(error = true))
+                    image = OdsCardImage(
+                        rememberAsyncImagePainter(
+                            model = recipe.imageUrl,
+                            placeholder = painterResource(id = DrawableManager.getPlaceholderResId()),
+                            error = painterResource(id = DrawableManager.getPlaceholderResId(error = true)),
+                        ),
+                        ""
                     ),
                     title = recipe.title,
                     subtitle = if (subtitleChecked.value) recipe.subtitle else null,
-                    onCardClick = if (isClickable) {
+                    onClick = if (isClickable) {
                         { clickOnElement(context, cardText) }
                     } else null
                 )
@@ -80,9 +84,12 @@ fun CardSmall(customizationState: CardCustomizationState) {
                     exhaustiveParameters = false,
                     parameters = {
                         title(recipe.title)
-                        image()
+                        classInstance("image", OdsCardImage::class.java) {
+                            painter()
+                            contentDescription("")
+                        }
                         if (hasSubtitle) subtitle(recipe.subtitle)
-                        if (isClickable) onCardClick()
+                        if (isClickable) onClick()
                     })
             }
         }
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt
index d2e0ac107..56ece9cb3 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt
@@ -33,6 +33,9 @@ import com.orange.ods.app.ui.utilities.DrawableManager
 import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
 import com.orange.ods.app.ui.utilities.composable.FunctionCallCode
 import com.orange.ods.compose.OdsComposable
+import com.orange.ods.compose.component.card.OdsCardButton
+import com.orange.ods.compose.component.card.OdsCardImage
+import com.orange.ods.compose.component.card.OdsCardThumbnail
 import com.orange.ods.compose.component.card.OdsVerticalHeaderFirstCard
 
 @Composable
@@ -48,8 +51,8 @@ fun CardVerticalHeaderFirst(customizationState: CardCustomizationState) {
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
                 .verticalScroll(state = rememberScrollState()),
         ) {
-            val button1Text = stringResource(id = R.string.component_element_first_button)
-            val button2Text = stringResource(id = R.string.component_element_second_button)
+            val firstButtonText = stringResource(id = R.string.component_element_first_button)
+            val secondButtonText = stringResource(id = R.string.component_element_second_button)
             val cardText = stringResource(id = R.string.component_card_element_card)
             val imagePainter = rememberAsyncImagePainter(
                 model = ImageRequest.Builder(context)
@@ -62,17 +65,15 @@ fun CardVerticalHeaderFirst(customizationState: CardCustomizationState) {
 
             OdsVerticalHeaderFirstCard(
                 title = recipe.title,
-                image = imagePainter,
-                thumbnail = if (hasThumbnail) imagePainter else null,
+                image = OdsCardImage(imagePainter, ""),
+                thumbnail = if (hasThumbnail) OdsCardThumbnail(imagePainter, "") else null,
                 subtitle = if (hasSubtitle) recipe.subtitle else null,
                 text = if (hasText) recipe.description else null,
-                onCardClick = if (isClickable) {
+                onClick = if (isClickable) {
                     { clickOnElement(context, cardText) }
                 } else null,
-                button1Text = if (hasButton1) button1Text else null,
-                onButton1Click = { clickOnElement(context, button1Text) },
-                button2Text = if (hasButton2) button2Text else null,
-                onButton2Click = { clickOnElement(context, button2Text) }
+                firstButton = if (hasFirstButton) OdsCardButton(firstButtonText) { clickOnElement(context, firstButtonText) } else null,
+                secondButton = if (hasSecondButton) OdsCardButton(secondButtonText) { clickOnElement(context, secondButtonText) } else null,
             )
 
             Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
@@ -83,18 +84,30 @@ fun CardVerticalHeaderFirst(customizationState: CardCustomizationState) {
                     exhaustiveParameters = false,
                     parameters = {
                         title(recipe.title)
-                        image()
-                        if (hasThumbnail) simple("thumbnail", "<thumbnail painter>")
+                        classInstance("image", OdsCardImage::class.java) {
+                            painter()
+                            contentDescription("")
+                        }
+                        if (hasThumbnail) {
+                            classInstance("thumbnail", OdsCardThumbnail::class.java) {
+                                painter()
+                                contentDescription("")
+                            }
+                        }
                         if (hasSubtitle) subtitle(recipe.subtitle)
                         if (hasText) cardText()
-                        if (isClickable) onCardClick()
-                        if (hasButton1) {
-                            button1Text(button1Text)
-                            onButton1Click()
+                        if (isClickable) onClick()
+                        if (hasFirstButton) {
+                            classInstance("firstButton", OdsCardButton::class.java) {
+                                text(firstButtonText)
+                                onClick()
+                            }
                         }
-                        if (hasButton2) {
-                            button2Text(button2Text)
-                            onButton2Click()
+                        if (hasSecondButton) {
+                            classInstance("secondButton", OdsCardButton::class.java) {
+                                text(secondButtonText)
+                                onClick()
+                            }
                         }
                     }
                 )
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt
index 32a2f249f..c770806e4 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt
@@ -31,6 +31,8 @@ import com.orange.ods.app.ui.utilities.DrawableManager
 import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
 import com.orange.ods.app.ui.utilities.composable.FunctionCallCode
 import com.orange.ods.compose.OdsComposable
+import com.orange.ods.compose.component.card.OdsCardButton
+import com.orange.ods.compose.component.card.OdsCardImage
 import com.orange.ods.compose.component.card.OdsVerticalImageFirstCard
 
 @Composable
@@ -46,26 +48,27 @@ fun CardVerticalImageFirst(customizationState: CardCustomizationState) {
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
                 .verticalScroll(state = rememberScrollState()),
         ) {
-            val button1Text = stringResource(id = R.string.component_element_first_button)
-            val button2Text = stringResource(id = R.string.component_element_second_button)
+            val firstButtonText = stringResource(id = R.string.component_element_first_button)
+            val secondButtonText = stringResource(id = R.string.component_element_second_button)
             val cardText = stringResource(id = R.string.component_card_element_card)
 
             OdsVerticalImageFirstCard(
                 title = recipe.title,
-                image = rememberAsyncImagePainter(
-                    model = recipe.imageUrl,
-                    placeholder = painterResource(id = DrawableManager.getPlaceholderResId()),
-                    error = painterResource(id = DrawableManager.getPlaceholderResId(error = true))
+                image = OdsCardImage(
+                    rememberAsyncImagePainter(
+                        model = recipe.imageUrl,
+                        placeholder = painterResource(id = DrawableManager.getPlaceholderResId()),
+                        error = painterResource(id = DrawableManager.getPlaceholderResId(error = true))
+                    ),
+                    ""
                 ),
                 subtitle = if (hasSubtitle) recipe.subtitle else null,
                 text = if (hasText) recipe.description else null,
-                onCardClick = if (isClickable) {
+                onClick = if (isClickable) {
                     { clickOnElement(context, cardText) }
                 } else null,
-                button1Text = if (hasButton1) button1Text else null,
-                onButton1Click = { clickOnElement(context, button1Text) },
-                button2Text = if (hasButton2) button2Text else null,
-                onButton2Click = { clickOnElement(context, button2Text) }
+                firstButton = if (hasFirstButton) OdsCardButton(firstButtonText) { clickOnElement(context, firstButtonText) } else null,
+                secondButton = if (hasSecondButton) OdsCardButton(secondButtonText) { clickOnElement(context, secondButtonText) } else null,
             )
 
             Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
@@ -76,17 +79,24 @@ fun CardVerticalImageFirst(customizationState: CardCustomizationState) {
                     exhaustiveParameters = false,
                     parameters = {
                         title(recipe.title)
-                        image()
+                        classInstance("image", OdsCardImage::class.java) {
+                            painter()
+                            contentDescription("")
+                        }
                         if (hasSubtitle) subtitle(recipe.subtitle)
                         if (hasText) cardText()
-                        if (isClickable) onCardClick()
-                        if (hasButton1) {
-                            button1Text(button1Text)
-                            onButton1Click()
+                        if (isClickable) onClick()
+                        if (hasFirstButton) {
+                            classInstance("firstButton", OdsCardButton::class.java) {
+                                text(firstButtonText)
+                                onClick()
+                            }
                         }
-                        if (hasButton2) {
-                            button2Text(button2Text)
-                            onButton2Click()
+                        if (hasSecondButton) {
+                            classInstance("secondButton", OdsCardButton::class.java) {
+                                text(secondButtonText)
+                                onClick()
+                            }
                         }
                     }
                 )
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/ComponentCard.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/ComponentCard.kt
index a7925f5f5..57fdb17e6 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/ComponentCard.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/ComponentCard.kt
@@ -69,19 +69,19 @@ fun ComponentCard(variant: Variant) {
                     )
                     ComponentCountRow(
                         title = stringResource(id = R.string.component_card_action_button_count),
-                        count = actionButtonCount,
+                        count = buttonCount,
                         minusIconContentDescription = stringResource(id = R.string.component_remove_action_button),
                         plusIconContentDescription = stringResource(id = R.string.component_add_action_button),
                         modifier = Modifier.padding(start = dimensionResource(id = com.orange.ods.R.dimen.screen_horizontal_margin)),
-                        minCount = CardCustomizationState.MinActionButtonCount,
-                        maxCount = CardCustomizationState.MaxActionButtonCount
+                        minCount = CardCustomizationState.MinButtonCount,
+                        maxCount = CardCustomizationState.MaxButtonCount
                     )
                 }
                 if (variant == Variant.CardHorizontal) {
-                    if (!hasButton1) dividerChecked.value = false
+                    if (!hasFirstButton) dividerChecked.value = false
                     OdsListItem(
                         text = stringResource(id = R.string.component_element_divider),
-                        trailing = OdsSwitchTrailing(checked = dividerChecked, enabled = hasButton1)
+                        trailing = OdsSwitchTrailing(checked = dividerChecked, enabled = hasFirstButton)
                     )
                 }
             }) {
diff --git a/app/src/main/java/com/orange/ods/app/ui/guidelines/GuidelinesScreen.kt b/app/src/main/java/com/orange/ods/app/ui/guidelines/GuidelinesScreen.kt
index 66b9096e9..f3a2fcd01 100644
--- a/app/src/main/java/com/orange/ods/app/ui/guidelines/GuidelinesScreen.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/guidelines/GuidelinesScreen.kt
@@ -21,10 +21,11 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
-import com.orange.ods.compose.component.card.OdsVerticalImageFirstCard
 import com.orange.ods.app.R
 import com.orange.ods.app.ui.LocalMainTopAppBarManager
 import com.orange.ods.app.ui.utilities.DrawableManager
+import com.orange.ods.compose.component.card.OdsCardImage
+import com.orange.ods.compose.component.card.OdsVerticalImageFirstCard
 
 @Composable
 fun GuidelinesScreen(onGuidelineClick: (String) -> Unit) {
@@ -41,11 +42,14 @@ fun GuidelinesScreen(onGuidelineClick: (String) -> Unit) {
         Guideline.values().forEach { guideline ->
             OdsVerticalImageFirstCard(
                 title = stringResource(id = guideline.titleRes),
-                image = painterResource(id = DrawableManager.getDrawableResIdForCurrentTheme(resId = guideline.imageRes)),
-                imageContentScale = guideline.imageContentScale,
-                imageBackgroundColor = guideline.imageBackgroundColor,
-                imageAlignment = guideline.imageAlignment,
-                onCardClick = { onGuidelineClick(guideline.route) }
+                image = OdsCardImage(
+                    painterResource(id = DrawableManager.getDrawableResIdForCurrentTheme(resId = guideline.imageRes)),
+                    "",
+                    guideline.imageAlignment,
+                    guideline.imageContentScale,
+                    guideline.imageBackgroundColor
+                ),
+                onClick = { onGuidelineClick(guideline.route) }
             )
         }
     }
diff --git a/app/src/main/java/com/orange/ods/app/ui/utilities/composable/CodeImplementation.kt b/app/src/main/java/com/orange/ods/app/ui/utilities/composable/CodeImplementation.kt
index e4d101d0a..4e8471c61 100644
--- a/app/src/main/java/com/orange/ods/app/ui/utilities/composable/CodeImplementation.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/utilities/composable/CodeImplementation.kt
@@ -94,7 +94,7 @@ private sealed class PredefinedParameter {
     object Icon : SimpleParameter("icon", IconPainterValue)
     object Painter : SimpleParameter("painter", IconPainterValue)
     object Image : SimpleParameter("image", ImagePainterValue)
-    object CardText : SimpleParameter("cardText", CardTextValue)
+    object CardText : SimpleParameter("text", CardTextValue)
     object FillMaxWidth : SimpleParameter("modifier", "Modifier.fillMaxWidth()")
 
     class Enabled(enabled: Boolean) : StringRepresentationParameter<Boolean>("enabled", enabled)
@@ -106,15 +106,10 @@ private sealed class PredefinedParameter {
     class Subtitle(text: String) : StringParameter("subtitle", text)
     class Label(text: String) : StringParameter("label", text)
     class Placeholder(text: String) : StringParameter("placeholder", text)
-    class Button1Text(text: String) : StringParameter("button1Text", text)
-    class Button2Text(text: String) : StringParameter("button2Text", text)
     class ContentDescription(text: String) : StringParameter("contentDescription", text)
 
     object OnClick : LambdaParameter("onClick")
     object OnCheckedChange : LambdaParameter("onCheckedChange")
-    object OnCardClick : LambdaParameter("onCardClick")
-    object OnButton1Click : LambdaParameter("onButton1Click")
-    object OnButton2Click : LambdaParameter("onButton2Click")
 }
 
 @Composable
@@ -305,15 +300,10 @@ class ParametersBuilder {
     fun subtitle(text: String) = add(PredefinedParameter.Subtitle(text))
     fun label(text: String) = add(PredefinedParameter.Label(text))
     fun placeholder(text: String) = add(PredefinedParameter.Placeholder(text))
-    fun button1Text(text: String) = add(PredefinedParameter.Button1Text(text))
-    fun button2Text(text: String) = add(PredefinedParameter.Button2Text(text))
     fun contentDescription(text: String) = add(PredefinedParameter.ContentDescription(text))
 
     fun onClick() = add(PredefinedParameter.OnClick)
     fun onCheckedChange() = add(PredefinedParameter.OnCheckedChange)
-    fun onCardClick() = add(PredefinedParameter.OnCardClick)
-    fun onButton1Click() = add(PredefinedParameter.OnButton1Click)
-    fun onButton2Click() = add(PredefinedParameter.OnButton2Click)
 
     @Composable
     fun Build() = parameters.forEach { it.code() }
diff --git a/changelog.md b/changelog.md
index da285f31c..42e7ee820 100644
--- a/changelog.md
+++ b/changelog.md
@@ -5,6 +5,12 @@ All notable changes done in ODS library will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [Unreleased](https://github.com/Orange-OpenSource/ods-android/compare/0.15.0...develop)
+
+### Changed
+
+- \[Lib\] Update `OdsHorizontalCard`, `OdsSmallCard`, `OdsVerticalHeaderFirstCard` and `OdsVerticalImageFirstCard` APIs ([#597](https://github.com/Orange-OpenSource/ods-android/issues/597))
+
 ## [0.15.0](https://github.com/Orange-OpenSource/ods-android/compare/0.14.0...0.15.0) - 2023-09-12
 
 ### Added
diff --git a/docs/components/Cards.md b/docs/components/Cards.md
index 7833a4956..0b2edea6e 100644
--- a/docs/components/Cards.md
+++ b/docs/components/Cards.md
@@ -53,18 +53,18 @@ In your composable screen you can use `OdsVerticalImageFirstCard` composable:
 ```kotlin
 OdsVerticalImageFirstCard(
     title = "Title",
-    image = painterResource(R.drawable.picture),
-    imageContentDescription = "Picture content description", //Optional
-    imageBackgroundColor = Color(0xff1b1b1b), //Optional
-    imageContentScale = ContentScale.Crop,
-    imageAlignment = Alignment.Center,
+    image = OdsCardImage(
+        painterResource(R.drawable.picture),
+        "Picture content description",
+        Alignment.Center,
+        ContentScale.Crop,
+        Color(0xff1b1b1b) //Optional
+    ),
     subtitle = "Subtitle", //Optional
     text = "Text", //Optional
-    button1Text = "Button1", //Optional
-    button2Text = "Button2", //Optional
-    onCardClick = {  }, //Optional
-    onButton1Click = {  }, //Optional
-    onButton2Click = {  } //Optional
+    firstButton = OdsCardButton("First button") {}, //Optional
+    secondButton = OdsCardButton("Second button") {}, //Optional
+    onClick = {} //Optional
 )
 ```
 
@@ -80,24 +80,27 @@ This is a full width card containing elements arranged vertically with a header
 
 > **Jetpack Compose implementation**
 
-In your composable screen you can use `OdsVerticalHeaderFirstCard`composable:
+In your composable screen you can use `OdsVerticalHeaderFirstCard` composable:
 
 ```kotlin
 OdsVerticalHeaderFirstCard(
     title = "Title",
-    image = painterResource(R.drawable.picture),
-    thumbnail = painterResource(R.drawable.thumbnail), //Optional
+    image = OdsCardImage(
+        painterResource(R.drawable.picture),
+        "Picture content description",
+        Alignment.Center,
+        ContentScale.Crop,
+        Color(0xff1b1b1b) //Optional
+    ),
+    thumbnail = OdsCardThumbnail(
+        painterResource(R.drawable.thumbnail),
+        "Thumbnail content description"
+    ), //Optional
     subtitle = "Subtitle", //Optional
-    imageContentDescription = "Picture content description", //Optional
-    imageBackgroundColor = Color(0xff1b1b1b), //Optional
-    imageContentScale = ContentScale.Crop,
-    imageAlignment = Alignment.Center,
     text = "Text", //Optional
-    button1Text = "Button1", //Optional
-    button2Text = "Button2", //Optional
-    onCardClick = {  }, //Optional
-    onButton1Click = {  }, //Optional
-    onButton2Click = {  } //Optional
+    firstButton = OdsCardButton("First button") {}, //Optional
+    secondButton = OdsCardButton("Second button") {}, //Optional
+    onClick = {} //Optional
 )
 ```
 
@@ -121,15 +124,21 @@ Row(
 ) {
     OdsSmallCard(
         title = "Title",
-        image = painterResource(R.drawable.picture),
+        image = OdsCardImage(
+            painterResource(R.drawable.picture),
+            "Picture content description"
+        ),
         modifier = Modifier.weight(0.5f),
-        onCardClick = {}
+        onClick = {}
     )
     OdsSmallCard(
         title = "Title",
-        image = painterResource(R.drawable.picture),
+        image = OdsCardImage(
+            painterResource(R.drawable.picture),
+            "Picture content description"
+        ),
         modifier = Modifier.weight(0.5f),
-        onCardClick = {}
+        onClick = {}
     )
 }
 ```
@@ -151,20 +160,20 @@ In your screen you can use `OdsHorizontalCard` composable:
 ```kotlin
 OdsHorizontalCard(
     title = "Title",
-    image = painterResource(R.drawable.picture),
-    imageContentDescription = "Picture content description", //Optional
-    imageBackgroundColor = Color(0xff1b1b1b), //Optional
-    imageContentScale = ContentScale.Crop,
-    imageAlignment = Alignment.Center,
+    image = OdsCardImage(
+        painterResource(R.drawable.picture),
+        "Picture content description",
+        Alignment.Center,
+        ContentScale.Crop,
+        Color(0xff1b1b1b) //Optional
+    ),
     subtitle = "Subtitle", //Optional
     text = "Text", //Optional
-    button1Text = "Button1", //Optional
-    button2Text = "Button2", //Optional
+    firstButton = OdsCardButton("First button") {}, //Optional
+    secondButton = OdsCardButton("Second button") {}, //Optional
     imagePosition = OdsHorizontalCardImagePosition.Start,  //Optional. Start by default.
-    dividerEnabled = false, // Optional. True by default.
-    onCardClick = {  }, //Optional
-    onButton1Click = {  }, //Optional
-    onButton2Click = {  } //Optional
+    divider = false, // Optional. True by default.
+    onClick = {} //Optional
 )
 ```
 
diff --git a/lib/src/main/java/com/orange/ods/compose/component/appbar/top/OdsTopAppBarsCommon.kt b/lib/src/main/java/com/orange/ods/compose/component/appbar/top/OdsTopAppBarsCommon.kt
index 5049cce64..4c7082626 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/appbar/top/OdsTopAppBarsCommon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/appbar/top/OdsTopAppBarsCommon.kt
@@ -62,7 +62,7 @@ class OdsTopAppBarNavigationIcon : OdsComponentIcon {
      * @param contentDescription The content description associated to this [OdsTopAppBarNavigationIcon].
      * @param onClick Will be called when the user clicks on the action icon button.
      */
-    constructor(painter: Painter, contentDescription: String, onClick: () -> Unit) : super(painter as Any, contentDescription, onClick = onClick)
+    constructor(painter: Painter, contentDescription: String, onClick: () -> Unit) : super(painter, contentDescription, onClick = onClick)
 
     /**
      * Creates an instance of [OdsTopAppBarNavigationIcon].
@@ -71,7 +71,7 @@ class OdsTopAppBarNavigationIcon : OdsComponentIcon {
      * @param contentDescription The content description associated to this [OdsTopAppBarNavigationIcon].
      * @param onClick Will be called when the user clicks on the action icon button.
      */
-    constructor(imageVector: ImageVector, contentDescription: String, onClick: () -> Unit) : super(imageVector as Any, contentDescription, onClick = onClick)
+    constructor(imageVector: ImageVector, contentDescription: String, onClick: () -> Unit) : super(imageVector, contentDescription, onClick = onClick)
 
     /**
      * Creates an instance of [OdsTopAppBarNavigationIcon].
@@ -80,7 +80,7 @@ class OdsTopAppBarNavigationIcon : OdsComponentIcon {
      * @param contentDescription The content description associated to this [OdsTopAppBarNavigationIcon].
      * @param onClick Will be called when the user clicks on the action icon button.
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String, onClick: () -> Unit) : super(bitmap as Any, contentDescription, onClick = onClick)
+    constructor(bitmap: ImageBitmap, contentDescription: String, onClick: () -> Unit) : super(bitmap, contentDescription, onClick = onClick)
 }
 
 /**
@@ -102,7 +102,7 @@ open class OdsTopAppBarActionButton : OdsComponentIcon {
         contentDescription: String,
         enabled: Boolean = true,
         onClick: () -> Unit
-    ) : super(painter as Any, contentDescription, enabled, onClick)
+    ) : super(painter, contentDescription, enabled, onClick)
 
     /**
      * Creates an instance of [OdsTopAppBarActionButton].
@@ -118,7 +118,7 @@ open class OdsTopAppBarActionButton : OdsComponentIcon {
         contentDescription: String,
         enabled: Boolean = true,
         onClick: () -> Unit
-    ) : super(imageVector as Any, contentDescription, enabled, onClick)
+    ) : super(imageVector, contentDescription, enabled, onClick)
 
     /**
      * Creates an instance of [OdsTopAppBarActionButton].
@@ -134,7 +134,7 @@ open class OdsTopAppBarActionButton : OdsComponentIcon {
         contentDescription: String,
         enabled: Boolean = true,
         onClick: () -> Unit
-    ) : super(bitmap as Any, contentDescription, enabled, onClick)
+    ) : super(bitmap, contentDescription, enabled, onClick)
 
     override val tint: Color?
         @Composable
diff --git a/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt b/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt
index 6bee4f218..08dc3a29f 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt
@@ -15,17 +15,13 @@ import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.ImageBitmap
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.style.TextOverflow
@@ -35,8 +31,8 @@ import com.orange.ods.R
 import com.orange.ods.compose.component.OdsComposable
 import com.orange.ods.compose.component.button.OdsTextButton
 import com.orange.ods.compose.component.button.OdsTextButtonStyle
+import com.orange.ods.compose.component.content.OdsComponentCircleImage
 import com.orange.ods.compose.component.content.OdsComponentContent
-import com.orange.ods.compose.component.content.OdsComponentImage
 import com.orange.ods.compose.component.divider.OdsDivider
 import com.orange.ods.compose.component.utilities.BasicPreviewParameterProvider
 import com.orange.ods.compose.component.utilities.Preview
@@ -78,12 +74,7 @@ fun OdsBanner(
                 )
                 .padding(horizontal = dimensionResource(id = R.dimen.spacing_m))
         ) {
-            image?.Content(
-                modifier = Modifier
-                    .padding(end = dimensionResource(id = R.dimen.spacing_m))
-                    .size(40.dp)
-                    .clip(CircleShape)
-            )
+            image?.Content(modifier = Modifier.padding(end = dimensionResource(id = R.dimen.spacing_m)))
             Row(verticalAlignment = Alignment.CenterVertically) {
                 Text(
                     modifier = Modifier.weight(1f),
@@ -130,7 +121,12 @@ class OdsBannerButton(private val text: String, private val onClick: () -> Unit)
 /**
  * An image in an [OdsBanner].
  */
-class OdsBannerImage : OdsComponentImage {
+class OdsBannerImage : OdsComponentCircleImage {
+
+    private companion object {
+
+        private val CircleSize = 40.dp
+    }
 
     /**
      * Creates an instance of [OdsBannerImage].
@@ -138,7 +134,7 @@ class OdsBannerImage : OdsComponentImage {
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsBannerImage].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription, ContentScale.Crop)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription, CircleSize)
 
     /**
      * Creates an instance of [OdsBannerImage].
@@ -146,7 +142,7 @@ class OdsBannerImage : OdsComponentImage {
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsBannerImage].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription, ContentScale.Crop)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription, CircleSize)
 
     /**
      * Creates an instance of [OdsBannerImage].
@@ -154,7 +150,7 @@ class OdsBannerImage : OdsComponentImage {
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsBannerImage].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription, ContentScale.Crop)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription, CircleSize)
 }
 
 @UiModePreviews.Default
diff --git a/lib/src/main/java/com/orange/ods/compose/component/bottomnavigation/OdsBottomNavigation.kt b/lib/src/main/java/com/orange/ods/compose/component/bottomnavigation/OdsBottomNavigation.kt
index f5d3cfe93..609f7757d 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/bottomnavigation/OdsBottomNavigation.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/bottomnavigation/OdsBottomNavigation.kt
@@ -130,7 +130,7 @@ class OdsBottomNavigationItemIcon : OdsComponentIcon {
      * @param painter Painter of the icon.
      * @param contentDescription The content description associated to this [OdsBottomNavigationItemIcon].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsBottomNavigationItemIcon].
@@ -138,7 +138,7 @@ class OdsBottomNavigationItemIcon : OdsComponentIcon {
      * @param imageVector Image vector of the icon.
      * @param contentDescription The content description associated to this [OdsBottomNavigationItemIcon].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsBottomNavigationItemIcon].
@@ -146,7 +146,7 @@ class OdsBottomNavigationItemIcon : OdsComponentIcon {
      * @param bitmap Image bitmap of the icon.
      * @param contentDescription The content description associated to this [OdsBottomNavigationItemIcon].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 }
 
 @UiModePreviews.Default
diff --git a/lib/src/main/java/com/orange/ods/compose/component/button/OdsButtonsCommon.kt b/lib/src/main/java/com/orange/ods/compose/component/button/OdsButtonsCommon.kt
index 31d51a36f..9df5d8055 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/button/OdsButtonsCommon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/button/OdsButtonsCommon.kt
@@ -34,21 +34,21 @@ class OdsButtonIcon : OdsComponentIcon {
      *
      * @param painter Painter of the icon.
      */
-    constructor(painter: Painter) : super(painter as Any, "")
+    constructor(painter: Painter) : super(painter, "")
 
     /**
      * Creates an instance of [OdsButtonIcon].
      *
      * @param imageVector Image vector of the icon.
      */
-    constructor(imageVector: ImageVector) : super(imageVector as Any, "")
+    constructor(imageVector: ImageVector) : super(imageVector, "")
 
     /**
      * Creates an instance of [OdsButtonIcon].
      *
      * @param bitmap Image bitmap of the icon.
      */
-    constructor(bitmap: ImageBitmap) : super(bitmap as Any, "")
+    constructor(bitmap: ImageBitmap) : super(bitmap, "")
 
     @Composable
     override fun Content(modifier: Modifier) {
@@ -68,7 +68,7 @@ class OdsIconButtonIcon : OdsComponentIcon {
      * @param painter Painter of the icon.
      * @param contentDescription The content description associated to this [OdsIconButtonIcon].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsIconButtonIcon].
@@ -76,7 +76,7 @@ class OdsIconButtonIcon : OdsComponentIcon {
      * @param imageVector Image vector of the icon.
      * @param contentDescription The content description associated to this [OdsIconButtonIcon].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsIconButtonIcon].
@@ -84,7 +84,7 @@ class OdsIconButtonIcon : OdsComponentIcon {
      * @param bitmap Image bitmap of the icon.
      * @param contentDescription The content description associated to this [OdsIconButtonIcon].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 
     override val tint: Color
         @Composable
diff --git a/lib/src/main/java/com/orange/ods/compose/component/button/OdsIconToggleButtonsRow.kt b/lib/src/main/java/com/orange/ods/compose/component/button/OdsIconToggleButtonsRow.kt
index 1a14efb5f..fe6c6acd8 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/button/OdsIconToggleButtonsRow.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/button/OdsIconToggleButtonsRow.kt
@@ -104,7 +104,7 @@ class OdsIconToggleButtonsRowIcon : OdsComponentIcon {
      * @param enabled Whether or not this [OdsIconToggleButtonsRowIcon] will handle input events and appear enabled for
      * semantics purposes, true by default.
      */
-    constructor(painter: Painter, contentDescription: String, enabled: Boolean = true) : super(painter as Any, contentDescription, enabled)
+    constructor(painter: Painter, contentDescription: String, enabled: Boolean = true) : super(painter, contentDescription, enabled)
 
     /**
      * Creates an instance of [OdsIconToggleButtonsRowIcon].
@@ -114,7 +114,7 @@ class OdsIconToggleButtonsRowIcon : OdsComponentIcon {
      * @param enabled Whether or not this [OdsIconToggleButtonsRowIcon] will handle input events and appear enabled for
      * semantics purposes, true by default.
      */
-    constructor(imageVector: ImageVector, contentDescription: String, enabled: Boolean = true) : super(imageVector as Any, contentDescription, enabled)
+    constructor(imageVector: ImageVector, contentDescription: String, enabled: Boolean = true) : super(imageVector, contentDescription, enabled)
 
     /**
      * Creates an instance of [OdsIconToggleButtonsRowIcon].
@@ -124,7 +124,7 @@ class OdsIconToggleButtonsRowIcon : OdsComponentIcon {
      * @param enabled Whether or not this [OdsIconToggleButtonsRowIcon] will handle input events and appear enabled for
      * semantics purposes, true by default.
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String, enabled: Boolean = true) : super(bitmap as Any, contentDescription, enabled)
+    constructor(bitmap: ImageBitmap, contentDescription: String, enabled: Boolean = true) : super(bitmap, contentDescription, enabled)
 
     private var index: Int = 0
     private var onClick: (Int) -> Unit = {}
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsCard.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsCard.kt
deleted file mode 100644
index 304a1d0fa..000000000
--- a/lib/src/main/java/com/orange/ods/compose/component/card/OdsCard.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- *  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.compose.component.card
-
-import androidx.compose.material.Card
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.semantics.semantics
-
-@OptIn(ExperimentalMaterialApi::class)
-@Composable
-internal fun OdsCard(modifier: Modifier, onClick: (() -> Unit)?, content: @Composable () -> Unit) {
-    if (onClick != null) {
-        Card(
-            modifier = modifier, onClick = onClick, content = content
-        )
-    } else {
-        Card(
-            modifier = modifier.semantics(mergeDescendants = true) {}, content = content
-        )
-    }
-}
\ No newline at end of file
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt
new file mode 100644
index 000000000..7b14b7b52
--- /dev/null
+++ b/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt
@@ -0,0 +1,164 @@
+/*
+ *
+ *  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.compose.component.card
+
+import androidx.compose.foundation.background
+import androidx.compose.material.Card
+import androidx.compose.material.ExperimentalMaterialApi
+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.graphics.ImageBitmap
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.dp
+import com.orange.ods.compose.component.button.OdsTextButton
+import com.orange.ods.compose.component.button.OdsTextButtonStyle
+import com.orange.ods.compose.component.content.OdsComponentCircleImage
+import com.orange.ods.compose.component.content.OdsComponentContent
+import com.orange.ods.compose.component.content.OdsComponentImage
+
+@OptIn(ExperimentalMaterialApi::class)
+@Composable
+internal fun OdsCard(modifier: Modifier, onClick: (() -> Unit)?, content: @Composable () -> Unit) {
+    if (onClick != null) {
+        Card(modifier = modifier, onClick = onClick, content = content)
+    } else {
+        Card(modifier = modifier.semantics(mergeDescendants = true) {}, content = content)
+    }
+}
+
+/**
+ * A button in an [OdsHorizontalCard], an [OdsVerticalHeaderFirstCard] or an [OdsVerticalImageFirstCard].
+ *
+ * @constructor Creates an instance of [OdsCardButton].
+ * @param text Text of the button.
+ * @param onClick Will be called when the user clicks the button.
+ */
+class OdsCardButton(private val text: String, private val onClick: () -> Unit) : OdsComponentContent() {
+
+    @Composable
+    override fun Content(modifier: Modifier) {
+        OdsTextButton(text = text, onClick = onClick, modifier = modifier, style = OdsTextButtonStyle.Primary)
+    }
+}
+
+/**
+ * An image in an [OdsSmallCard], [OdsHorizontalCard], [OdsVerticalHeaderFirstCard] or [OdsVerticalImageFirstCard].
+ */
+class OdsCardImage private constructor(
+    graphicsObject: Any,
+    contentDescription: String,
+    alignment: Alignment = Alignment.Center,
+    contentScale: ContentScale = ContentScale.Crop,
+    private val backgroundColor: Color? = null
+) : OdsComponentImage(graphicsObject, contentDescription, alignment, contentScale) {
+
+    /**
+     * Creates an instance of [OdsCardImage].
+     *
+     * @param painter The painter to draw.
+     * @param contentDescription The content description associated to this [OdsCardImage].
+     * @param alignment Alignment parameter used to place the [Painter] in the given
+     * bounds defined by the width and height.
+     * @param contentScale Scale parameter used to determine the aspect ratio scaling to be used
+     * if the bounds are a different size from the intrinsic size of the [Painter]
+     * @param backgroundColor Optional background color of the card image.
+     */
+    constructor(
+        painter: Painter,
+        contentDescription: String,
+        alignment: Alignment = Alignment.Center,
+        contentScale: ContentScale = ContentScale.Crop,
+        backgroundColor: Color? = null
+    ) : this(painter as Any, contentDescription, alignment, contentScale, backgroundColor)
+
+    /**
+     * Creates an instance of [OdsCardImage].
+     *
+     * @param imageVector The image vector to draw.
+     * @param contentDescription The content description associated to this [OdsCardImage].
+     * @param alignment Alignment parameter used to place the [ImageVector] in the given
+     * bounds defined by the width and height.
+     * @param contentScale Scale parameter used to determine the aspect ratio scaling to be used
+     * if the bounds are a different size from the intrinsic size of the [ImageVector]
+     * @param backgroundColor Optional background color of the card image.
+     */
+    constructor(
+        imageVector: ImageVector,
+        contentDescription: String,
+        alignment: Alignment = Alignment.Center,
+        contentScale: ContentScale = ContentScale.Crop,
+        backgroundColor: Color? = null
+    ) : this(imageVector as Any, contentDescription, alignment, contentScale, backgroundColor)
+
+    /**
+     * Creates an instance of [OdsCardImage].
+     *
+     * @param bitmap The image bitmap to draw.
+     * @param contentDescription The content description associated to this [OdsCardImage].
+     * @param alignment Alignment parameter used to place the [ImageBitmap] in the given
+     * bounds defined by the width and height.
+     * @param contentScale Scale parameter used to determine the aspect ratio scaling to be used
+     * if the bounds are a different size from the intrinsic size of the [ImageBitmap]
+     * @param backgroundColor Optional background color of the card image.
+     */
+    constructor(
+        bitmap: ImageBitmap,
+        contentDescription: String,
+        alignment: Alignment = Alignment.Center,
+        contentScale: ContentScale = ContentScale.Crop,
+        backgroundColor: Color? = null
+    ) : this(bitmap as Any, contentDescription, alignment, contentScale, backgroundColor)
+
+    @Composable
+    override fun Content(modifier: Modifier) {
+        super.Content(modifier = with(modifier) { if (backgroundColor != null) background(backgroundColor) else this })
+    }
+}
+
+/**
+ * A thumbnail in a card.
+ */
+class OdsCardThumbnail : OdsComponentCircleImage {
+
+    private companion object {
+
+        private val CircleSize = 40.dp
+    }
+
+    /**
+     * Creates an instance of [OdsCardThumbnail].
+     *
+     * @param painter The painter to draw.
+     * @param contentDescription The content description associated to this [OdsCardThumbnail].
+     */
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription, CircleSize)
+
+    /**
+     * Creates an instance of [OdsCardThumbnail].
+     *
+     * @param imageVector The image vector to draw.
+     * @param contentDescription The content description associated to this [OdsCardThumbnail].
+     */
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription, CircleSize)
+
+    /**
+     * Creates an instance of [OdsCardThumbnail].
+     *
+     * @param bitmap The image bitmap to draw.
+     * @param contentDescription The content description associated to this [OdsCardThumbnail].
+     */
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription, CircleSize)
+}
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsHorizontalCard.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsHorizontalCard.kt
index 7266a0e95..0969119fb 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/card/OdsHorizontalCard.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/card/OdsHorizontalCard.kt
@@ -10,19 +10,13 @@
 
 package com.orange.ods.compose.component.card
 
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.material.SnackbarDefaults.backgroundColor
 import androidx.compose.material.Text
 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.graphics.painter.Painter
-import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.style.TextOverflow
@@ -34,8 +28,6 @@ import androidx.constraintlayout.compose.Visibility
 import androidx.constraintlayout.compose.atLeast
 import com.orange.ods.R
 import com.orange.ods.compose.component.OdsComposable
-import com.orange.ods.compose.component.button.OdsTextButton
-import com.orange.ods.compose.component.button.OdsTextButtonStyle
 import com.orange.ods.compose.component.divider.OdsDivider
 import com.orange.ods.compose.component.utilities.BasicPreviewParameterProvider
 import com.orange.ods.compose.component.utilities.Preview
@@ -50,47 +42,33 @@ import com.orange.ods.compose.theme.OdsTheme
  * Cards contain content and actions about a single subject.
  *
  * @param title The title to be displayed in the card.
- * @param image The painter of the card image.
+ * @param image The card image.
  * @param modifier Modifier to be applied to the layout of the card.
  * @param subtitle Optional subtitle to be displayed in the card.
  * @param text Optional text description to be displayed in the card. It is truncated to fit on 2 lines.
- * @param button1Text Optional text of the first button in the card. If not present, button will not be shown. If present, [onButton1Click] need to be handled.
- * @param button2Text Optional text of the second button in the card. If not present, button will not be shown. If present, [onButton2Click] need to be handled.
- * @param imageContentDescription Optional card image content description.
- * @param imageBackgroundColor Optional background color of the card image.
- * @param imageContentScale Optional scale parameter used to determine the aspect ratio scaling to be used
- * if the bounds are a different size from the intrinsic size of the [Painter]
- * @param imageAlignment Optional alignment parameter used to place the [Painter] in the given
- * bounds defined by the width and height.
+ * @param firstButton Optional first button in the card.
+ * @param secondButton Optional second button in the card.
  * @param imagePosition Position of the image, it can be [OdsHorizontalCardImagePosition.Start] or [OdsHorizontalCardImagePosition.End] in the card. [OdsHorizontalCardImagePosition.Start] by default.
- * @param dividerEnabled If true, a divider is displayed between card content and the action buttons. True by default.
- * @param onCardClick Optional click on the card itself.
- * @param onButton1Click Optional handler for the first button click.
- * @param onButton2Click Optional handler for the second button click.
+ * @param divider If true, a divider is displayed between card content and the action buttons. True by default.
+ * @param onClick Optional click on the card itself.
  */
 @Composable
 @OdsComposable
 fun OdsHorizontalCard(
     title: String,
-    image: Painter,
+    image: OdsCardImage,
     modifier: Modifier = Modifier,
     subtitle: String? = null,
     text: String? = null,
-    button1Text: String? = null,
-    button2Text: String? = null,
-    imageContentDescription: String? = null,
-    imageBackgroundColor: Color? = null,
-    imageContentScale: ContentScale = ContentScale.Crop,
-    imageAlignment: Alignment = Alignment.Center,
+    firstButton: OdsCardButton? = null,
+    secondButton: OdsCardButton? = null,
     imagePosition: OdsHorizontalCardImagePosition = OdsHorizontalCardImagePosition.Start,
-    dividerEnabled: Boolean = true,
-    onCardClick: (() -> Unit)? = null,
-    onButton1Click: (() -> Unit)? = null,
-    onButton2Click: (() -> Unit)? = null
+    divider: Boolean = true,
+    onClick: (() -> Unit)? = null,
 ) {
     OdsCard(
         modifier = modifier.fillMaxWidth(),
-        onClick = onCardClick
+        onClick = onClick
     ) {
         ConstraintLayout {
             val (
@@ -100,20 +78,16 @@ fun OdsHorizontalCard(
                 textRef,
                 chainBottomSpacerRef, // A 0 dp spacer located at the bottom of the vertical chain composed of title, subtitle and text. Without this spacer, when text is gone, bottom margin of the chain is not respected
                 dividerRef,
-                button1Ref,
-                button2Ref
+                firstButtonRef,
+                secondButtonRef
             ) = createRefs()
 
             val imageSize = dimensionResource(R.dimen.card_horizontal_image_size)
             val smallSpacing = dimensionResource(id = R.dimen.spacing_s)
             val mediumSpacing = dimensionResource(id = R.dimen.spacing_m)
 
-            Image(
-                painter = image,
-                contentDescription = imageContentDescription,
-                contentScale = imageContentScale,
+            image.Content(
                 modifier = Modifier
-                    .let { if (imageBackgroundColor != null) it.background(backgroundColor) else it }
                     .constrainAs(imageRef) {
                         top.linkTo(parent.top)
                         bottom.linkTo(dividerRef.top)
@@ -123,8 +97,7 @@ fun OdsHorizontalCard(
                         }
                         width = Dimension.value(imageSize)
                         height = Dimension.fillToConstraints.atLeast(imageSize)
-                    },
-                alignment = imageAlignment
+                    }
             )
 
             val chainRef = createVerticalChain(titleRef, subtitleRef, textRef, chainBottomSpacerRef, chainStyle = ChainStyle.Packed)
@@ -182,31 +155,27 @@ fun OdsHorizontalCard(
                     top.linkTo(imageRef.bottom)
                     start.linkTo(parent.start)
                     end.linkTo(parent.end)
-                    visibility = if (dividerEnabled && (button1Text != null || button2Text != null)) Visibility.Visible else Visibility.Gone
+                    visibility = if (divider && (firstButton != null || secondButton != null)) Visibility.Visible else Visibility.Gone
                 }
             )
 
-            OdsTextButton(
-                modifier = Modifier.constrainAs(button1Ref) {
-                    top.linkTo(dividerRef.bottom)
-                    start.linkTo(parent.start, margin = smallSpacing)
-                    visibility = if (button1Text != null) Visibility.Visible else Visibility.Gone
-                },
-                text = button1Text.orEmpty(),
-                onClick = { onButton1Click?.invoke() },
-                style = OdsTextButtonStyle.Primary
-            )
+            Box(modifier = Modifier.constrainAs(firstButtonRef) {
+                top.linkTo(dividerRef.bottom)
+                start.linkTo(parent.start, margin = smallSpacing)
+                visibility = if (firstButton != null) Visibility.Visible else Visibility.Gone
+            }) {
+                firstButton?.Content()
+            }
 
-            OdsTextButton(
-                modifier = Modifier.constrainAs(button2Ref) {
+            Box(
+                modifier = Modifier.constrainAs(secondButtonRef) {
                     top.linkTo(dividerRef.bottom)
-                    start.linkTo(button1Ref.end, margin = smallSpacing, goneMargin = smallSpacing)
-                    visibility = if (button2Text != null) Visibility.Visible else Visibility.Gone
-                },
-                text = button2Text.orEmpty(),
-                onClick = { onButton2Click?.invoke() },
-                style = OdsTextButtonStyle.Primary
-            )
+                    start.linkTo(firstButtonRef.end, margin = smallSpacing, goneMargin = smallSpacing)
+                    visibility = if (secondButton != null) Visibility.Visible else Visibility.Gone
+                }
+            ) {
+                secondButton?.Content()
+            }
         }
     }
 }
@@ -223,11 +192,11 @@ private fun PreviewOdsHorizontalCard(@PreviewParameter(OdsHorizontalCardPreviewP
             title = "Title",
             subtitle = parameter.subtitle,
             text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.",
-            button1Text = parameter.button1Text,
-            button2Text = parameter.button2Text,
-            image = painterResource(id = R.drawable.placeholder),
-            dividerEnabled = parameter.dividerEnabled,
-            imagePosition = parameter.imagePosition
+            firstButton = parameter.firstButtonText?.let { OdsCardButton(it) {} },
+            secondButton = parameter.secondButtonText?.let { OdsCardButton(it) {} },
+            image = OdsCardImage(painterResource(id = R.drawable.placeholder), ""),
+            imagePosition = parameter.imagePosition,
+            divider = parameter.dividerEnabled
         )
     }
 
@@ -235,8 +204,8 @@ internal data class OdsHorizontalCardPreviewParameter(
     val subtitle: String?,
     val imagePosition: OdsHorizontalCardImagePosition,
     val dividerEnabled: Boolean,
-    val button1Text: String?,
-    val button2Text: String?
+    val firstButtonText: String?,
+    val secondButtonText: String?
 )
 
 private class OdsHorizontalCardPreviewParameterProvider :
@@ -245,13 +214,13 @@ private class OdsHorizontalCardPreviewParameterProvider :
 private val previewParameterValues: List<OdsHorizontalCardPreviewParameter>
     get() {
         val subtitle = "Subtitle"
-        val button1Text = "Button 1"
-        val button2Text = "Button 2"
+        val firstButtonText = "First button"
+        val secondButtonText = "Second button"
 
         return listOf(
-            OdsHorizontalCardPreviewParameter(subtitle, OdsHorizontalCardImagePosition.Start, true, button1Text, button2Text),
-            OdsHorizontalCardPreviewParameter(subtitle, OdsHorizontalCardImagePosition.End, false, button1Text, null),
+            OdsHorizontalCardPreviewParameter(subtitle, OdsHorizontalCardImagePosition.Start, true, firstButtonText, secondButtonText),
+            OdsHorizontalCardPreviewParameter(subtitle, OdsHorizontalCardImagePosition.End, false, firstButtonText, null),
             OdsHorizontalCardPreviewParameter(subtitle, OdsHorizontalCardImagePosition.Start, true, null, null),
-            OdsHorizontalCardPreviewParameter(null, OdsHorizontalCardImagePosition.Start, false, null, button2Text)
+            OdsHorizontalCardPreviewParameter(null, OdsHorizontalCardImagePosition.Start, false, null, secondButtonText)
         )
     }
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsSmallCard.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsSmallCard.kt
index e17e4daee..257ec6ed5 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/card/OdsSmallCard.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/card/OdsSmallCard.kt
@@ -10,19 +10,13 @@
 
 package com.orange.ods.compose.component.card
 
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.Text
 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.graphics.painter.Painter
-import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.style.TextOverflow
@@ -38,45 +32,30 @@ import com.orange.ods.compose.theme.OdsTheme
  * Cards contain content and actions about a single subject.
  *
  * @param title The title to be displayed in the card.
- * @param image The painter of the card image.
+ * @param image The card image.
  * @param modifier Modifier to be applied to the layout of the card.
  * @param subtitle Optional subtitle to be displayed in the card.
- * @param imageContentDescription Optional card image content description.
- * @param imageBackgroundColor Optional background color of the card image.
- * @param imageContentScale The content scale of the card image.
- * @param imageAlignment The alignment of the card image.
- * @param onCardClick Optional click on the card itself.
+ * @param onClick Optional click on the card itself.
  *
  */
 @Composable
 @OdsComposable
 fun OdsSmallCard(
     title: String,
-    image: Painter,
+    image: OdsCardImage,
     modifier: Modifier = Modifier,
     subtitle: String? = null,
-    imageContentDescription: String? = null,
-    imageBackgroundColor: Color? = null,
-    imageContentScale: ContentScale = ContentScale.Crop,
-    imageAlignment: Alignment = Alignment.Center,
-    onCardClick: (() -> Unit)? = null
+    onClick: (() -> Unit)? = null
 ) {
     OdsCard(
         modifier = modifier,
-        onClick = onCardClick
+        onClick = onClick
     ) {
         Column {
-            Image(
-                painter = image,
-                contentDescription = imageContentDescription,
-                contentScale = imageContentScale,
+            image.Content(
                 modifier = Modifier
                     .fillMaxWidth()
                     .height(dimensionResource(R.dimen.card_small_image_width))
-                    .let {
-                        if (imageBackgroundColor != null) it.background(imageBackgroundColor) else it
-                    },
-                alignment = imageAlignment
             )
             Column(
                 modifier = Modifier
@@ -105,6 +84,6 @@ private fun PreviewOdsSmallCard() = Preview {
     OdsSmallCard(
         title = "Title",
         subtitle = "Subtitle",
-        image = painterResource(id = R.drawable.placeholder)
+        image = OdsCardImage(painterResource(id = R.drawable.placeholder), "")
     )
 }
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalHeaderFirstCard.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalHeaderFirstCard.kt
index 32403dd7d..d39b616a1 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalHeaderFirstCard.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalHeaderFirstCard.kt
@@ -10,8 +10,6 @@
 
 package com.orange.ods.compose.component.card
 
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -22,17 +20,11 @@ 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.graphics.painter.Painter
-import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.unit.dp
 import com.orange.ods.R
 import com.orange.ods.compose.component.OdsComposable
-import com.orange.ods.compose.component.button.OdsTextButton
-import com.orange.ods.compose.component.button.OdsTextButtonStyle
-import com.orange.ods.compose.component.utilities.OdsImageCircleShape
 import com.orange.ods.compose.component.utilities.Preview
 import com.orange.ods.compose.component.utilities.UiModePreviews
 import com.orange.ods.compose.text.OdsTextBody1
@@ -46,44 +38,31 @@ import com.orange.ods.extension.orElse
  * Cards contain content and actions about a single subject.
  *
  * @param title The title to be displayed in the card.
- * @param image The painter of the card image.
+ * @param image The card image.
  * @param modifier Modifier to be applied to the layout of the card.
- * @param thumbnail Optional painter of the card thumbnail: avatar, logo or icon.
+ * @param thumbnail Optional card thumbnail: avatar, logo or icon.
  * @param subtitle Optional subtitle to be displayed in the card.
- * @param imageContentDescription Optional card image content description.
- * @param imageBackgroundColor Optional background color of the card image.
- * @param imageContentScale The content scale of the card image.
- * @param imageAlignment The alignment of the card image.
  * @param text Optional text description to be displayed in the card.
- * @param button1Text Optional text of the first button in the card. If not present, button will not be shown. If present, [onButton1Click] need to be handled.
- * @param button2Text Optional text of the second button in the card. If not present, button will not be shown. If present, [onButton2Click] need to be handled.
- * @param onCardClick Optional click on the card itself.
- * @param onButton1Click Optional handler for the first button click.
- * @param onButton2Click Optional handler for the second button click.
- *
+ * @param firstButton Optional first button in the card.
+ * @param secondButton Optional second button in the card.
+ * @param onClick Optional click on the card itself.
  */
 @Composable
 @OdsComposable
 fun OdsVerticalHeaderFirstCard(
     title: String,
-    image: Painter,
+    image: OdsCardImage,
     modifier: Modifier = Modifier,
-    thumbnail: Painter? = null,
+    thumbnail: OdsCardThumbnail? = null,
     subtitle: String? = null,
-    imageContentDescription: String? = null,
-    imageBackgroundColor: Color? = null,
-    imageContentScale: ContentScale = ContentScale.Crop,
-    imageAlignment: Alignment = Alignment.Center,
     text: String? = null,
-    button1Text: String? = null,
-    button2Text: String? = null,
-    onCardClick: (() -> Unit)? = null,
-    onButton1Click: (() -> Unit)? = null,
-    onButton2Click: (() -> Unit)? = null
+    firstButton: OdsCardButton? = null,
+    secondButton: OdsCardButton? = null,
+    onClick: (() -> Unit)? = null
 ) {
     OdsCard(
         modifier = modifier,
-        onClick = onCardClick
+        onClick = onClick
     ) {
         Column {
             Row(
@@ -93,7 +72,7 @@ fun OdsVerticalHeaderFirstCard(
                     .padding(horizontal = dimensionResource(id = R.dimen.spacing_m)),
                 verticalAlignment = Alignment.CenterVertically
             ) {
-                thumbnail?.let { OdsImageCircleShape(painter = it) }
+                thumbnail?.Content()
                 Column(modifier = Modifier.padding(start = thumbnail?.let { dimensionResource(id = R.dimen.spacing_s) }.orElse { 0.dp })) {
                     OdsTextH6(text = title)
                     subtitle?.let {
@@ -101,17 +80,10 @@ fun OdsVerticalHeaderFirstCard(
                     }
                 }
             }
-            Image(
-                painter = image,
-                contentDescription = imageContentDescription,
-                contentScale = imageContentScale,
+            image.Content(
                 modifier = Modifier
                     .fillMaxWidth()
                     .height(dimensionResource(R.dimen.card_big_image_height))
-                    .let {
-                        if (imageBackgroundColor != null) it.background(imageBackgroundColor) else it
-                    },
-                alignment = imageAlignment
             )
 
             text?.let {
@@ -123,7 +95,7 @@ fun OdsVerticalHeaderFirstCard(
                 )
             }
 
-            if (button1Text != null || button2Text != null || text != null) {
+            if (firstButton != null || secondButton != null || text != null) {
                 Spacer(modifier = Modifier.height(dimensionResource(id = R.dimen.spacing_m)))
             }
 
@@ -133,20 +105,8 @@ fun OdsVerticalHeaderFirstCard(
                     .padding(horizontal = dimensionResource(id = R.dimen.spacing_s)),
                 horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing_s))
             ) {
-                button1Text?.let {
-                    OdsTextButton(
-                        text = it,
-                        onClick = { onButton1Click?.invoke() },
-                        style = OdsTextButtonStyle.Primary
-                    )
-                }
-                button2Text?.let {
-                    OdsTextButton(
-                        text = it,
-                        onClick = { onButton2Click?.invoke() },
-                        style = OdsTextButtonStyle.Primary
-                    )
-                }
+                firstButton?.Content()
+                secondButton?.Content()
             }
         }
     }
@@ -157,11 +117,11 @@ fun OdsVerticalHeaderFirstCard(
 private fun PreviewOdsVerticalHeaderFirstCard() = Preview {
     OdsVerticalHeaderFirstCard(
         title = "Title",
-        image = painterResource(id = R.drawable.placeholder),
-        thumbnail = painterResource(id = R.drawable.placeholder_small),
+        image = OdsCardImage(painterResource(id = R.drawable.placeholder), ""),
+        thumbnail = OdsCardThumbnail(painterResource(id = R.drawable.placeholder_small), ""),
         subtitle = "Subtitle",
         text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.",
-        button1Text = "Button 1",
-        button2Text = "Button 2"
+        firstButton = OdsCardButton("First button") {},
+        secondButton = OdsCardButton("Second button") {}
     )
 }
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalImageFirstCard.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalImageFirstCard.kt
index 17f0e26dd..db0a271c7 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalImageFirstCard.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/card/OdsVerticalImageFirstCard.kt
@@ -10,8 +10,6 @@
 
 package com.orange.ods.compose.component.card
 
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -19,17 +17,11 @@ import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 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.graphics.painter.Painter
-import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import com.orange.ods.R
 import com.orange.ods.compose.component.OdsComposable
-import com.orange.ods.compose.component.button.OdsTextButton
-import com.orange.ods.compose.component.button.OdsTextButtonStyle
 import com.orange.ods.compose.component.utilities.Preview
 import com.orange.ods.compose.component.utilities.UiModePreviews
 import com.orange.ods.compose.text.OdsTextBody1
@@ -42,55 +34,35 @@ import com.orange.ods.compose.text.OdsTextSubtitle2
  * Cards contain content and actions about a single subject.
  *
  * @param title The title to be displayed in the card.
- * @param image The painter of the card image.
+ * @param image The card image.
  * @param modifier Modifier to be applied to the layout of the card.
  * @param subtitle Optional subtitle to be displayed in the card.
  * @param text Optional text description to be displayed in the card.
- * @param button1Text Optional text of the first button in the card. If not present, button will not be shown. If present, [onButton1Click] need to be handled.
- * @param button2Text Optional text of the second button in the card. If not present, button will not be shown. If present, [onButton2Click] need to be handled.
- * @param imageContentDescription Optional card image content description.
- * @param imageBackgroundColor Optional background color of the card image.
- * @param imageContentScale The content scale of the card image.
- * @param imageAlignment The alignment of the card image.
- * @param onCardClick Optional click on the card itself.
- * @param onButton1Click Optional handler for the first button click.
- * @param onButton2Click Optional handler for the second button click.
- *
+ * @param firstButton Optional first button in the card.
+ * @param secondButton Optional second button in the card.
+ * @param onClick Optional click on the card itself.
  */
 @Composable
 @OdsComposable
 fun OdsVerticalImageFirstCard(
     title: String,
-    image: Painter,
+    image: OdsCardImage,
     modifier: Modifier = Modifier,
     subtitle: String? = null,
     text: String? = null,
-    button1Text: String? = null,
-    button2Text: String? = null,
-    imageContentDescription: String? = null,
-    imageBackgroundColor: Color? = null,
-    imageContentScale: ContentScale = ContentScale.Crop,
-    imageAlignment: Alignment = Alignment.Center,
-    onCardClick: (() -> Unit)? = null,
-    onButton1Click: (() -> Unit)? = null,
-    onButton2Click: (() -> Unit)? = null
+    firstButton: OdsCardButton? = null,
+    secondButton: OdsCardButton? = null,
+    onClick: (() -> Unit)? = null
 ) {
     OdsCard(
         modifier = modifier,
-        onClick = onCardClick
+        onClick = onClick
     ) {
         Column {
-            Image(
-                painter = image,
-                contentDescription = imageContentDescription,
-                contentScale = imageContentScale,
+            image.Content(
                 modifier = Modifier
                     .fillMaxWidth()
                     .height(dimensionResource(R.dimen.card_big_image_height))
-                    .let {
-                        if (imageBackgroundColor != null) it.background(imageBackgroundColor) else it
-                    },
-                alignment = imageAlignment
             )
             Column(
                 modifier = Modifier
@@ -113,20 +85,8 @@ fun OdsVerticalImageFirstCard(
                 modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.spacing_s)),
                 horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing_s))
             ) {
-                button1Text?.let {
-                    OdsTextButton(
-                        text = it,
-                        onClick = { onButton1Click?.invoke() },
-                        style = OdsTextButtonStyle.Primary
-                    )
-                }
-                button2Text?.let {
-                    OdsTextButton(
-                        text = it,
-                        onClick = { onButton2Click?.invoke() },
-                        style = OdsTextButtonStyle.Primary
-                    )
-                }
+                firstButton?.Content()
+                secondButton?.Content()
             }
         }
     }
@@ -139,8 +99,8 @@ private fun PreviewOdsVerticalImageFirstCard() = Preview {
         title = "Title",
         subtitle = "Subtitle",
         text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.",
-        button1Text = "Button 1",
-        button2Text = "Button 2",
-        image = painterResource(id = R.drawable.placeholder)
+        firstButton = OdsCardButton("First button") {},
+        secondButton = OdsCardButton("Second button") {},
+        image = OdsCardImage(painterResource(id = R.drawable.placeholder), "")
     )
 }
diff --git a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt
new file mode 100644
index 000000000..8e77b82e1
--- /dev/null
+++ b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt
@@ -0,0 +1,62 @@
+/*
+ *
+ *  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.compose.component.content
+
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.unit.Dp
+
+abstract class OdsComponentCircleImage private constructor(
+    graphicsObject: Any,
+    contentDescription: String,
+    private val circleSize: Dp
+) : OdsComponentImage(graphicsObject, contentDescription, contentScale = ContentScale.Crop) {
+
+    /**
+     * Creates an instance of [OdsComponentCircleImage].
+     *
+     * @param painter The painter to draw.
+     * @param contentDescription The content description associated to this [OdsComponentCircleImage].
+     */
+    constructor(painter: Painter, contentDescription: String, circleSize: Dp) : this(painter as Any, contentDescription, circleSize)
+
+    /**
+     * Creates an instance of [OdsComponentCircleImage].
+     *
+     * @param imageVector The image vector to draw.
+     * @param contentDescription The content description associated to this [OdsComponentCircleImage].
+     */
+    constructor(imageVector: ImageVector, contentDescription: String, circleSize: Dp) : this(imageVector as Any, contentDescription, circleSize)
+
+    /**
+     * Creates an instance of [OdsComponentCircleImage].
+     *
+     * @param bitmap The image bitmap to draw.
+     * @param contentDescription The content description associated to this [OdsComponentCircleImage].
+     */
+    constructor(bitmap: ImageBitmap, contentDescription: String, circleSize: Dp) : this(bitmap as Any, contentDescription, circleSize)
+
+    @Composable
+    override fun Content(modifier: Modifier) {
+        super.Content(
+            modifier = modifier
+                .size(circleSize)
+                .clip(CircleShape)
+        )
+    }
+}
diff --git a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt
index 39106cad8..436618e16 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt
@@ -25,7 +25,7 @@ import com.orange.ods.extension.orElse
 /**
  * An icon in a component.
  */
-abstract class OdsComponentIcon protected constructor(
+abstract class OdsComponentIcon private constructor(
     private val graphicsObject: Any,
     private val contentDescription: String,
     protected var enabled: Boolean = true,
diff --git a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt
index 9afc1bfc7..6b094dee5 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt
@@ -12,6 +12,7 @@ package com.orange.ods.compose.component.content
 
 import androidx.compose.foundation.Image
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.ImageBitmap
 import androidx.compose.ui.graphics.painter.Painter
@@ -24,33 +25,55 @@ import androidx.compose.ui.layout.ContentScale
 abstract class OdsComponentImage(
     private val graphicsObject: Any,
     private val contentDescription: String,
+    private val alignment: Alignment = Alignment.Center,
     private val contentScale: ContentScale = ContentScale.Fit
 ) : OdsComponentContent() {
 
     protected constructor(
         painter: Painter,
         contentDescription: String,
+        alignment: Alignment = Alignment.Center,
         contentScale: ContentScale = ContentScale.Fit
-    ) : this(painter as Any, contentDescription, contentScale)
+    ) : this(painter as Any, contentDescription, alignment, contentScale)
 
     protected constructor(
         imageVector: ImageVector,
         contentDescription: String,
+        alignment: Alignment = Alignment.Center,
         contentScale: ContentScale = ContentScale.Fit
-    ) : this(imageVector as Any, contentDescription, contentScale)
+    ) : this(imageVector as Any, contentDescription, alignment, contentScale)
 
     protected constructor(
         bitmap: ImageBitmap,
         contentDescription: String,
+        alignment: Alignment = Alignment.Center,
         contentScale: ContentScale = ContentScale.Fit
-    ) : this(bitmap as Any, contentDescription, contentScale)
+    ) : this(bitmap as Any, contentDescription, alignment, contentScale)
 
     @Composable
     override fun Content(modifier: Modifier) {
         when (graphicsObject) {
-            is Painter -> Image(painter = graphicsObject, contentDescription = contentDescription, modifier = modifier, contentScale = contentScale)
-            is ImageVector -> Image(imageVector = graphicsObject, contentDescription = contentDescription, modifier = modifier, contentScale = contentScale)
-            is ImageBitmap -> Image(bitmap = graphicsObject, contentDescription = contentDescription, modifier = modifier, contentScale = contentScale)
+            is Painter -> Image(
+                painter = graphicsObject,
+                contentDescription = contentDescription,
+                modifier = modifier,
+                alignment = alignment,
+                contentScale = contentScale
+            )
+            is ImageVector -> Image(
+                imageVector = graphicsObject,
+                contentDescription = contentDescription,
+                modifier = modifier,
+                alignment = alignment,
+                contentScale = contentScale
+            )
+            is ImageBitmap -> Image(
+                bitmap = graphicsObject,
+                contentDescription = contentDescription,
+                modifier = modifier,
+                alignment = alignment,
+                contentScale = contentScale
+            )
             else -> {}
         }
     }

From 3d1b2b2ef0879e18e7abf779ea2e1a541cf20686 Mon Sep 17 00:00:00 2001
From: Florent Maitre <florent.maitre@orange.com>
Date: Wed, 20 Sep 2023 14:56:42 +0200
Subject: [PATCH 2/5] [#597] Fix build errors after rebase

---
 .../component/button/OdsFloatingActionButton.kt      |  6 +++---
 .../ods/compose/component/chip/OdsChipCommon.kt      | 12 ++++++------
 .../ods/compose/component/imagetile/OdsImageTile.kt  |  6 +++---
 .../progressindicator/OdsLinearProgressIndicator.kt  |  6 +++---
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/lib/src/main/java/com/orange/ods/compose/component/button/OdsFloatingActionButton.kt b/lib/src/main/java/com/orange/ods/compose/component/button/OdsFloatingActionButton.kt
index 878ed8e2c..7a229b932 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/button/OdsFloatingActionButton.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/button/OdsFloatingActionButton.kt
@@ -115,7 +115,7 @@ class OdsFloatingActionButtonIcon : OdsComponentIcon {
      * @param painter Painter of the icon.
      * @param contentDescription The content description associated to this [OdsFloatingActionButtonIcon].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsFloatingActionButtonIcon].
@@ -123,7 +123,7 @@ class OdsFloatingActionButtonIcon : OdsComponentIcon {
      * @param imageVector Image vector of the icon.
      * @param contentDescription The content description associated to this [OdsFloatingActionButtonIcon].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsFloatingActionButtonIcon].
@@ -131,7 +131,7 @@ class OdsFloatingActionButtonIcon : OdsComponentIcon {
      * @param bitmap Image bitmap of the icon.
      * @param contentDescription The content description associated to this [OdsFloatingActionButtonIcon].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 
     @Composable
     override fun Content(modifier: Modifier) {
diff --git a/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt b/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt
index 089570f57..31f66ba09 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt
@@ -39,7 +39,7 @@ class OdsChipLeadingIcon : OdsComponentIcon {
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingIcon].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsChipLeadingIcon].
@@ -47,7 +47,7 @@ class OdsChipLeadingIcon : OdsComponentIcon {
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingIcon].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsChipLeadingIcon].
@@ -55,7 +55,7 @@ class OdsChipLeadingIcon : OdsComponentIcon {
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingIcon].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 
     @Composable
     override fun Content(modifier: Modifier) {
@@ -74,7 +74,7 @@ class OdsChipLeadingAvatar : OdsComponentImage {
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingAvatar].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription, ContentScale.Crop)
+    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription, contentScale = ContentScale.Crop)
 
     /**
      * Creates an instance of [OdsChipLeadingAvatar].
@@ -82,7 +82,7 @@ class OdsChipLeadingAvatar : OdsComponentImage {
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingAvatar].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription, ContentScale.Crop)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription, contentScale = ContentScale.Crop)
 
     /**
      * Creates an instance of [OdsChipLeadingAvatar].
@@ -90,7 +90,7 @@ class OdsChipLeadingAvatar : OdsComponentImage {
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingAvatar].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription, ContentScale.Crop)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription, contentScale = ContentScale.Crop)
 
     @Composable
     fun Content(enabled: Boolean) {
diff --git a/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt b/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt
index 096a2d93f..edeef3c60 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt
@@ -142,7 +142,7 @@ class OdsImageTileImage : OdsComponentImage {
     constructor(painter: Painter, contentDescription: String, contentScale: ContentScale = ContentScale.Crop) : super(
         painter as Any,
         contentDescription,
-        contentScale
+        contentScale = contentScale
     )
 
     /**
@@ -155,7 +155,7 @@ class OdsImageTileImage : OdsComponentImage {
     constructor(imageVector: ImageVector, contentDescription: String, contentScale: ContentScale = ContentScale.Crop) : super(
         imageVector as Any,
         contentDescription,
-        contentScale
+        contentScale = contentScale
     )
 
     /**
@@ -168,7 +168,7 @@ class OdsImageTileImage : OdsComponentImage {
     constructor(bitmap: ImageBitmap, contentDescription: String, contentScale: ContentScale = ContentScale.Crop) : super(
         bitmap as Any,
         contentDescription,
-        contentScale
+        contentScale = contentScale
     )
 }
 
diff --git a/lib/src/main/java/com/orange/ods/compose/component/progressindicator/OdsLinearProgressIndicator.kt b/lib/src/main/java/com/orange/ods/compose/component/progressindicator/OdsLinearProgressIndicator.kt
index badb35686..eafd48430 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/progressindicator/OdsLinearProgressIndicator.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/progressindicator/OdsLinearProgressIndicator.kt
@@ -125,7 +125,7 @@ class OdsLinearProgressIndicatorIcon : OdsComponentIcon {
      * @param painter Painter of the icon.
      * @param contentDescription The content description associated to this [OdsLinearProgressIndicatorIcon].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsLinearProgressIndicatorIcon].
@@ -133,7 +133,7 @@ class OdsLinearProgressIndicatorIcon : OdsComponentIcon {
      * @param imageVector Image vector of the icon.
      * @param contentDescription The content description associated to this [OdsLinearProgressIndicatorIcon].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsLinearProgressIndicatorIcon].
@@ -141,7 +141,7 @@ class OdsLinearProgressIndicatorIcon : OdsComponentIcon {
      * @param bitmap Image bitmap of the icon.
      * @param contentDescription The content description associated to this [OdsLinearProgressIndicatorIcon].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 
     @Composable
     override fun Content(modifier: Modifier) {

From 10fb233f66a30460e8c1a1ce7c69acee654ee06b Mon Sep 17 00:00:00 2001
From: Florent Maitre <florent.maitre@orange.com>
Date: Wed, 20 Sep 2023 15:02:00 +0200
Subject: [PATCH 3/5] [#597] OdsComponentIcon and OdsComponentImage generic
 constructors are now internal

---
 .../com/orange/ods/compose/component/chip/OdsChipCommon.kt  | 6 +++---
 .../ods/compose/component/content/OdsComponentIcon.kt       | 2 +-
 .../ods/compose/component/content/OdsComponentImage.kt      | 2 +-
 .../orange/ods/compose/component/imagetile/OdsImageTile.kt  | 6 +++---
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt b/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt
index 31f66ba09..2403e8d23 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/chip/OdsChipCommon.kt
@@ -74,7 +74,7 @@ class OdsChipLeadingAvatar : OdsComponentImage {
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingAvatar].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter as Any, contentDescription, contentScale = ContentScale.Crop)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription, contentScale = ContentScale.Crop)
 
     /**
      * Creates an instance of [OdsChipLeadingAvatar].
@@ -82,7 +82,7 @@ class OdsChipLeadingAvatar : OdsComponentImage {
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingAvatar].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector as Any, contentDescription, contentScale = ContentScale.Crop)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription, contentScale = ContentScale.Crop)
 
     /**
      * Creates an instance of [OdsChipLeadingAvatar].
@@ -90,7 +90,7 @@ class OdsChipLeadingAvatar : OdsComponentImage {
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsChipLeadingAvatar].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap as Any, contentDescription, contentScale = ContentScale.Crop)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription, contentScale = ContentScale.Crop)
 
     @Composable
     fun Content(enabled: Boolean) {
diff --git a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt
index 436618e16..dcf846134 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentIcon.kt
@@ -25,7 +25,7 @@ import com.orange.ods.extension.orElse
 /**
  * An icon in a component.
  */
-abstract class OdsComponentIcon private constructor(
+abstract class OdsComponentIcon internal constructor(
     private val graphicsObject: Any,
     private val contentDescription: String,
     protected var enabled: Boolean = true,
diff --git a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt
index 6b094dee5..db5cba588 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentImage.kt
@@ -22,7 +22,7 @@ import androidx.compose.ui.layout.ContentScale
 /**
  * An image in a component.
  */
-abstract class OdsComponentImage(
+abstract class OdsComponentImage internal constructor(
     private val graphicsObject: Any,
     private val contentDescription: String,
     private val alignment: Alignment = Alignment.Center,
diff --git a/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt b/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt
index edeef3c60..16d9b37b4 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/imagetile/OdsImageTile.kt
@@ -140,7 +140,7 @@ class OdsImageTileImage : OdsComponentImage {
      * @param contentScale The rule to apply to scale the image in this [OdsImageTileImage], [ContentScale.Crop] by default.
      */
     constructor(painter: Painter, contentDescription: String, contentScale: ContentScale = ContentScale.Crop) : super(
-        painter as Any,
+        painter,
         contentDescription,
         contentScale = contentScale
     )
@@ -153,7 +153,7 @@ class OdsImageTileImage : OdsComponentImage {
      * @param contentScale The rule to apply to scale the image in this [OdsImageTileImage], [ContentScale.Crop] by default.
      */
     constructor(imageVector: ImageVector, contentDescription: String, contentScale: ContentScale = ContentScale.Crop) : super(
-        imageVector as Any,
+        imageVector,
         contentDescription,
         contentScale = contentScale
     )
@@ -166,7 +166,7 @@ class OdsImageTileImage : OdsComponentImage {
      * @param contentScale The rule to apply to scale the image in this [OdsImageTileImage], [ContentScale.Crop] by default.
      */
     constructor(bitmap: ImageBitmap, contentDescription: String, contentScale: ContentScale = ContentScale.Crop) : super(
-        bitmap as Any,
+        bitmap,
         contentDescription,
         contentScale = contentScale
     )

From 329ee24c82bdf22ce8c0f4af48f97456dab6bbba Mon Sep 17 00:00:00 2001
From: Florent Maitre <florent.maitre@orange.com>
Date: Wed, 20 Sep 2023 14:39:17 +0200
Subject: [PATCH 4/5] [#597] Review: Circle size of OdsComponentCircleImage is
 now hardcoded

---
 .../ods/compose/component/banner/OdsBanner.kt       | 12 +++---------
 .../ods/compose/component/card/OdsCardsCommon.kt    | 12 +++---------
 .../component/content/OdsComponentCircleImage.kt    | 13 ++++++-------
 3 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt b/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt
index 08dc3a29f..089d9a0ae 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/banner/OdsBanner.kt
@@ -26,7 +26,6 @@ import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.PreviewParameter
-import androidx.compose.ui.unit.dp
 import com.orange.ods.R
 import com.orange.ods.compose.component.OdsComposable
 import com.orange.ods.compose.component.button.OdsTextButton
@@ -123,18 +122,13 @@ class OdsBannerButton(private val text: String, private val onClick: () -> Unit)
  */
 class OdsBannerImage : OdsComponentCircleImage {
 
-    private companion object {
-
-        private val CircleSize = 40.dp
-    }
-
     /**
      * Creates an instance of [OdsBannerImage].
      *
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsBannerImage].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription, CircleSize)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsBannerImage].
@@ -142,7 +136,7 @@ class OdsBannerImage : OdsComponentCircleImage {
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsBannerImage].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription, CircleSize)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsBannerImage].
@@ -150,7 +144,7 @@ class OdsBannerImage : OdsComponentCircleImage {
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsBannerImage].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription, CircleSize)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 }
 
 @UiModePreviews.Default
diff --git a/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt b/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt
index 7b14b7b52..8077bc203 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/card/OdsCardsCommon.kt
@@ -22,7 +22,6 @@ import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.unit.dp
 import com.orange.ods.compose.component.button.OdsTextButton
 import com.orange.ods.compose.component.button.OdsTextButtonStyle
 import com.orange.ods.compose.component.content.OdsComponentCircleImage
@@ -133,18 +132,13 @@ class OdsCardImage private constructor(
  */
 class OdsCardThumbnail : OdsComponentCircleImage {
 
-    private companion object {
-
-        private val CircleSize = 40.dp
-    }
-
     /**
      * Creates an instance of [OdsCardThumbnail].
      *
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsCardThumbnail].
      */
-    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription, CircleSize)
+    constructor(painter: Painter, contentDescription: String) : super(painter, contentDescription)
 
     /**
      * Creates an instance of [OdsCardThumbnail].
@@ -152,7 +146,7 @@ class OdsCardThumbnail : OdsComponentCircleImage {
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsCardThumbnail].
      */
-    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription, CircleSize)
+    constructor(imageVector: ImageVector, contentDescription: String) : super(imageVector, contentDescription)
 
     /**
      * Creates an instance of [OdsCardThumbnail].
@@ -160,5 +154,5 @@ class OdsCardThumbnail : OdsComponentCircleImage {
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsCardThumbnail].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription, CircleSize)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : super(bitmap, contentDescription)
 }
diff --git a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt
index 8e77b82e1..f458096bc 100644
--- a/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt
+++ b/lib/src/main/java/com/orange/ods/compose/component/content/OdsComponentCircleImage.kt
@@ -19,12 +19,11 @@ import androidx.compose.ui.graphics.ImageBitmap
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
 
 abstract class OdsComponentCircleImage private constructor(
     graphicsObject: Any,
-    contentDescription: String,
-    private val circleSize: Dp
+    contentDescription: String
 ) : OdsComponentImage(graphicsObject, contentDescription, contentScale = ContentScale.Crop) {
 
     /**
@@ -33,7 +32,7 @@ abstract class OdsComponentCircleImage private constructor(
      * @param painter The painter to draw.
      * @param contentDescription The content description associated to this [OdsComponentCircleImage].
      */
-    constructor(painter: Painter, contentDescription: String, circleSize: Dp) : this(painter as Any, contentDescription, circleSize)
+    constructor(painter: Painter, contentDescription: String) : this(painter as Any, contentDescription)
 
     /**
      * Creates an instance of [OdsComponentCircleImage].
@@ -41,7 +40,7 @@ abstract class OdsComponentCircleImage private constructor(
      * @param imageVector The image vector to draw.
      * @param contentDescription The content description associated to this [OdsComponentCircleImage].
      */
-    constructor(imageVector: ImageVector, contentDescription: String, circleSize: Dp) : this(imageVector as Any, contentDescription, circleSize)
+    constructor(imageVector: ImageVector, contentDescription: String) : this(imageVector as Any, contentDescription)
 
     /**
      * Creates an instance of [OdsComponentCircleImage].
@@ -49,13 +48,13 @@ abstract class OdsComponentCircleImage private constructor(
      * @param bitmap The image bitmap to draw.
      * @param contentDescription The content description associated to this [OdsComponentCircleImage].
      */
-    constructor(bitmap: ImageBitmap, contentDescription: String, circleSize: Dp) : this(bitmap as Any, contentDescription, circleSize)
+    constructor(bitmap: ImageBitmap, contentDescription: String) : this(bitmap as Any, contentDescription)
 
     @Composable
     override fun Content(modifier: Modifier) {
         super.Content(
             modifier = modifier
-                .size(circleSize)
+                .size(40.dp)
                 .clip(CircleShape)
         )
     }

From 361ef97ccff82daa408a975c63cd82dca6021c4a Mon Sep 17 00:00:00 2001
From: Florent Maitre <florent.maitre@orange.com>
Date: Wed, 20 Sep 2023 15:48:40 +0200
Subject: [PATCH 5/5] [#597] Review: Fix a padding bug in cards

---
 .../orange/ods/app/ui/components/cards/CardHorizontal.kt | 9 ++++-----
 .../com/orange/ods/app/ui/components/cards/CardSmall.kt  | 9 ++++-----
 .../app/ui/components/cards/CardVerticalHeaderFirst.kt   | 9 ++++-----
 .../app/ui/components/cards/CardVerticalImageFirst.kt    | 9 ++++-----
 4 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt
index 1ab38d816..b6fae1d17 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardHorizontal.kt
@@ -11,7 +11,6 @@
 package com.orange.ods.app.ui.components.cards
 
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.rememberScrollState
@@ -45,8 +44,8 @@ fun CardHorizontal(customizationState: CardCustomizationState) {
         Column(
             modifier = Modifier
                 .fillMaxSize()
+                .verticalScroll(state = rememberScrollState())
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
-                .verticalScroll(state = rememberScrollState()),
         ) {
             val firstButtonText = stringResource(id = R.string.component_element_first_button)
             val secondButtonText = stringResource(id = R.string.component_element_second_button)
@@ -73,9 +72,9 @@ fun CardHorizontal(customizationState: CardCustomizationState) {
                 divider = hasDivider
             )
 
-            Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
-
-            CodeImplementationColumn {
+            CodeImplementationColumn(
+                modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s))
+            ) {
                 FunctionCallCode(
                     name = OdsComposable.OdsHorizontalCard.name,
                     exhaustiveParameters = false,
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt
index f525f3db5..43373222d 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardSmall.kt
@@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.rememberScrollState
@@ -47,8 +46,8 @@ fun CardSmall(customizationState: CardCustomizationState) {
         Column(
             modifier = Modifier
                 .fillMaxSize()
+                .verticalScroll(state = rememberScrollState())
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
-                .verticalScroll(state = rememberScrollState()),
         ) {
             Row(
                 modifier = Modifier
@@ -76,9 +75,9 @@ fun CardSmall(customizationState: CardCustomizationState) {
                 Box(modifier = Modifier.weight(0.5f))
             }
 
-            Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
-
-            CodeImplementationColumn {
+            CodeImplementationColumn(
+                modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s))
+            ) {
                 FunctionCallCode(
                     name = OdsComposable.OdsSmallCard.name,
                     exhaustiveParameters = false,
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt
index 56ece9cb3..df11b68d0 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalHeaderFirst.kt
@@ -11,7 +11,6 @@
 package com.orange.ods.app.ui.components.cards
 
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.rememberScrollState
@@ -48,8 +47,8 @@ fun CardVerticalHeaderFirst(customizationState: CardCustomizationState) {
         Column(
             modifier = Modifier
                 .fillMaxSize()
+                .verticalScroll(state = rememberScrollState())
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
-                .verticalScroll(state = rememberScrollState()),
         ) {
             val firstButtonText = stringResource(id = R.string.component_element_first_button)
             val secondButtonText = stringResource(id = R.string.component_element_second_button)
@@ -76,9 +75,9 @@ fun CardVerticalHeaderFirst(customizationState: CardCustomizationState) {
                 secondButton = if (hasSecondButton) OdsCardButton(secondButtonText) { clickOnElement(context, secondButtonText) } else null,
             )
 
-            Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
-
-            CodeImplementationColumn {
+            CodeImplementationColumn(
+                modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s))
+            ) {
                 FunctionCallCode(
                     name = OdsComposable.OdsVerticalHeaderFirstCard.name,
                     exhaustiveParameters = false,
diff --git a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt
index c770806e4..b7f38c9f5 100644
--- a/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt
+++ b/app/src/main/java/com/orange/ods/app/ui/components/cards/CardVerticalImageFirst.kt
@@ -11,7 +11,6 @@
 package com.orange.ods.app.ui.components.cards
 
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.rememberScrollState
@@ -45,8 +44,8 @@ fun CardVerticalImageFirst(customizationState: CardCustomizationState) {
         Column(
             modifier = Modifier
                 .fillMaxSize()
+                .verticalScroll(state = rememberScrollState())
                 .padding(dimensionResource(id = com.orange.ods.R.dimen.spacing_m))
-                .verticalScroll(state = rememberScrollState()),
         ) {
             val firstButtonText = stringResource(id = R.string.component_element_first_button)
             val secondButtonText = stringResource(id = R.string.component_element_second_button)
@@ -71,9 +70,9 @@ fun CardVerticalImageFirst(customizationState: CardCustomizationState) {
                 secondButton = if (hasSecondButton) OdsCardButton(secondButtonText) { clickOnElement(context, secondButtonText) } else null,
             )
 
-            Spacer(modifier = Modifier.padding(top = dimensionResource(com.orange.ods.R.dimen.spacing_s)))
-
-            CodeImplementationColumn {
+            CodeImplementationColumn(
+                modifier = Modifier.padding(top = dimensionResource(id = com.orange.ods.R.dimen.spacing_s))
+            ) {
                 FunctionCallCode(
                     name = OdsComposable.OdsVerticalImageFirstCard.name,
                     exhaustiveParameters = false,