Merge pull request #5017 from element-hq/feature/bma/a11y/sessionVerification
[a11y] Improve session verification screens
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,11 @@ data class OutgoingVerificationState(
|
||||
data class Verifying(val data: SessionVerificationData, val state: AsyncData<Unit>) : 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +78,6 @@ class KonsistPreviewTest {
|
||||
"MessagesReactionButtonAddPreview",
|
||||
"MessagesReactionButtonExtraPreview",
|
||||
"MessagesViewWithIdentityChangePreview",
|
||||
"PageTitleWithIconFullPreview",
|
||||
"PageTitleWithIconMinimalPreview",
|
||||
"PendingMemberRowWithLongNamePreview",
|
||||
"PinUnlockViewInAppPreview",
|
||||
"PollAnswerViewDisclosedNotSelectedPreview",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user