Skip to content

Commit

Permalink
Merge pull request #720 from Orange-OpenSource/643-banner-enhance-dis…
Browse files Browse the repository at this point in the history
…play

643 - Banner - Enhance display for accessibility and allow banner without button
  • Loading branch information
florentmaitre authored Nov 30, 2023
2 parents 47921a6 + 669ad5f commit e104c59
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,33 @@ import androidx.compose.runtime.saveable.rememberSaveable
@Composable
fun rememberBannerCustomizationState(
buttonsCount: MutableState<Int> = rememberSaveable { mutableStateOf(BannerCustomizationState.MinActionButtonCount) },
textLinesCount: MutableState<Int> = rememberSaveable { mutableStateOf(BannerCustomizationState.MaxTextCount) },
shortMessage: MutableState<Boolean> = rememberSaveable { mutableStateOf(true) },
imageChecked: MutableState<Boolean> = rememberSaveable { mutableStateOf(false) }
) =
remember(buttonsCount, textLinesCount, imageChecked) {
BannerCustomizationState(buttonsCount, textLinesCount, imageChecked)
remember(buttonsCount, shortMessage, imageChecked) {
BannerCustomizationState(buttonsCount, shortMessage, imageChecked)
}

class BannerCustomizationState(
val buttonsCount: MutableState<Int>,
val textLinesCount: MutableState<Int>,
val shortMessage: MutableState<Boolean>,
val imageChecked: MutableState<Boolean>,
) {

companion object {
const val MinActionButtonCount = 1
const val MinActionButtonCount = 0
const val MaxActionButtonCount = 2
const val MinTextCount = 1
const val MaxTextCount = 2
}

val hasImage
get() = imageChecked.value

val hasFirstButton
get() = buttonsCount.value > 0

val hasSecondButton
get() = buttonsCount.value > 1

val hasTwoTextLines
get() = textLinesCount.value > 1
val hasShortMessage
get() = shortMessage.value
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ import com.orange.ods.app.ui.components.utilities.clickOnElement
import com.orange.ods.app.ui.utilities.DrawableManager
import com.orange.ods.app.ui.utilities.code.CodeImplementationColumn
import com.orange.ods.app.ui.utilities.code.FunctionCallCode
import com.orange.ods.app.ui.utilities.composable.Subtitle
import com.orange.ods.compose.OdsComposable
import com.orange.ods.compose.component.banner.OdsBanner
import com.orange.ods.compose.component.chip.OdsChoiceChip
import com.orange.ods.compose.component.chip.OdsChoiceChipsFlowRow
import com.orange.ods.compose.component.listitem.OdsListItem
import com.orange.ods.extension.ifNotNull

Expand All @@ -53,14 +56,18 @@ fun ComponentBanners() {
ComponentCustomizationBottomSheetScaffold(
bottomSheetScaffoldState = rememberBottomSheetScaffoldState(),
bottomSheetContent = {
ComponentCountRow(
title = stringResource(id = R.string.component_banner_text_lines_count),
count = textLinesCount,
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 = BannerCustomizationState.MinTextCount,
maxCount = BannerCustomizationState.MaxTextCount
Subtitle(textRes = R.string.component_banner_message_example, horizontalPadding = true)
OdsChoiceChipsFlowRow(
value = shortMessage.value,
onValueChange = { value -> shortMessage.value = value },
modifier = Modifier.padding(horizontal = dimensionResource(id = com.orange.ods.R.dimen.spacing_m)),
chips = listOf(
OdsChoiceChip(
text = stringResource(id = R.string.component_banner_message_example_short),
value = true
),
OdsChoiceChip(text = stringResource(id = R.string.component_banner_message_example_long), value = false)
)
)
ComponentCountRow(
title = stringResource(id = R.string.component_banner_buttons_count),
Expand All @@ -73,7 +80,7 @@ fun ComponentBanners() {
)
OdsListItem(
text = stringResource(id = R.string.component_banner_image),
trailing = OdsListItem.TrailingSwitch(checked = imageChecked.value, { imageChecked.value = it })
trailing = OdsListItem.TrailingSwitch(checked = hasImage, { imageChecked.value = it })
)
}
) {
Expand All @@ -82,10 +89,12 @@ fun ComponentBanners() {
modifier = Modifier
.verticalScroll(rememberScrollState())
) {
val message = if (hasTwoTextLines) recipe.description else recipe.title
val firstButtonText = stringResource(id = R.string.component_banner_dismiss)
val message = if (hasShortMessage) recipe.title else recipe.description
val firstButtonText = if (hasFirstButton) stringResource(id = R.string.component_banner_dismiss) else null
val onFirstButtonClickText = stringResource(id = R.string.component_element_first_button)
val onFirstButtonClick = { clickOnElement(context, onFirstButtonClickText) }
val onFirstButtonClick = if (hasFirstButton) {
{ clickOnElement(context, onFirstButtonClickText) }
} else null
val secondButtonText = if (hasSecondButton) stringResource(id = R.string.component_banner_detail) else null
val onSecondButtonClickText = stringResource(id = R.string.component_element_second_button)
val onSecondButtonClick = if (hasSecondButton) {
Expand All @@ -97,7 +106,6 @@ fun ComponentBanners() {
compose = {
OdsBanner(
message = message,
firstButton = OdsBanner.Button(firstButtonText, onFirstButtonClick),
image = if (hasImage) {
val painter = rememberAsyncImagePainter(
model = recipe.imageUrl,
Expand All @@ -108,6 +116,7 @@ fun ComponentBanners() {
} else {
null
},
firstButton = ifNotNull(firstButtonText, onFirstButtonClick) { text, onClick -> OdsBanner.Button(text, onClick) },
secondButton = ifNotNull(secondButtonText, onSecondButtonClick) { text, onClick -> OdsBanner.Button(text, onClick) }
)
},
Expand Down Expand Up @@ -139,10 +148,12 @@ fun ComponentBanners() {
name = OdsComposable.OdsBanner.name,
exhaustiveParameters = false,
parameters = {
string("message", if (hasTwoTextLines) recipe.description else recipe.title)
classInstance<OdsBanner.Button>("firstButton") {
text(context.getString(R.string.component_banner_dismiss))
onClick()
string("message", if (hasShortMessage) recipe.title else recipe.description)
if (hasFirstButton) {
classInstance<OdsBanner.Button>("firstButton") {
text(context.getString(R.string.component_banner_dismiss))
onClick()
}
}
if (hasImage) {
classInstance<OdsBanner.Image>("image") {
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@
<!-- Components Banners -->
<string name="component_banners">Banners</string>
<string name="component_banners_description">A banner displays an important message which requires an action to be dismissed.</string>
<string name="component_banner_text_lines_count">Text lines count</string>
<string name="component_banner_message_example">Message example</string>
<string name="component_banner_message_example_short">Short</string>
<string name="component_banner_message_example_long">Long</string>
<string name="component_banner_buttons_count">Buttons count</string>
<string name="component_banner_image">Image</string>
<string name="component_banner_remove_action_button">Remove Line</string>
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- \[Lib\] Update `OdsBottomSheetScaffold` documentation ([#678](https://github.com/Orange-OpenSource/ods-android/issues/678))
- \[Lib\] Update `OdsChip` API to use a unique leading parameter ([#705](https://github.com/Orange-OpenSource/ods-android/issues/705))
- \[Lib\] Update most API types to be clearer for v1 launch ([#701](https://github.com/Orange-OpenSource/ods-android/issues/701))
- \[Lib\] Update `OdsBanner` to allow banner without button and avoid text truncation in banner for accessibility purpose ([#643](https://github.com/Orange-OpenSource/ods-android/issues/643))

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion docs/components/Banners.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ OdsBanner(
Parameter | Default&nbsp;value | Description
-- | -- | --
`message: String` | | Text displayed into the banner
`firstButton: OdsBanner.Button` | | Primary button displayed in the banner
`modifier: Modifier` | `Modifier` | `Modifier` applied to the banner
`image: OdsBanner.Image?` | `null` | Image displayed in the banner in a circle shape
`firstButton: OdsBanner.Button?` | `null` | Primary button displayed in the banner
`secondButton: OdsBanner.Button?` | `null` | Secondary button displayed into the banner next to the primary one
{:.table}
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ import com.orange.ods.xml.utilities.extension.getResourceIdOrNull
class OdsBanner @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : OdsAbstractComposeView(context, attrs) {

var message by mutableStateOf("")
var firstButtonText by mutableStateOf("")
var onFirstButtonClick by mutableStateOf({})
var image by mutableStateOf<Drawable?>(null)
var imageContentDescription by mutableStateOf<String?>(null)
var firstButtonText by mutableStateOf<String?>(null)
var onFirstButtonClick by mutableStateOf<(() -> Unit)?>(null)
var secondButtonText by mutableStateOf<String?>(null)
var onSecondButtonClick by mutableStateOf<(() -> Unit)?>(null)

init {
context.withStyledAttributes(attrs, R.styleable.OdsBanner) {
message = getString(R.styleable.OdsBanner_message).orEmpty()
firstButtonText = getString(R.styleable.OdsBanner_firstButtonText).orEmpty()
image = getResourceIdOrNull(R.styleable.OdsBanner_image)?.let { AppCompatResources.getDrawable(context, it) }
imageContentDescription = getString(R.styleable.OdsBanner_imageContentDescription)
firstButtonText = getString(R.styleable.OdsBanner_firstButtonText)
secondButtonText = getString(R.styleable.OdsBanner_secondButtonText)
}
}
Expand All @@ -50,11 +50,13 @@ class OdsBanner @JvmOverloads constructor(context: Context, attrs: AttributeSet?
override fun OdsContent() {
OdsBanner(
message = message,
firstButton = OdsBanner.Button(firstButtonText, onFirstButtonClick),
image = image?.let { image ->
val painter = rememberDrawablePainter(drawable = image)
OdsBanner.Image(painter, imageContentDescription.orEmpty())
},
firstButton = ifNotNull(firstButtonText, onFirstButtonClick) { text, onClick ->
OdsBanner.Button(text, onClick)
},
secondButton = ifNotNull(secondButtonText, onSecondButtonClick) { text, onClick ->
OdsBanner.Button(text, onClick)
}
Expand Down
2 changes: 1 addition & 1 deletion lib-xml/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@

<declare-styleable name="OdsBanner">
<attr name="message" format="string" />
<attr name="firstButtonText" format="string" />
<attr name="image" format="reference|color" />
<attr name="imageContentDescription" format="string" />
<attr name="firstButtonText" format="string" />
<attr name="secondButtonText" format="string" />
</declare-styleable>

Expand Down
Loading

0 comments on commit e104c59

Please sign in to comment.