Merge pull request #4108 from element-hq/feature/fga/design_counter

design : CounterAtom
This commit is contained in:
ganfra
2025-01-06 10:50:06 +01:00
committed by GitHub
10 changed files with 111 additions and 1 deletions

View File

@@ -48,6 +48,8 @@ open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState>
aRoomDetailsState(isPublic = false),
aRoomDetailsState(heroes = aMatrixUserList()),
aRoomDetailsState(pinnedMessagesCount = 3),
aRoomDetailsState(knockRequestsCount = null, canShowKnockRequests = true),
aRoomDetailsState(knockRequestsCount = 4, canShowKnockRequests = true),
// Add other state here
)
}

View File

@@ -251,7 +251,7 @@ private fun KnockRequestsItem(knockRequestsCount: Int?, onKnockRequestsClick: ()
trailingContent = if (knockRequestsCount == null || knockRequestsCount == 0) {
null
} else {
ListItemContent.Text(knockRequestsCount.toString())
ListItemContent.Counter(knockRequestsCount)
},
onClick = onKnockRequestsClick,
)

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.designsystem.atomic.atoms
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.toDp
import io.element.android.libraries.designsystem.theme.components.Text
private const val MAX_COUNT = 99
private const val MAX_COUNT_STRING = "+$MAX_COUNT"
/**
* A counter atom that displays a number in a circle.
* Figma link : https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2805-2649&m=dev
*
* @param count The number to display. If the number is greater than [MAX_COUNT], the counter will display [MAX_COUNT_STRING].
* If the number is less than 1, the counter will not be displayed.
* @param modifier The modifier to apply to this layout.
*/
@Composable
fun CounterAtom(
count: Int,
modifier: Modifier = Modifier,
) {
if (count < 1) return
val countAsText = when (count) {
in 0..MAX_COUNT -> count.toString()
else -> MAX_COUNT_STRING
}
val textStyle = ElementTheme.typography.fontBodyMdMedium
val textMeasurer = rememberTextMeasurer()
// Measure the maximum count string size
val textLayoutResult = textMeasurer.measure(
text = MAX_COUNT_STRING,
style = textStyle
)
val textSize = textLayoutResult.size
val squareSize = maxOf(textSize.width, textSize.height)
Box(
modifier = modifier
.size(squareSize.toDp() + 1.dp)
.clip(CircleShape)
.background(ElementTheme.colors.iconSuccessPrimary)
) {
Text(
modifier = Modifier.align(Alignment.Center),
text = countAsText,
style = textStyle,
color = Color.White,
)
}
}
@PreviewsDayNight
@Composable
internal fun CounterAtomPreview() = ElementPreview {
Column(verticalArrangement = spacedBy(2.dp)) {
CounterAtom(count = 0)
CounterAtom(count = 4)
CounterAtom(count = 99)
CounterAtom(count = 100)
}
}

View File

@@ -17,6 +17,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.atomic.atoms.CounterAtom
import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom
import io.element.android.libraries.designsystem.theme.components.IconSource
import io.element.android.libraries.designsystem.theme.components.ListItem
@@ -91,6 +92,9 @@ sealed interface ListItemContent {
/** Displays a badge. */
data object Badge : ListItemContent
/** Displays a counter. */
data class Counter(val count: Int) : ListItemContent
@Composable
fun View() {
when (this) {
@@ -125,6 +129,9 @@ sealed interface ListItemContent {
) {
RedIndicatorAtom()
}
is Counter -> {
CounterAtom(count = count)
}
is Custom -> content()
}
}