Skip to content

Commit

Permalink
feat: [ANDROAPP-6399] selectable list card
Browse files Browse the repository at this point in the history
  • Loading branch information
mmmateos authored and Balcan committed Oct 1, 2024
1 parent 7889fac commit b21b39a
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import org.hisp.dhis.mobile.ui.designsystem.component.ListCard
import org.hisp.dhis.mobile.ui.designsystem.component.ListCardDescriptionModel
import org.hisp.dhis.mobile.ui.designsystem.component.ListCardTitleModel
import org.hisp.dhis.mobile.ui.designsystem.component.MetadataAvatarSize
import org.hisp.dhis.mobile.ui.designsystem.component.SelectionState
import org.hisp.dhis.mobile.ui.designsystem.component.internal.ImageCardData
import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberAdditionalInfoColumnState
import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberListCardState
Expand Down Expand Up @@ -650,6 +651,53 @@ fun ListCardScreen(horizontal: Boolean) {
onCardClick = {},
)
}

ColumnComponentContainer("Selectable list cards") {
var selectionState by remember {
mutableStateOf(SelectionState.NONE)
}

ListCard(
listCardState = rememberListCardState(
title = ListCardTitleModel(text = "Palak Khanna, F, 61"),
lastUpdated = "5 hours",
additionalInfoColumnState = rememberAdditionalInfoColumnState(
additionalInfoList = basicAdditionalItemList.toMutableList(),
syncProgressItem = syncProgressItem(),
),
selectionState = selectionState,
),
listAvatar = {
Avatar(
style = AvatarStyleData.Text("P"),
)
},
onCardClick = {},
onCardSelected = { selectionState = it },
)
var selectionState2 by remember {
mutableStateOf(SelectionState.NONE)
}

ListCard(
listCardState = rememberListCardState(
title = ListCardTitleModel(text = "Palak Khanna, F, 61"),
lastUpdated = "5 hours",
additionalInfoColumnState = rememberAdditionalInfoColumnState(
additionalInfoList = basicAdditionalItemListWithLongKeyText.toMutableList(),
syncProgressItem = syncProgressItem(),
),
selectionState = selectionState2,
),
listAvatar = {
Avatar(
style = AvatarStyleData.Text("P"),
)
},
onCardClick = {},
onCardSelected = { selectionState2 = it },
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -53,6 +55,7 @@ import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor
import org.hisp.dhis.mobile.ui.designsystem.theme.dropShadow
import org.hisp.dhis.mobile.ui.designsystem.theme.hoverPointerIcon

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun BaseCard(
modifier: Modifier = Modifier,
Expand All @@ -62,6 +65,8 @@ fun BaseCard(
expandable: Boolean,
itemVerticalPadding: Dp?,
onSizeChanged: ((IntSize) -> Unit)?,
isSelectionMode: Boolean,
onCardSelected: () -> Unit,
content: @Composable () -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
Expand All @@ -74,13 +79,17 @@ fun BaseCard(
})
.background(color = TextColor.OnPrimary, shape = RoundedCornerShape(Radius.S))
.clip(shape = RoundedCornerShape(Radius.S))
.clickable(
.combinedClickable(
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple(
color = SurfaceColor.Primary,
),
onClick = onCardClick,
onClick = when {
isSelectionMode -> onCardSelected
else -> onCardClick
},
onLongClick = onCardSelected,
)
.hoverPointerIcon(true)
.padding(paddingValues)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fun ListCard(
actionButton: @Composable (() -> Unit)? = null,
onCardClick: () -> Unit,
onSizeChanged: ((IntSize) -> Unit)? = null,
onCardSelected: ((SelectionState) -> Unit)? = null,
) {
BaseCard(
modifier = modifier,
Expand All @@ -102,14 +103,23 @@ fun ListCard(
expandable = listCardState.expandable,
itemVerticalPadding = listCardState.itemVerticalPadding,
onSizeChanged = onSizeChanged,
isSelectionMode = listCardState.selectionState != SelectionState.NONE,
onCardSelected = {
onCardSelected?.invoke(listCardState.selectionState.changeState())
},
paddingValues = getPaddingValues(
expandable = listCardState.expandable,
hasShadow = listCardState.shadow,
hasAvatar = listAvatar != null,
),
) {
Row(horizontalArrangement = spacedBy(Spacing.Spacing16)) {
listAvatar?.invoke()
when (listCardState.selectionState) {
SelectionState.SELECTABLE -> UnselectedItemIcon()
SelectionState.SELECTED -> SelectedItemIcon()
SelectionState.NONE -> listAvatar?.invoke()
}

Column(Modifier.fillMaxWidth().weight(1f)) {
Row(horizontalArrangement = Arrangement.SpaceBetween) {
ListCardTitle(
Expand Down Expand Up @@ -247,6 +257,8 @@ fun VerticalInfoListCard(
),
expandable = listCardState.expandable,
itemVerticalPadding = listCardState.itemVerticalPadding,
isSelectionMode = false,
onCardSelected = {},
onSizeChanged = onSizeChanged,
) {
Column(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.hisp.dhis.mobile.ui.designsystem.component

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckBoxOutlineBlank
import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import org.hisp.dhis.mobile.ui.designsystem.theme.Radius
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing
import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor
import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor

enum class SelectionState {
SELECTABLE,
SELECTED,
NONE,
;

fun changeState(): SelectionState {
return when (this) {
SELECTABLE -> SELECTED
SELECTED -> SELECTABLE
NONE -> SELECTED
}
}
}

@Composable
fun UnselectedItemIcon(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.size(Spacing.Spacing40)
.background(
color = SurfaceColor.PrimaryContainer,
shape = RoundedCornerShape(Radius.Full),
),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.Filled.CheckBoxOutlineBlank,
contentDescription = "Unselected",
tint = SurfaceColor.ContainerHighest,
)
}
}

@Composable
fun SelectedItemIcon(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.size(Spacing.Spacing40)
.background(
color = SurfaceColor.Primary,
shape = RoundedCornerShape(Radius.Full),
),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.Filled.Done,
contentDescription = "Selected",
tint = TextColor.OnPrimary,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.unit.Dp
import org.hisp.dhis.mobile.ui.designsystem.component.ListCardDescriptionModel
import org.hisp.dhis.mobile.ui.designsystem.component.ListCardTitleModel
import org.hisp.dhis.mobile.ui.designsystem.component.SelectionState

@Stable
interface ListCardState {
Expand All @@ -17,6 +18,7 @@ interface ListCardState {
val shadow: Boolean
val expandable: Boolean
val itemVerticalPadding: Dp?
val selectionState: SelectionState

fun descriptionBasedOnLoading() = description?.takeIf { !loading }
fun lastUpdateBasedOnLoading() = lastUpdated?.takeIf { !loading }
Expand All @@ -32,6 +34,7 @@ internal class ListCardStateImpl(
override val shadow: Boolean,
override val expandable: Boolean,
override val itemVerticalPadding: Dp?,
override val selectionState: SelectionState,
) : ListCardState

@Composable
Expand All @@ -44,12 +47,14 @@ fun rememberListCardState(
shadow: Boolean = true,
expandable: Boolean = false,
itemVerticalPadding: Dp? = null,
selectionState: SelectionState = SelectionState.NONE,
): ListCardState = remember(
description,
itemVerticalPadding,
loading,
additionalInfoColumnState,
lastUpdated,
selectionState,
) {
ListCardStateImpl(
title,
Expand All @@ -60,5 +65,6 @@ fun rememberListCardState(
shadow,
expandable,
itemVerticalPadding,
selectionState,
)
}

0 comments on commit b21b39a

Please sign in to comment.