mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-10-31 16:22:49 +00:00
Merge pull request #7141 from element-hq/feature/bma/visualListItem
Iterate on visual list
This commit is contained in:
+6
-7
@@ -31,12 +31,12 @@ 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.visuallist.VisualList
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualListItemData
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
|
||||
@@ -129,22 +129,21 @@ private fun AnalyticsOptInContent() {
|
||||
verticalBias = -0.4f
|
||||
)
|
||||
) {
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
items = persistentListOf(
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(id = R.string.screen_analytics_prompt_data_usage),
|
||||
iconVector = CompoundIcons.CheckCircle(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(id = R.string.screen_analytics_prompt_third_party_sharing),
|
||||
iconVector = CompoundIcons.CheckCircle(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(id = R.string.screen_analytics_prompt_settings),
|
||||
iconVector = CompoundIcons.CheckCircle(),
|
||||
),
|
||||
),
|
||||
textStyle = ElementTheme.typography.fontBodyLgMedium,
|
||||
iconTint = ElementTheme.colors.iconSuccessPrimary,
|
||||
)
|
||||
}
|
||||
|
||||
+9
-11
@@ -36,10 +36,10 @@ import io.element.android.features.announcement.impl.AnnouncementState
|
||||
import io.element.android.features.announcement.impl.AnnouncementStateProvider
|
||||
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.components.BigIcon
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualList
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualListItemData
|
||||
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
|
||||
@@ -134,11 +134,9 @@ private fun FullscreenAnnouncementContent(
|
||||
Column(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
) {
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
items = announcement.items(),
|
||||
textStyle = ElementTheme.typography.fontBodyLgMedium,
|
||||
iconTint = ElementTheme.colors.iconSecondary,
|
||||
iconSize = 24.dp
|
||||
)
|
||||
announcement.notice()?.let { notice ->
|
||||
@@ -186,25 +184,25 @@ private fun Announcement.Fullscreen.icon() = when (this) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Announcement.Fullscreen.items(): ImmutableList<InfoListItem> = when (this) {
|
||||
private fun Announcement.Fullscreen.items(): ImmutableList<VisualListItemData> = when (this) {
|
||||
Announcement.Fullscreen.Space -> persistentListOf(
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = "View spaces you\'ve created or joined",
|
||||
iconVector = CompoundIcons.VisibilityOn(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = "Accept or decline invites to spaces",
|
||||
iconVector = CompoundIcons.Email(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = "Discover any rooms you can join in your spaces",
|
||||
iconVector = CompoundIcons.Search(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = "Join public spaces",
|
||||
iconVector = CompoundIcons.Explore(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = "Leave any spaces you’ve joined",
|
||||
iconVector = CompoundIcons.Leave(),
|
||||
),
|
||||
|
||||
+7
-7
@@ -48,11 +48,11 @@ import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.deactivation.impl.R
|
||||
import io.element.android.features.logout.impl.ui.AccountDeactivationActionDialog
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem
|
||||
import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.components.list.SwitchListItem
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualList
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualListItemData
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
@@ -175,9 +175,9 @@ private fun Content(
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
items = persistentListOf(
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = buildAnnotatedStringWithStyledPart(
|
||||
R.string.screen_deactivate_account_list_item_1,
|
||||
R.string.screen_deactivate_account_list_item_1_bold_part,
|
||||
@@ -194,7 +194,7 @@ private fun Content(
|
||||
)
|
||||
},
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(R.string.screen_deactivate_account_list_item_2),
|
||||
iconComposable = {
|
||||
Icon(
|
||||
@@ -205,7 +205,7 @@ private fun Content(
|
||||
)
|
||||
},
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(R.string.screen_deactivate_account_list_item_3),
|
||||
iconComposable = {
|
||||
Icon(
|
||||
@@ -216,7 +216,7 @@ private fun Content(
|
||||
)
|
||||
},
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(R.string.screen_deactivate_account_list_item_4),
|
||||
iconComposable = {
|
||||
Icon(
|
||||
|
||||
+6
-6
@@ -22,11 +22,11 @@ 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.features.securebackup.impl.R
|
||||
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.FlowStepPage
|
||||
import io.element.android.libraries.designsystem.components.BigIcon
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualList
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualListItemData
|
||||
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
|
||||
@@ -79,10 +79,10 @@ private fun Content() {
|
||||
modifier = Modifier.padding(top = 8.dp, bottom = 40.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
items = persistentListOf(
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(R.string.screen_encryption_reset_bullet_1),
|
||||
iconComposable = {
|
||||
Icon(
|
||||
@@ -93,7 +93,7 @@ private fun Content() {
|
||||
)
|
||||
},
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(R.string.screen_encryption_reset_bullet_2),
|
||||
iconComposable = {
|
||||
Icon(
|
||||
@@ -104,7 +104,7 @@ private fun Content() {
|
||||
)
|
||||
},
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(R.string.screen_encryption_reset_bullet_3),
|
||||
iconComposable = {
|
||||
Icon(
|
||||
|
||||
+6
-9
@@ -21,14 +21,13 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
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.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.components.BigIcon
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualList
|
||||
import io.element.android.libraries.designsystem.components.visuallist.VisualListItemData
|
||||
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
|
||||
@@ -75,23 +74,21 @@ private fun SignedOutContent() {
|
||||
verticalBias = -0.4f
|
||||
)
|
||||
) {
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
items = persistentListOf(
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(id = R.string.screen_signed_out_reason_1),
|
||||
iconVector = CompoundIcons.Lock(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(id = R.string.screen_signed_out_reason_2),
|
||||
iconVector = CompoundIcons.Devices(),
|
||||
),
|
||||
InfoListItem(
|
||||
VisualListItemData(
|
||||
message = stringResource(id = R.string.screen_signed_out_reason_3),
|
||||
iconVector = CompoundIcons.Block(),
|
||||
),
|
||||
),
|
||||
textStyle = ElementTheme.typography.fontBodyMdMedium,
|
||||
iconTint = ElementTheme.colors.iconSecondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+18
-28
@@ -6,25 +6,19 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.atomic.organisms
|
||||
package io.element.android.libraries.designsystem.components.visuallist
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.InfoListItemMolecule
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.InfoListItemPosition
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
@@ -32,14 +26,17 @@ import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2001-140
|
||||
*/
|
||||
@Composable
|
||||
fun InfoListOrganism(
|
||||
items: ImmutableList<InfoListItem>,
|
||||
fun VisualList(
|
||||
items: ImmutableList<VisualListItemData>,
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = ElementTheme.colors.bgSubtleSecondary,
|
||||
iconTint: Color = LocalContentColor.current,
|
||||
iconTint: Color = ElementTheme.colors.iconSecondary,
|
||||
iconSize: Dp = 20.dp,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
textStyle: TextStyle = ElementTheme.typography.fontBodyMdMedium,
|
||||
textColor: Color = ElementTheme.colors.textPrimary,
|
||||
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
@@ -49,12 +46,12 @@ fun InfoListOrganism(
|
||||
) {
|
||||
for ((index, item) in items.withIndex()) {
|
||||
val position = when {
|
||||
items.size == 1 -> InfoListItemPosition.Single
|
||||
index == 0 -> InfoListItemPosition.Top
|
||||
index == items.size - 1 -> InfoListItemPosition.Bottom
|
||||
else -> InfoListItemPosition.Middle
|
||||
items.size == 1 -> VisualListItemPosition.Single
|
||||
index == 0 -> VisualListItemPosition.Top
|
||||
index == items.size - 1 -> VisualListItemPosition.Bottom
|
||||
else -> VisualListItemPosition.Middle
|
||||
}
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = {
|
||||
if (item.message is AnnotatedString) {
|
||||
Text(
|
||||
@@ -96,22 +93,15 @@ fun InfoListOrganism(
|
||||
}
|
||||
}
|
||||
|
||||
data class InfoListItem(
|
||||
val message: CharSequence,
|
||||
@DrawableRes val iconId: Int? = null,
|
||||
val iconVector: ImageVector? = null,
|
||||
val iconComposable: @Composable () -> Unit = {},
|
||||
)
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun InfoListOrganismPreview() = ElementPreview {
|
||||
internal fun VisualListPreview() = ElementPreview {
|
||||
val items = persistentListOf(
|
||||
InfoListItem(message = "A top item"),
|
||||
InfoListItem(message = "A middle item"),
|
||||
InfoListItem(message = "A bottom item"),
|
||||
VisualListItemData(message = "A top item"),
|
||||
VisualListItemData(message = "A middle item"),
|
||||
VisualListItemData(message = "A bottom item"),
|
||||
)
|
||||
InfoListOrganism(
|
||||
VisualList(
|
||||
items = items,
|
||||
)
|
||||
}
|
||||
+20
-17
@@ -6,7 +6,7 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.atomic.molecules
|
||||
package io.element.android.libraries.designsystem.components.visuallist
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -27,10 +27,13 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
/**
|
||||
* Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2001-159
|
||||
*/
|
||||
@Composable
|
||||
fun InfoListItemMolecule(
|
||||
fun VisualListItem(
|
||||
message: @Composable () -> Unit,
|
||||
position: InfoListItemPosition,
|
||||
position: VisualListItemPosition,
|
||||
backgroundColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: @Composable () -> Unit = {},
|
||||
@@ -38,10 +41,10 @@ fun InfoListItemMolecule(
|
||||
val radius = 14.dp
|
||||
val backgroundShape = remember(position) {
|
||||
when (position) {
|
||||
InfoListItemPosition.Single -> RoundedCornerShape(radius)
|
||||
InfoListItemPosition.Top -> RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
InfoListItemPosition.Middle -> RoundedCornerShape(0.dp)
|
||||
InfoListItemPosition.Bottom -> RoundedCornerShape(bottomStart = radius, bottomEnd = radius)
|
||||
VisualListItemPosition.Single -> RoundedCornerShape(radius)
|
||||
VisualListItemPosition.Top -> RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
VisualListItemPosition.Middle -> RoundedCornerShape(0.dp)
|
||||
VisualListItemPosition.Bottom -> RoundedCornerShape(bottomStart = radius, bottomEnd = radius)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
@@ -61,42 +64,42 @@ fun InfoListItemMolecule(
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun InfoListItemMoleculePreview() {
|
||||
internal fun VisualListItemPreview() {
|
||||
ElementPreview {
|
||||
val color = ElementTheme.colors.bgSubtleSecondary
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A single item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Single,
|
||||
position = VisualListItemPosition.Single,
|
||||
backgroundColor = color,
|
||||
)
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A top item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Top,
|
||||
position = VisualListItemPosition.Top,
|
||||
backgroundColor = color,
|
||||
)
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A middle item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Middle,
|
||||
position = VisualListItemPosition.Middle,
|
||||
backgroundColor = color,
|
||||
)
|
||||
InfoListItemMolecule(
|
||||
VisualListItem(
|
||||
message = { Text("A bottom item") },
|
||||
icon = { Icon(imageVector = CompoundIcons.InfoSolid(), contentDescription = null) },
|
||||
position = InfoListItemPosition.Bottom,
|
||||
position = VisualListItemPosition.Bottom,
|
||||
backgroundColor = color,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class InfoListItemPosition {
|
||||
enum class VisualListItemPosition {
|
||||
Top,
|
||||
Middle,
|
||||
Bottom,
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations 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.visuallist
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
data class VisualListItemData(
|
||||
val message: CharSequence,
|
||||
@DrawableRes val iconId: Int? = null,
|
||||
val iconVector: ImageVector? = null,
|
||||
val iconComposable: @Composable () -> Unit = {},
|
||||
)
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user