diff --git a/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt b/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt index a6ae754944..f04f4dc273 100644 --- a/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt +++ b/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt @@ -29,13 +29,13 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.analytics.api.AnalyticsOptInEvents import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.background.OnboardingBackground import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.ClickableLinkText -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart @@ -89,10 +89,10 @@ private fun AnalyticsOptInHeader( Column( horizontalAlignment = Alignment.CenterHorizontally, ) { - PageTitle( - modifier = Modifier.padding(top = 60.dp, bottom = 12.dp), + IconTitleSubtitleMolecule( + modifier = Modifier.padding(top = 60.dp, bottom = 28.dp), title = stringResource(id = R.string.screen_analytics_prompt_title, state.applicationName), - subtitle = stringResource(id = R.string.screen_analytics_prompt_help_us_improve), + subTitle = stringResource(id = R.string.screen_analytics_prompt_help_us_improve), iconStyle = BigIcon.Style.Default(CompoundIcons.Chart()) ) if (state.hasPolicyLink) { diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt index 444c311a63..f23b9bafcd 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -31,10 +31,10 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.ftue.impl.R import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.background.OnboardingBackground import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -59,7 +59,7 @@ fun NotificationsOptInView( .statusBarsPadding() .fillMaxSize(), background = { OnboardingBackground() }, - header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 12.dp)) }, + header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 28.dp)) }, footer = { NotificationsOptInFooter(state) }, ) { NotificationsOptInContent() @@ -70,10 +70,10 @@ fun NotificationsOptInView( private fun NotificationsOptInHeader( modifier: Modifier = Modifier, ) { - PageTitle( + IconTitleSubtitleMolecule( modifier = modifier, title = stringResource(R.string.screen_notification_optin_title), - subtitle = stringResource(R.string.screen_notification_optin_subtitle), + subTitle = stringResource(R.string.screen_notification_optin_subtitle), iconStyle = BigIcon.Style.Default(CompoundIcons.NotificationsSolid()), ) } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt index 9839f3bf7c..74eed0115c 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt @@ -24,9 +24,9 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.ftue.impl.R import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button @@ -65,10 +65,11 @@ fun ChooseSelfVerificationModeView( ) }, header = { - PageTitle( + IconTitleSubtitleMolecule( + modifier = Modifier.padding(bottom = 16.dp), iconStyle = BigIcon.Style.Default(CompoundIcons.LockSolid()), title = stringResource(id = R.string.screen_identity_confirmation_title), - subtitle = stringResource(id = R.string.screen_identity_confirmation_subtitle) + subTitle = stringResource(id = R.string.screen_identity_confirmation_subtitle) ) }, footer = { diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationState.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationState.kt index 95f81af479..fdc9f373d4 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationState.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationState.kt @@ -36,5 +36,9 @@ data class IncomingVerificationState( data object Canceled : Step data object Completed : Step data object Failure : Step + + val isTimeLimited: Boolean + get() = this is Initial || + this is Verifying } } diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationView.kt index 12bfe99fcd..4d51b0ca4f 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationView.kt @@ -8,6 +8,7 @@ package io.element.android.features.verifysession.impl.incoming import androidx.activity.compose.BackHandler +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth @@ -19,6 +20,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.ProgressBarRangeInfo +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.focused +import androidx.compose.ui.semantics.progressBarRangeInfo +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -30,9 +36,9 @@ import io.element.android.features.verifysession.impl.incoming.ui.SessionDetails import io.element.android.features.verifysession.impl.ui.VerificationBottomMenu import io.element.android.features.verifysession.impl.ui.VerificationContentVerifying import io.element.android.features.verifysession.impl.ui.VerificationUserProfileContent +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -140,10 +146,26 @@ private fun IncomingVerificationHeader(step: Step, request: VerificationRequest. } Step.Failure -> R.string.screen_session_verification_request_failure_subtitle } - PageTitle( + val timeLimitMessage = if (step.isTimeLimited) { + stringResource(CommonStrings.a11y_time_limited_action_required) + } else { + "" + } + IconTitleSubtitleMolecule( + modifier = Modifier + .padding(bottom = 16.dp) + .semantics(mergeDescendants = true) { + contentDescription = timeLimitMessage + focused = true + if (iconStyle == BigIcon.Style.Loading) { + // Same code than Modifier.progressSemantics() + progressBarRangeInfo = ProgressBarRangeInfo.Indeterminate + } + } + .focusable(), iconStyle = iconStyle, title = stringResource(id = titleTextId), - subtitle = stringResource(id = subtitleTextId) + subTitle = stringResource(id = subtitleTextId), ) } @@ -187,7 +209,9 @@ private fun ContentInitial( } is VerificationRequest.Incoming.User -> { Column( - modifier = Modifier.fillMaxWidth().padding(top = 24.dp), + modifier = Modifier + .fillMaxWidth() + .padding(top = 24.dp), ) { VerificationUserProfileContent( userId = request.details.senderProfile.userId, diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/ui/SessionDetailsView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/ui/SessionDetailsView.kt index 83d82ec795..da3471ddc1 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/ui/SessionDetailsView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/ui/SessionDetailsView.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.verifysession.impl.R @@ -46,7 +47,8 @@ fun SessionDetailsView( color = ElementTheme.colors.borderDisabled, shape = RoundedCornerShape(8.dp) ) - .padding(24.dp), + .padding(24.dp) + .semantics(mergeDescendants = true) {}, verticalArrangement = Arrangement.spacedBy(12.dp), ) { Row( @@ -76,6 +78,7 @@ fun SessionDetailsView( label = stringResource(CommonStrings.common_device_id), text = deviceId.value, modifier = Modifier.weight(5f), + spellText = true, ) } } diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationState.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationState.kt index 02653124ab..9b2d5f2e40 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationState.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationState.kt @@ -29,5 +29,11 @@ data class OutgoingVerificationState( data class Verifying(val data: SessionVerificationData, val state: AsyncData) : Step data object Completed : Step data object Exit : Step + + val isTimeLimited: Boolean + get() = this is Initial || + this is AwaitingOtherDeviceResponse || + this is Ready || + this is Verifying } } diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt index 8669472cf4..f58a5ac76a 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt @@ -9,6 +9,7 @@ package io.element.android.features.verifysession.impl.outgoing import androidx.activity.compose.BackHandler import androidx.compose.foundation.clickable +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -22,6 +23,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.ProgressBarRangeInfo +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.focused +import androidx.compose.ui.semantics.progressBarRangeInfo +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -31,9 +37,9 @@ import io.element.android.features.verifysession.impl.outgoing.OutgoingVerificat import io.element.android.features.verifysession.impl.ui.VerificationBottomMenu import io.element.android.features.verifysession.impl.ui.VerificationContentVerifying import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -180,11 +186,26 @@ private fun OutgoingVerificationHeader(step: Step, request: VerificationRequest. } is Step.Exit -> return } - - PageTitle( + val timeLimitMessage = if (step.isTimeLimited) { + stringResource(CommonStrings.a11y_time_limited_action_required) + } else { + "" + } + IconTitleSubtitleMolecule( + modifier = Modifier + .padding(bottom = 16.dp) + .semantics(mergeDescendants = true) { + contentDescription = timeLimitMessage + focused = true + if (iconStyle == BigIcon.Style.Loading) { + // Same code than Modifier.progressSemantics() + progressBarRangeInfo = ProgressBarRangeInfo.Indeterminate + } + } + .focusable(), iconStyle = iconStyle, title = stringResource(id = titleTextId), - subtitle = stringResource(id = subtitleTextId) + subTitle = stringResource(id = subtitleTextId), ) } diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt index b2010bd61c..7a31a26cbb 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt @@ -24,6 +24,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -39,14 +41,20 @@ internal fun VerificationContentVerifying( modifier: Modifier = Modifier, ) { Box( - modifier = modifier.fillMaxSize().padding(bottom = 20.dp), + modifier = modifier + .fillMaxSize() + .padding(bottom = 20.dp), contentAlignment = Alignment.Center ) { when (data) { is SessionVerificationData.Decimals -> { - val text = data.decimals.joinToString(separator = " - ") { it.toString() } + val text = data.decimals.joinToString(separator = " - ") Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .semantics { + contentDescription = data.decimals.joinToString() + }, text = text, style = ElementTheme.typography.fontHeadingLgBold, color = ElementTheme.colors.textPrimary, @@ -57,7 +65,9 @@ internal fun VerificationContentVerifying( // We want each row to have up to 4 emojis val rows = data.emojis.chunked(4) Column( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .semantics(mergeDescendants = true) {}, verticalArrangement = Arrangement.spacedBy(40.dp), ) { rows.forEach { emojis -> diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/TextWithLabelMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/TextWithLabelMolecule.kt index 2d22ef38a0..cc195ca686 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/TextWithLabelMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/TextWithLabelMolecule.kt @@ -10,14 +10,26 @@ package io.element.android.libraries.designsystem.atomic.molecules import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.theme.components.Text +/** + * Display a label and a text in a column. + * @param label the label to display + * @param text the text to display + * @param modifier the modifier to apply to this layout + * @param spellText if true, the text will be spelled out in the content description for accessibility. + * Useful for deviceId for instance, that the screen reader will read as a list of letters instead of trying to read a + * word of random characters. + */ @Composable fun TextWithLabelMolecule( label: String, text: String, modifier: Modifier = Modifier, + spellText: Boolean = false, ) { Column(modifier = modifier) { Text( @@ -26,6 +38,11 @@ fun TextWithLabelMolecule( color = ElementTheme.colors.textSecondary, ) Text( + modifier = Modifier.semantics { + if (spellText) { + contentDescription = text.toList().joinToString() + } + }, text = text, style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textPrimary, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt index bf549ecda2..a6af316399 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt @@ -22,8 +22,8 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -69,9 +69,10 @@ fun FlowStepPage( ) }, header = { - PageTitle( + IconTitleSubtitleMolecule( + modifier = Modifier.padding(bottom = 16.dp), title = title, - subtitle = subTitle, + subTitle = subTitle, iconStyle = iconStyle, ) }, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PageTitle.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PageTitle.kt deleted file mode 100644 index 55b8967169..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PageTitle.kt +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.designsystem.components - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -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.text.AnnotatedString -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp -import io.element.android.compound.theme.ElementTheme -import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.components.TextButton - -/** - * Compound component that displays a big icon, a title, an optional subtitle and an optional call to action component. - * - * @param title the title to display - * @param iconStyle the style of the [BigIcon] to display - * @param modifier the modifier to apply to this layout - * @param subtitle the optional subtitle to display. It defaults to `null` - * @param callToAction the optional call to action component to display. It defaults to `null` - */ -@Composable -fun PageTitle( - title: AnnotatedString, - iconStyle: BigIcon.Style, - modifier: Modifier = Modifier, - subtitle: AnnotatedString? = null, - callToAction: @Composable (() -> Unit)? = null, -) { - Column( - modifier = modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - BigIcon(style = iconStyle) - Column( - modifier = Modifier.padding(vertical = 16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text( - modifier = Modifier.fillMaxWidth(), - text = title, - style = ElementTheme.typography.fontHeadingMdBold, - color = ElementTheme.colors.textPrimary, - textAlign = TextAlign.Center, - ) - - subtitle?.let { - Text( - modifier = Modifier.fillMaxWidth(), - text = it, - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - } - } - callToAction?.invoke() - } -} - -/** - * Compound component that displays a big icon, a title, an optional subtitle and an optional call to action component. - * - * @param title the title to display - * @param iconStyle the style of the [BigIcon] to display - * @param modifier the modifier to apply to this layout - * @param subtitle the optional subtitle to display. It defaults to `null` - * @param callToAction the optional call to action component to display. It defaults to `null` - */ -@Composable -fun PageTitle( - title: String, - iconStyle: BigIcon.Style, - modifier: Modifier = Modifier, - subtitle: String? = null, - callToAction: @Composable (() -> Unit)? = null, -) = PageTitle( - title = AnnotatedString(title), - iconStyle = iconStyle, - modifier = modifier, - subtitle = subtitle?.let { AnnotatedString(it) }, - callToAction = callToAction -) - -@PreviewsDayNight -@Composable -internal fun PageTitleWithIconFullPreview(@PreviewParameter(BigIconStyleProvider::class) style: BigIcon.Style) { - ElementPreview { - PageTitle( - modifier = Modifier.padding(top = 24.dp), - title = AnnotatedString("Headline"), - subtitle = AnnotatedString("Description goes here"), - iconStyle = style, - callToAction = { - TextButton(text = "Learn more", onClick = {}) - } - ) - } -} - -@PreviewsDayNight -@Composable -internal fun PageTitleWithIconMinimalPreview() { - ElementPreview { - PageTitle( - modifier = Modifier.padding(top = 24.dp), - title = "Headline", - iconStyle = BigIcon.Style.Default(CompoundIcons.CheckCircleSolid()), - ) - } -} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt index a35099cd19..121f23a79b 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt @@ -11,7 +11,9 @@ import androidx.compose.foundation.background 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.size import androidx.compose.material3.ExperimentalMaterial3Api @@ -28,8 +30,8 @@ import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button @@ -57,14 +59,15 @@ fun MediaDeleteConfirmationBottomSheet( .fillMaxWidth() .padding(horizontal = 16.dp), ) { - PageTitle( + IconTitleSubtitleMolecule( modifier = Modifier .fillMaxWidth() .padding(vertical = 16.dp, horizontal = 8.dp), title = stringResource(R.string.screen_media_browser_delete_confirmation_title), iconStyle = BigIcon.Style.Default(CompoundIcons.Delete(), useCriticalTint = true), - subtitle = stringResource(R.string.screen_media_browser_delete_confirmation_subtitle), + subTitle = stringResource(R.string.screen_media_browser_delete_confirmation_subtitle), ) + Spacer(modifier = Modifier.height(16.dp)) MediaRow( modifier = Modifier .fillMaxWidth() diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt index 23f68c290d..a48ff93d71 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt @@ -44,9 +44,9 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.background.OnboardingBackground import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.async.AsyncFailure import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview @@ -472,14 +472,14 @@ private fun EmptyContent( modifier = Modifier.fillMaxSize(), ) { OnboardingBackground() - PageTitle( + IconTitleSubtitleMolecule( modifier = Modifier .fillMaxWidth() .padding(top = 44.dp) .padding(24.dp), title = stringResource(titleRes), iconStyle = BigIcon.Style.Default(icon), - subtitle = stringResource(subtitleRes), + subTitle = stringResource(subtitleRes), ) } } diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt index a45791a6d0..d34dabcb9f 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt @@ -78,8 +78,6 @@ class KonsistPreviewTest { "MessagesReactionButtonAddPreview", "MessagesReactionButtonExtraPreview", "MessagesViewWithIdentityChangePreview", - "PageTitleWithIconFullPreview", - "PageTitleWithIconMinimalPreview", "PendingMemberRowWithLongNamePreview", "PinUnlockViewInAppPreview", "PollAnswerViewDisclosedNotSelectedPreview", diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_0_en.png deleted file mode 100644 index 9e29a276b3..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ea4fd71bc94982578bc061607066dfd3efe55aeccbec69b6826fd345113f95e -size 13296 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_1_en.png deleted file mode 100644 index 345e8ca643..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:56aabf6f359235c77b7bffa3d7e2c4ebf7b2c688eaf9e2d8a67da9a00433ebcb -size 12350 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_2_en.png deleted file mode 100644 index 110210ee92..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:058f539d2f7652342394adb681084147dcc2d4a1e24f9c8efd47781a0def4c33 -size 12925 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_3_en.png deleted file mode 100644 index 951f776d62..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:315e1d831a1e3082a9d4ea749b76b374b0f8018c6d5c11b1f48ed34db3b3a1c5 -size 13279 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_4_en.png deleted file mode 100644 index 6e54ed1bff..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eb1c80dfc5926f3aa29ab5118f8c5a6a62ab13a1247e198e32f00509723cd4e3 -size 12550 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_5_en.png deleted file mode 100644 index 54ac4972d6..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_5_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61c83e013e73d55a6b3504f34dcdb0111744499172839a71c35ada67cece1184 -size 13162 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_6_en.png deleted file mode 100644 index 0684f2bcaf..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Day_6_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d81aade2945be977896038addacdb9246d17bb1a57fb3bd0d43169e382ce9f03 -size 13126 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_0_en.png deleted file mode 100644 index a544956d4f..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:46639efc4726cfb78ba5955c7c56619ce06342ef222c4c06eb8829c22d90e6f7 -size 13200 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_1_en.png deleted file mode 100644 index 1517ba7210..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:316d70aa6507a9b0c5ab9833d750033df44f8197ca3f25d7f6acbfc496b68d59 -size 12184 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_2_en.png deleted file mode 100644 index b3ac22f394..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d07c5029da082dcce7b86a202ea611e089ddb1e379d2511395f75dfabdedd5d3 -size 13034 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_3_en.png deleted file mode 100644 index 5a1526f50b..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:da1945462f70133c47e33eaaa9dfc3d64033c6a83d4d50b03776adcc7a7f77e0 -size 13334 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_4_en.png deleted file mode 100644 index aeeae19771..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d4871583b442845d3ae8e3dd98f4099fb7906f2ccccf25b61aad59efb8112c62 -size 12259 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_5_en.png deleted file mode 100644 index 3b86fa73ad..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_5_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0d2d9b68cff6f00bf12eed5df4123af7da908ae3e25e710e5ce305f36b404382 -size 13101 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_6_en.png deleted file mode 100644 index 7e7a23ed38..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconFull_Night_6_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:610e68016011b14db56217ebcd27a86ab597c1668a3a90b09c3e39ac308f8764 -size 13054 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en.png deleted file mode 100644 index 0f0769d977..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a1638d8805c8029573b8cae9a71c3c2dddf569d5154969f49085def60ec74ec8 -size 7545 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en.png deleted file mode 100644 index 756c1aca44..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19c89df3b96fad54d28fdd608cec70d2d8c71fb20901746abacd9bcc26fd5332 -size 7579