Merge pull request #6740 from element-hq/feature/bma/uiSample

Introduce UI sample
This commit is contained in:
Benoit Marty 2026-05-07 12:28:08 +02:00 committed by GitHub
commit a7c9fedc8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
108 changed files with 412 additions and 274 deletions

View file

@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.designsystem.utils.CommonDrawables
private val PIN_WIDTH = 42.dp
@ -395,7 +396,7 @@ private object LocationPinRenderer {
internal fun LocationPinPreview() = ElementPreview {
val sampleAvatarData = AvatarData(
id = "@alice:matrix.org",
name = "Alice",
name = USER_NAME_ALICE,
url = null,
size = AvatarSize.SelectedUser
)

View file

@ -8,10 +8,12 @@
package io.element.android.libraries.designsystem.components.avatar
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
fun anAvatarData(
// Let's the id not start with a 'a'.
// Let the id not start with a 'a'.
id: String = "@id_of_alice:server.org",
name: String? = "Alice",
name: String? = USER_NAME_ALICE,
url: String? = null,
size: AvatarSize = AvatarSize.RoomListItem,
) = AvatarData(

View file

@ -29,6 +29,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.LayoutDirection
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.designsystem.preview.USER_NAME_BOB
import io.element.android.libraries.designsystem.text.toPx
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag
@ -116,12 +118,12 @@ internal fun DmAvatarsPreview() = ElementThemedPreview {
DmAvatars(
userAvatarData = anAvatarData(
id = "Alice",
name = "Alice",
name = USER_NAME_ALICE,
size = size,
),
otherUserAvatarData = anAvatarData(
id = "Bob",
name = "Bob",
name = USER_NAME_BOB,
size = size,
),
openAvatarPreview = {},

View file

@ -0,0 +1,27 @@
/*
* 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.preview
const val USER_NAME_ALICE = "Alice"
const val USER_NAME_BOB = "Bob"
const val USER_NAME_CHARLIE = "Charlie"
const val USER_NAME_CAROL = "Carol"
const val USER_NAME_DAVID = "David"
const val USER_NAME_EVE = "Eve"
const val USER_NAME_JOHN_DOE = "John Doe"
const val USER_NAME_JUSTIN = "Justin"
const val USER_NAME_MALLORY = "Mallory"
const val USER_NAME_SENDER = "Sender"
const val USER_NAME_SUSIE = "Susie"
const val USER_NAME_VICTOR = "Victor"
const val USER_NAME_WALTER = "Walter"
const val ROOM_NAME = "Room name"
const val SPACE_NAME = "Space name"
const val LAST_MESSAGE = "Last message"

View file

@ -22,6 +22,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.USER_NAME_BOB
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.ui.model.InviteSender
@ -57,10 +58,10 @@ internal fun InviteSenderViewPreview() = ElementPreview {
InviteSenderView(
inviteSender = InviteSender(
userId = UserId("@bob:example.com"),
displayName = "Bob",
displayName = USER_NAME_BOB,
avatarData = AvatarData(
id = "@bob:example.com",
name = "Bob",
name = USER_NAME_BOB,
url = null,
size = AvatarSize.InviteSender,
),

View file

@ -9,6 +9,17 @@
package io.element.android.libraries.matrix.ui.components
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.designsystem.preview.USER_NAME_BOB
import io.element.android.libraries.designsystem.preview.USER_NAME_CAROL
import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID
import io.element.android.libraries.designsystem.preview.USER_NAME_EVE
import io.element.android.libraries.designsystem.preview.USER_NAME_JOHN_DOE
import io.element.android.libraries.designsystem.preview.USER_NAME_JUSTIN
import io.element.android.libraries.designsystem.preview.USER_NAME_MALLORY
import io.element.android.libraries.designsystem.preview.USER_NAME_SUSIE
import io.element.android.libraries.designsystem.preview.USER_NAME_VICTOR
import io.element.android.libraries.designsystem.preview.USER_NAME_WALTER
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser
@ -23,30 +34,30 @@ open class MatrixUserProvider : PreviewParameterProvider<MatrixUser> {
open class MatrixUserWithAvatarProvider : PreviewParameterProvider<MatrixUser?> {
override val values: Sequence<MatrixUser?>
get() = sequenceOf(
aMatrixUser(displayName = "John Doe"),
aMatrixUser(displayName = "John Doe", avatarUrl = "anUrl"),
aMatrixUser(displayName = USER_NAME_JOHN_DOE),
aMatrixUser(displayName = USER_NAME_JOHN_DOE, avatarUrl = "anUrl"),
)
}
fun aMatrixUser(
id: String = "@id_of_alice:server.org",
displayName: String? = "Alice",
id: String? = null,
displayName: String? = USER_NAME_ALICE,
avatarUrl: String? = null,
) = MatrixUser(
userId = UserId(id),
userId = UserId(id ?: "@${displayName?.lowercase()?.replace(" ", "_") ?: "id"}:server.org"),
displayName = displayName,
avatarUrl = avatarUrl,
)
fun aMatrixUserList() = listOf(
aMatrixUser("@alice:server.org", "Alice"),
aMatrixUser("@bob:server.org", "Bob"),
aMatrixUser("@carol:server.org", "Carol"),
aMatrixUser("@david:server.org", "David"),
aMatrixUser("@eve:server.org", "Eve"),
aMatrixUser("@justin:server.org", "Justin"),
aMatrixUser("@mallory:server.org", "Mallory"),
aMatrixUser("@susie:server.org", "Susie"),
aMatrixUser("@victor:server.org", "Victor"),
aMatrixUser("@walter:server.org", "Walter"),
aMatrixUser(displayName = USER_NAME_ALICE),
aMatrixUser(displayName = USER_NAME_BOB),
aMatrixUser(displayName = USER_NAME_CAROL),
aMatrixUser(displayName = USER_NAME_DAVID),
aMatrixUser(displayName = USER_NAME_EVE),
aMatrixUser(displayName = USER_NAME_JUSTIN),
aMatrixUser(displayName = USER_NAME_MALLORY),
aMatrixUser(displayName = USER_NAME_SUSIE),
aMatrixUser(displayName = USER_NAME_VICTOR),
aMatrixUser(displayName = USER_NAME_WALTER),
)

View file

@ -27,6 +27,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.components.avatar.anAvatarData
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.SPACE_NAME
/**
* Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=3643-2048&m=dev
@ -72,7 +73,7 @@ internal fun OrganizationHeaderPreview() = ElementPreview {
url = "anUrl",
size = AvatarSize.OrganizationHeader,
),
name = "Space name",
name = SPACE_NAME,
numberOfSpaces = 9,
numberOfRooms = 88,
)

View file

@ -18,6 +18,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.USER_NAME_JOHN_DOE
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.matrix.ui.model.getBestName
@ -58,7 +59,7 @@ internal fun SelectedUserRtlPreview() = CompositionLocalProvider(
) {
ElementPreview {
SelectedUser(
matrixUser = aMatrixUser(displayName = "John Doe"),
matrixUser = aMatrixUser(displayName = USER_NAME_JOHN_DOE),
canRemove = true,
onUserRemove = {},
)

View file

@ -30,6 +30,11 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.components.avatar.anAvatarData
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.SPACE_NAME
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.designsystem.preview.USER_NAME_BOB
import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE
import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.spaces.SpaceRoomVisibility
import io.element.android.libraries.matrix.api.user.MatrixUser
@ -115,15 +120,15 @@ internal fun SpaceHeaderViewPreview() = ElementPreview {
size = AvatarSize.SpaceHeader,
),
alias = RoomAlias("#spaceAlias:matrix.org"),
name = "Space name",
name = SPACE_NAME,
topic = "Space topic: " + LoremIpsum(40).values.first(),
topicMaxLines = 2,
visibility = SpaceRoomVisibility.Public,
heroes = persistentListOf(
aMatrixUser(id = "@1:d", displayName = "Alice", avatarUrl = "aUrl"),
aMatrixUser(id = "@2:d", displayName = "Bob"),
aMatrixUser(id = "@3:d", displayName = "Charlie", avatarUrl = "aUrl"),
aMatrixUser(id = "@4:d", displayName = "Dave"),
aMatrixUser(id = "@1:d", displayName = USER_NAME_ALICE, avatarUrl = "aUrl"),
aMatrixUser(id = "@2:d", displayName = USER_NAME_BOB),
aMatrixUser(id = "@3:d", displayName = USER_NAME_CHARLIE, avatarUrl = "aUrl"),
aMatrixUser(id = "@4:d", displayName = USER_NAME_DAVID),
),
numberOfMembers = 999,
)

View file

@ -22,6 +22,10 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.designsystem.preview.USER_NAME_BOB
import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE
import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.user.MatrixUser
@ -98,10 +102,10 @@ internal fun SpaceMembersViewPreview() = ElementPreview(
) {
SpaceMembersView(
heroes = persistentListOf(
aMatrixUser(id = "@1:d", displayName = "Alice", avatarUrl = "aUrl"),
aMatrixUser(id = "@2:d", displayName = "Bob"),
aMatrixUser(id = "@3:d", displayName = "Charlie", avatarUrl = "aUrl"),
aMatrixUser(id = "@4:d", displayName = "Dave"),
aMatrixUser(id = "@1:d", displayName = USER_NAME_ALICE, avatarUrl = "aUrl"),
aMatrixUser(id = "@2:d", displayName = USER_NAME_BOB),
aMatrixUser(id = "@3:d", displayName = USER_NAME_CHARLIE, avatarUrl = "aUrl"),
aMatrixUser(id = "@4:d", displayName = USER_NAME_DAVID),
),
numberOfMembers = 123,
)

View file

@ -9,6 +9,8 @@
package io.element.android.libraries.matrix.ui.components
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.preview.SPACE_NAME
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomType
@ -28,10 +30,10 @@ class SpaceRoomProvider : PreviewParameterProvider<SpaceRoom> {
state = CurrentUserMembership.LEFT,
),
aSpaceRoom(
displayName = "Alice",
displayName = SPACE_NAME,
roomType = RoomType.Room,
isDirect = true,
heroes = listOf(aMatrixUser(displayName = "Alice")),
heroes = listOf(aMatrixUser(displayName = USER_NAME_ALICE)),
state = CurrentUserMembership.JOINED,
numJoinedMembers = 2,
),
@ -69,9 +71,9 @@ class SpaceRoomProvider : PreviewParameterProvider<SpaceRoom> {
state = CurrentUserMembership.INVITED,
),
aSpaceRoom(
displayName = "Alice",
displayName = SPACE_NAME,
roomType = RoomType.Space,
heroes = listOf(aMatrixUser(displayName = "Alice")),
heroes = listOf(aMatrixUser(displayName = USER_NAME_ALICE)),
state = CurrentUserMembership.JOINED,
numJoinedMembers = 2,
),

View file

@ -9,6 +9,7 @@
package io.element.android.libraries.matrix.ui.messages.reply
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.preview.USER_NAME_SENDER
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.MediaSource
@ -159,7 +160,7 @@ private fun aInReplyToDetails(
)
fun aProfileDetailsReady(
displayName: String? = "Sender",
displayName: String? = USER_NAME_SENDER,
displayNameAmbiguous: Boolean = false,
avatarUrl: String? = null,
) = ProfileDetails.Ready(

View file

@ -9,6 +9,7 @@
package io.element.android.libraries.mediaviewer.impl.details
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.mediaviewer.api.MediaInfo
@ -26,7 +27,7 @@ open class MediaBottomSheetStateDeleteConfirmationProvider : PreviewParameterPro
fun aMediaBottomSheetStateDeleteConfirmation(
mediaInfo: MediaInfo = anImageMediaInfo(
senderName = "Alice",
senderName = USER_NAME_ALICE,
),
thumbnailSource: MediaSource? = null,
) = MediaBottomSheetState.DeleteConfirmation(

View file

@ -8,6 +8,7 @@
package io.element.android.libraries.mediaviewer.impl.details
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.api.anApkMediaInfo
@ -35,7 +36,7 @@ fun aMediaBottomSheetStateDetails(
eventId: EventId? = EventId($$"$eventId"),
canDelete: Boolean = true,
mediaInfo: MediaInfo = anImageMediaInfo(
senderName = "Alice",
senderName = USER_NAME_ALICE,
dateSentFull = "December 6, 2024 at 12:59",
),
) = MediaBottomSheetState.Details(

View file

@ -11,6 +11,7 @@ package io.element.android.libraries.mediaviewer.impl.gallery
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.designsystem.preview.ROOM_NAME
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState
import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails
@ -112,7 +113,7 @@ open class MediaGalleryStateProvider : PreviewParameterProvider<MediaGalleryStat
}
private fun aMediaGalleryState(
roomName: String = "Room name",
roomName: String = ROOM_NAME,
mode: MediaGalleryMode = MediaGalleryMode.Images,
groupedMediaItems: AsyncData<GroupedMediaItems> = AsyncData.Uninitialized,
mediaBottomSheetState: MediaBottomSheetState = MediaBottomSheetState.Hidden,

View file

@ -13,6 +13,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.timeline.Timeline
@ -179,7 +180,7 @@ open class MediaViewerStateProvider : PreviewParameterProvider<MediaViewerState>
)
),
anImageMediaInfo(
senderName = "Alice",
senderName = USER_NAME_ALICE,
dateSent = "21 NOV, 2024",
caption = LONG_CAPTION,
).let {

View file

@ -8,6 +8,16 @@
package io.element.android.libraries.previewutils.room
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
import io.element.android.libraries.designsystem.preview.USER_NAME_BOB
import io.element.android.libraries.designsystem.preview.USER_NAME_CAROL
import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID
import io.element.android.libraries.designsystem.preview.USER_NAME_EVE
import io.element.android.libraries.designsystem.preview.USER_NAME_JUSTIN
import io.element.android.libraries.designsystem.preview.USER_NAME_MALLORY
import io.element.android.libraries.designsystem.preview.USER_NAME_SUSIE
import io.element.android.libraries.designsystem.preview.USER_NAME_VICTOR
import io.element.android.libraries.designsystem.preview.USER_NAME_WALTER
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipState
@ -38,27 +48,27 @@ fun aRoomMember(
fun aRoomMemberList() = persistentListOf(
anAlice(),
aBob(),
aRoomMember(UserId("@carol:server.org"), "Carol"),
aRoomMember(UserId("@david:server.org"), "David"),
aRoomMember(UserId("@eve:server.org"), "Eve"),
aRoomMember(UserId("@justin:server.org"), "Justin"),
aRoomMember(UserId("@mallory:server.org"), "Mallory"),
aRoomMember(UserId("@susie:server.org"), "Susie"),
aRoomMember(UserId("@carol:server.org"), USER_NAME_CAROL),
aRoomMember(UserId("@david:server.org"), USER_NAME_DAVID),
aRoomMember(UserId("@eve:server.org"), USER_NAME_EVE),
aRoomMember(UserId("@justin:server.org"), USER_NAME_JUSTIN),
aRoomMember(UserId("@mallory:server.org"), USER_NAME_MALLORY),
aRoomMember(UserId("@susie:server.org"), USER_NAME_SUSIE),
aVictor(),
aWalter(),
)
fun anAlice() = aRoomMember(UserId("@alice:server.org"), "Alice", role = RoomMember.Role.Admin)
fun aBob() = aRoomMember(UserId("@bob:server.org"), "Bob", role = RoomMember.Role.Moderator)
fun anAlice() = aRoomMember(UserId("@alice:server.org"), USER_NAME_ALICE, role = RoomMember.Role.Admin)
fun aBob() = aRoomMember(UserId("@bob:server.org"), USER_NAME_BOB, role = RoomMember.Role.Moderator)
fun aVictor() = aRoomMember(
UserId("@victor:server.org"),
"Victor",
USER_NAME_VICTOR,
membership = RoomMembershipState.INVITE
)
fun aWalter() = aRoomMember(
UserId("@walter:server.org"),
"Walter",
USER_NAME_WALTER,
membership = RoomMembershipState.INVITE
)

View file

@ -8,6 +8,7 @@
package io.element.android.libraries.previewutils.room
import io.element.android.libraries.designsystem.preview.SPACE_NAME
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
@ -19,7 +20,7 @@ import kotlinx.collections.immutable.toImmutableList
fun aSpaceRoom(
rawName: String? = null,
displayName: String = "Space name",
displayName: String = SPACE_NAME,
avatarUrl: String? = null,
canonicalAlias: RoomAlias? = null,
childrenCount: Int = 0,