diff --git a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/others/ChipsScreen.kt b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/others/ChipsScreen.kt index ebc03034b..da5dc682e 100644 --- a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/others/ChipsScreen.kt +++ b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/others/ChipsScreen.kt @@ -2,12 +2,17 @@ package org.hisp.dhis.common.screens.others import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.AssistChipDefaults +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import org.hisp.dhis.mobile.ui.designsystem.component.AssistChip import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer import org.hisp.dhis.mobile.ui.designsystem.component.FilterChip import org.hisp.dhis.mobile.ui.designsystem.component.InputChip @@ -58,5 +63,46 @@ fun ChipsScreen() { SubTitle("Filter Chips With badges") FilterChip(label = "Label", selected = true, badge = "3") FilterChip(label = "Label", selected = false, badge = "3") + Spacer(Modifier.size(Spacing.Spacing18)) + + SubTitle("Assist Chips") + // var isSelected5 by remember { mutableStateOf(false) } + AssistChip( + label = "Label", + onClick = { }, + ) + AssistChip( + label = "Label", + icon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = "search icon", + modifier = Modifier + .size(AssistChipDefaults.IconSize), + ) + }, + onClick = { }, + ) + Spacer(Modifier.size(Spacing.Spacing18)) + + SubTitle("Assist Chips With badges") + AssistChip( + label = "Label", + icon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = "search icon", + modifier = Modifier + .size(AssistChipDefaults.IconSize), + ) + }, + onClick = {}, + badge = "2", + ) + AssistChip( + label = "Label", + onClick = {}, + badge = "4", + ) } } diff --git a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/AssistChipSanpshotTest.kt b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/AssistChipSanpshotTest.kt new file mode 100644 index 000000000..bc2f15d29 --- /dev/null +++ b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/AssistChipSanpshotTest.kt @@ -0,0 +1,45 @@ +package org.hisp.dhis.mobile.ui.designsystem + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.AssistChipDefaults +import androidx.compose.material3.Icon +import androidx.compose.ui.Modifier +import org.hisp.dhis.mobile.ui.designsystem.component.AssistChip +import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer +import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing +import org.junit.Rule +import org.junit.Test + +class AssistChipSanpshotTest { + @get:Rule + val paparazzi = paparazzi() + + @Test + fun launchAssistChip() { + paparazzi.snapshot { + ColumnComponentContainer(modifier = Modifier.padding(Spacing.Spacing10)) { + AssistChip( + label = "Label", + icon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = "search icon", + modifier = Modifier + .size(AssistChipDefaults.IconSize), + ) + }, + onClick = {}, + badge = "3", + ) + AssistChip( + label = "Label", + onClick = {}, + badge = "3", + ) + } + } + } +} diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/AssistChip.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/AssistChip.kt new file mode 100644 index 000000000..384a53955 --- /dev/null +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/AssistChip.kt @@ -0,0 +1,97 @@ +package org.hisp.dhis.mobile.ui.designsystem.component + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.offset +import androidx.compose.material.ripple.LocalRippleTheme +import androidx.compose.material3.AssistChip +import androidx.compose.material3.AssistChipDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.unit.IntOffset +import org.hisp.dhis.mobile.ui.designsystem.theme.Outline +import org.hisp.dhis.mobile.ui.designsystem.theme.Ripple +import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor +import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor + +/** + * DHIS2 [AssistChip] button with custom icon slot. + * wraps Material 3 [AssistChip]. + * AssistChips are used to trigger actions. + * @param label: the text to be shown. + * @param icon: custom leading icon to be shown, use AssistChipDefaults in the + * Icon composable modifier to set the size of the icon. + * @param enabled: controls the enabled state. "False" will disabled the component + * @param modifier: optional [Modifier]. + * @param onClick: Will be called when the user taps the chip. + * @param badge: the text to be displayed within the badge. + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AssistChip( + modifier: Modifier = Modifier, + label: String, + icon: @Composable (() -> Unit)? = null, + enabled: Boolean = true, + onClick: (() -> Unit), + badge: String? = null, +) { + val interactionSource = remember { MutableInteractionSource() } + val isPressed by interactionSource.collectIsPressedAsState() + + Box(modifier = Modifier) { + CompositionLocalProvider(LocalRippleTheme provides Ripple.CustomDHISRippleTheme()) { + AssistChip( + onClick = { onClick.invoke() }, + label = { + Text( + label, + color = TextColor.OnSurfaceVariant, + ) + }, + modifier = modifier, + enabled = enabled, + colors = if (isPressed) { + AssistChipDefaults.assistChipColors( + containerColor = SurfaceColor.Container, + leadingIconContentColor = TextColor.OnSurfaceVariant, + ) + } else { + AssistChipDefaults.assistChipColors( + containerColor = SurfaceColor.SurfaceBright, + leadingIconContentColor = TextColor.OnSurfaceVariant, + ) + }, + border = AssistChipDefaults.assistChipBorder( + borderColor = Outline.Dark, + ), + leadingIcon = { + icon?.invoke() + }, + + ) + } + badge?.let { + var offset by remember { mutableStateOf(IntOffset(0, 0)) } + Badge( + modifier = Modifier + .align(Alignment.TopEnd) + .onSizeChanged { offset = IntOffset(it.width / 3, it.height / 3) } + .offset { offset } + .testTag("ASSIST_CHIP_BADGE"), + text = badge, + ) + } + } +} diff --git a/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/AssistChipTest.kt b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/AssistChipTest.kt new file mode 100644 index 000000000..a9eda1a57 --- /dev/null +++ b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/AssistChipTest.kt @@ -0,0 +1,39 @@ +package org.hisp.dhis.mobile.ui.designsystem.component + +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.AssistChipDefaults +import androidx.compose.material3.Icon +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import org.junit.Rule +import org.junit.Test + +class AssistChipTest { + + @get:Rule + val rule = createComposeRule() + + @Test + fun assistChipShouldDisplayBadges() { + rule.setContent { + AssistChip( + label = "Label", + icon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = "search icon", + modifier = Modifier + .size(AssistChipDefaults.IconSize), + ) + }, + onClick = {}, + badge = "2", + ) + } + + rule.onNodeWithTag("ASSIST_CHIP_BADGE").assertExists() + } +}