diff --git a/components-compose/CHANGELOG.md b/components-compose/CHANGELOG.md index 870532f4..1d1c820f 100644 --- a/components-compose/CHANGELOG.md +++ b/components-compose/CHANGELOG.md @@ -18,6 +18,8 @@ Allowed headings: ### Added +feature/HMA-5091-Android-Jetpack-Compose-Components-SummaryRowView +* `SummaryRowView` added in Organism. * `PasswordInputView` component added with show/hide feature * `requiresSequenceSpacing` parameter added to `TextInputView` to enable additional character spacing for use during sequences diff --git a/components-compose/src/main/java/uk/gov/hmrc/components/compose/organism/summaryrow/SummaryRowView.kt b/components-compose/src/main/java/uk/gov/hmrc/components/compose/organism/summaryrow/SummaryRowView.kt new file mode 100644 index 00000000..681b1b6f --- /dev/null +++ b/components-compose/src/main/java/uk/gov/hmrc/components/compose/organism/summaryrow/SummaryRowView.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2024 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.gov.hmrc.components.compose.organism.summaryrow + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.ripple.LocalRippleTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.focused +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.style.TextOverflow +import uk.gov.hmrc.components.compose.R +import uk.gov.hmrc.components.compose.ui.theme.HmrcRippleTheme +import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme.dimensions +import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme.typography + +@Composable +fun SummaryRowView( + titleText: String, + rows: List<@Composable () -> Unit>, + modifier: Modifier = Modifier, + isBoldTitleTextAppearance: Boolean = true, + titleMaxLines: Int = -1, + icon: Painter = painterResource(id = R.drawable.components_ic_chevron_right), + chevronContentDescription: String = "", + readerTrait: ReaderTrait = ReaderTrait.READER_TRAIT_INFO, + onSummaryRowClicked: (() -> Unit)? = null +) { + if (onSummaryRowClicked != null) { + CompositionLocalProvider(LocalRippleTheme provides HmrcRippleTheme) { + Row( + modifier = modifier.clickable { onSummaryRowClicked.invoke() }, + verticalAlignment = Alignment.CenterVertically + ) { + SummaryRow( + modifier = Modifier + .padding( + top = dimensions.hmrcSpacing16, + bottom = dimensions.hmrcSpacing16, + start = dimensions.hmrcSpacing16 + ) + .weight(1f), + titleText = titleText, + titleMaxLines = titleMaxLines, + isBoldTitleTextAppearance = isBoldTitleTextAppearance, + readerTrait = readerTrait, + rows = rows + ) + Spacer(modifier = Modifier.width(dimensions.hmrcSpacing8)) + Image( + painter = icon, + modifier = Modifier + .semantics { role = Role.Button } + .clickable { onSummaryRowClicked() }, + contentDescription = chevronContentDescription + ) + Spacer(modifier = Modifier.width(dimensions.hmrcSpacing16)) + } + } + } else { + SummaryRow( + modifier = modifier.padding(dimensions.hmrcSpacing16), + titleText = titleText, + titleMaxLines = titleMaxLines, + isBoldTitleTextAppearance = isBoldTitleTextAppearance, + readerTrait = readerTrait, + rows = rows + ) + } +} + +@Composable +private fun SummaryRow( + titleText: String, + isBoldTitleTextAppearance: Boolean, + titleMaxLines: Int, + readerTrait: ReaderTrait, + rows: List<@Composable () -> Unit>, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier) { + Text( + modifier = Modifier + .fillMaxWidth() + .semantics { if (readerTrait == ReaderTrait.READER_TRAIT_INFO) focused = true }, + text = titleText, + style = if (isBoldTitleTextAppearance) typography.h6 else typography.body, + maxLines = if (titleMaxLines == -1) Int.MAX_VALUE else titleMaxLines, + overflow = TextOverflow.Ellipsis + ) + rows.forEach { rowItem -> + Spacer(modifier = Modifier.height(dimensions.hmrcSpacing8)) + Box( + modifier = Modifier + .fillMaxWidth() + .semantics { if (readerTrait == ReaderTrait.READER_TRAIT_INFO) focused = true } + ) { + rowItem() + } + } + } +} + +enum class ReaderTrait { + READER_TRAIT_INFO, + READER_TRAIT_SIMPLE +} diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/data/repository/RepositoryImp.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/data/repository/RepositoryImp.kt index e17fd184..5c10a643 100644 --- a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/data/repository/RepositoryImp.kt +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/data/repository/RepositoryImp.kt @@ -54,6 +54,7 @@ class RepositoryImpl @Inject constructor() : Repository { ComponentMenuItem(ORGANISM_HEADLINE_CARD_VIEW, R.string.organisms_headline_card), ComponentMenuItem(ORGANISM_PRIMARY_CARD_VIEW, R.string.organisms_primary_card), ComponentMenuItem(ORGANISM_ICON_BUTTON_CARD_VIEW, R.string.organisms_icon_button_card), + ComponentMenuItem(ORGANISM_SUMMARY_ROW_VIEW, R.string.organisms_summary_row), ComponentMenuItem(ORGANISM_SEPARATED_VIEW_CONTAINER, R.string.organisms_separated_view_container), ComponentMenuItem(ORGANISM_INFORMATION_MESSAGE_CARD_VIEW, R.string.organisms_info_message_card) ) @@ -86,6 +87,7 @@ class RepositoryImpl @Inject constructor() : Repository { const val ORGANISM_HEADLINE_CARD_VIEW = 1 const val ORGANISM_PRIMARY_CARD_VIEW = 2 const val ORGANISM_ICON_BUTTON_CARD_VIEW = 4 + const val ORGANISM_SUMMARY_ROW_VIEW = 5 const val ORGANISM_SEPARATED_VIEW_CONTAINER = 6 const val ORGANISM_INFORMATION_MESSAGE_CARD_VIEW = 7 } diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/AppNavigator.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/AppNavigator.kt index 2a984e04..d6274bf8 100644 --- a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/AppNavigator.kt +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/AppNavigator.kt @@ -106,6 +106,10 @@ class AppNavigator @Inject constructor() : Navigator{ navigate(OrganismsFragmentDirections.actionOrganismsFragmentToInformationMessageCardViewFragment()) } + override fun Fragment.goToSummaryRowView() { + navigate(OrganismsFragmentDirections.actionOrganismsFragmentToSummaryRowFragment()) + } + override fun Fragment.goBack() { findNavController().popBackStack() } diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/Navigator.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/Navigator.kt index 7987d73d..59b1cf25 100644 --- a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/Navigator.kt +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/navigator/Navigator.kt @@ -67,5 +67,7 @@ interface Navigator { fun Fragment.goToInformationMessageCardView() + fun Fragment.goToSummaryRowView() + fun Fragment.goBack() } diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/OrganismsFragment.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/OrganismsFragment.kt index 4d5c3fbf..08e11986 100644 --- a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/OrganismsFragment.kt +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/OrganismsFragment.kt @@ -31,6 +31,7 @@ import uk.gov.hmrc.sample_compose_fragments.data.repository.RepositoryImpl.Compa import uk.gov.hmrc.sample_compose_fragments.data.repository.RepositoryImpl.Companion.ORGANISM_INFORMATION_MESSAGE_CARD_VIEW import uk.gov.hmrc.sample_compose_fragments.data.repository.RepositoryImpl.Companion.ORGANISM_PRIMARY_CARD_VIEW import uk.gov.hmrc.sample_compose_fragments.data.repository.RepositoryImpl.Companion.ORGANISM_SEPARATED_VIEW_CONTAINER +import uk.gov.hmrc.sample_compose_fragments.data.repository.RepositoryImpl.Companion.ORGANISM_SUMMARY_ROW_VIEW import uk.gov.hmrc.sample_compose_fragments.navigator.Navigator import uk.gov.hmrc.sample_compose_fragments.presentation.screens.ComponentListScreen import uk.gov.hmrc.sample_compose_fragments.presentation.screens.sampletemplate.HmrcSurface @@ -76,6 +77,10 @@ class OrganismsFragment : Fragment(R.layout.fragment_compose_example) { ORGANISM_INFORMATION_MESSAGE_CARD_VIEW -> { with(navigator) { goToInformationMessageCardView() } } + + ORGANISM_SUMMARY_ROW_VIEW -> { + with(navigator) { goToSummaryRowView() } + } } }) } diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/SummaryRowFragment.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/SummaryRowFragment.kt new file mode 100644 index 00000000..cc86cc93 --- /dev/null +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/fragment/organisms/SummaryRowFragment.kt @@ -0,0 +1,41 @@ +package uk.gov.hmrc.sample_compose_fragments.presentation.fragment.organisms + +import android.os.Bundle +import android.view.View +import android.widget.Toast +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.fragment.app.Fragment +import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme +import uk.gov.hmrc.components.compose.ui.theme.rememberWindowSizeClass +import uk.gov.hmrc.sample_compose_components.R +import uk.gov.hmrc.sample_compose_components.databinding.FragmentComposeExampleBinding +import uk.gov.hmrc.sample_compose_fragments.presentation.screens.organisms.InformationMessageCardViewScreen +import uk.gov.hmrc.sample_compose_fragments.presentation.screens.organisms.SummaryRowViewScreen +import uk.gov.hmrc.sample_compose_fragments.presentation.screens.sampletemplate.HmrcSurface + +class SummaryRowFragment : Fragment(R.layout.fragment_compose_example) { + + private lateinit var binding: FragmentComposeExampleBinding + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding = FragmentComposeExampleBinding.bind(view) + binding.composeView.apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + val window = rememberWindowSizeClass() + HmrcTheme(window) { + HmrcSurface { + SummaryRowViewScreen { + showToast(getString(R.string.cta_pressed)) + } + } + } + } + } + } + + private fun showToast(text: String) { + Toast.makeText(context, text, Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/organisms/SummaryRowViewScreen.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/organisms/SummaryRowViewScreen.kt new file mode 100644 index 00000000..3ab02d98 --- /dev/null +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/organisms/SummaryRowViewScreen.kt @@ -0,0 +1,270 @@ +package uk.gov.hmrc.sample_compose_fragments.presentation.screens.organisms + +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import uk.gov.hmrc.components.compose.molecule.multiColumnRowView.MultiColumnRowItem +import uk.gov.hmrc.components.compose.molecule.multiColumnRowView.MultiColumnRowView +import uk.gov.hmrc.components.compose.organism.HmrcCardView +import uk.gov.hmrc.components.compose.organism.container.SeparatedViewContainer +import uk.gov.hmrc.components.compose.organism.summaryrow.ReaderTrait +import uk.gov.hmrc.components.compose.organism.summaryrow.SummaryRowView +import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme.dimensions +import uk.gov.hmrc.sample_compose_components.R +import uk.gov.hmrc.sample_compose_fragments.presentation.screens.sampletemplate.ExamplesSlot +import uk.gov.hmrc.sample_compose_fragments.presentation.screens.sampletemplate.PlaceholderSlot +import uk.gov.hmrc.sample_compose_fragments.presentation.screens.sampletemplate.ScreenScrollViewColumn + +@Composable +fun SummaryRowViewScreen(onClickAction: () -> Unit) { + ScreenScrollViewColumn { + PlaceholderSlot { + SummaryRowView( + titleText = stringResource(id = R.string.summary_row_placeholder_title), + rows = listOf { + MultiColumnRowView( + modifier = Modifier, + columnList = listOf( + MultiColumnRowItem( + text = stringResource(id = R.string.multi_column_row_placeholder_text1) + ), + MultiColumnRowItem( + text = stringResource(id = R.string.multi_column_row_placeholder_text2) + ), + MultiColumnRowItem( + text = stringResource(id = R.string.multi_column_row_placeholder_text3) + ) + ) + ) + } + ) { + onClickAction() + } + } + + ExamplesSlot { + HmrcCardView(modifier = Modifier.padding(bottom = dimensions.hmrcSpacing16)) { + SeparatedViewContainer( + showDivider = SeparatedViewContainer.DividerMode.SHOW_DIVIDER_MIDDLE, + dividerHorizontalPadding = dimensions.hmrcSpacing16, + views = listOf( + { + // Example : 1 + SummaryRowView( + titleText = stringResource(id = R.string.summary_row_example_1a_title), + isBoldTitleTextAppearance = false, + chevronContentDescription = stringResource( + id = R.string.summary_row_example_1a_accessibility_message + ), + rows = listOf( + + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1a_row1_text1 + ) + ), + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1a_row1_text2 + ) + ), + ) + ) + }, + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1a_row2_text1 + ) + ), + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1a_row2_text2 + ) + ), + ) + ) + }, + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1a_row3_text1 + ) + ), + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1a_row3_text2 + ) + ), + ) + ) + } + + + ) + ) { + onClickAction() + } + }, + + { + // Example : 2 + SummaryRowView( + titleText = stringResource(id = R.string.summary_row_example_1b_title), + rows = listOf( + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1b_row1_text1 + ) + ), + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1b_row1_text2 + ) + ), + ) + ) + }, + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1b_row2_text1 + ) + ), + MultiColumnRowItem( + text = stringResource( + id = R.string.summary_row_example_1b_row2_text2 + ) + ), + ) + ) + } + ) + ) { + onClickAction() + } + + } + ) + ) + } + + // Example : 3 + HmrcCardView(modifier = Modifier.padding(bottom = dimensions.hmrcSpacing16)) { + SummaryRowView( + titleText = stringResource(id = R.string.summary_row_example_2_title), + readerTrait = ReaderTrait.READER_TRAIT_SIMPLE, + rows = listOf { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem( + text = stringResource(id = R.string.summary_row_example_2_row1_text1) + ) + ) + ) + } + ) { + onClickAction() + } + } + + HmrcCardView(modifier = Modifier.padding(bottom = dimensions.hmrcSpacing16)) { + SeparatedViewContainer( + showDivider = SeparatedViewContainer.DividerMode.SHOW_DIVIDER_MIDDLE, + dividerHorizontalPadding = dimensions.hmrcSpacing16, + views = listOf( + { + // Example : 4 + SummaryRowView( + titleText = stringResource(id = R.string.longer_text), + rows = listOf { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem(text = stringResource(id = R.string.longest_text)), + ) + ) + } + ) { + onClickAction() + } + }, + + { + // Example : 5 + SummaryRowView( + titleText = stringResource(id = R.string.longer_text), + rows = listOf { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem(text = stringResource(id = R.string.long_text)), + MultiColumnRowItem(text = stringResource(id = R.string.long_text)), + ) + ) + } + ) + }, + { + // Example : 6 + SummaryRowView( + titleText = stringResource(id = R.string.longer_text), + titleMaxLines = 2, + rows = listOf( + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem(text = stringResource(id = R.string.long_text)), + MultiColumnRowItem(text = stringResource(id = R.string.long_text)), + MultiColumnRowItem(text = stringResource(id = R.string.long_text)), + ) + ) + }, + { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem(text = stringResource(id = R.string.long_text)) + ) + ) + } + ) + ) { + onClickAction() + } + } + ) + ) + } + + // Example : 7 + HmrcCardView(modifier = Modifier.padding(bottom = dimensions.hmrcSpacing16)) { + SummaryRowView( + titleText = stringResource(id = R.string.summary_row_example_2_title), + icon = painterResource(id = R.drawable.ic_calendar), + readerTrait = ReaderTrait.READER_TRAIT_SIMPLE, + rows = listOf { + MultiColumnRowView( + columnList = listOf( + MultiColumnRowItem(text = stringResource(id = R.string.long_text)) + ) + ) + } + ) { + onClickAction() + } + } + } + } +} diff --git a/sample-compose-fragments/src/main/res/drawable/ic_calendar.xml b/sample-compose-fragments/src/main/res/drawable/ic_calendar.xml new file mode 100644 index 00000000..37903c4a --- /dev/null +++ b/sample-compose-fragments/src/main/res/drawable/ic_calendar.xml @@ -0,0 +1,12 @@ + + + diff --git a/sample-compose-fragments/src/main/res/navigation/nav_graph.xml b/sample-compose-fragments/src/main/res/navigation/nav_graph.xml index a2f46652..93dcb979 100644 --- a/sample-compose-fragments/src/main/res/navigation/nav_graph.xml +++ b/sample-compose-fragments/src/main/res/navigation/nav_graph.xml @@ -39,6 +39,9 @@ + @@ -49,7 +52,7 @@ android:id="@+id/iconButtonCardViewFragment" android:name="uk.gov.hmrc.sample_compose_fragments.presentation.fragment.organisms.IconButtonCardViewFragment" android:label="@string/organisms_icon_button_card" - tools:layout="@layout/fragment_compose_example"/> + tools:layout="@layout/fragment_compose_example" /> + tools:layout="@layout/fragment_compose_example" /> + tools:layout="@layout/fragment_compose_example" /> + tools:layout="@layout/fragment_compose_example" /> + \ No newline at end of file