Merge pull request #4108 from element-hq/feature/fga/design_counter
design : CounterAtom
This commit is contained in:
commit
54be31c670
10 changed files with 111 additions and 1 deletions
|
|
@ -48,6 +48,8 @@ open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState>
|
||||||
aRoomDetailsState(isPublic = false),
|
aRoomDetailsState(isPublic = false),
|
||||||
aRoomDetailsState(heroes = aMatrixUserList()),
|
aRoomDetailsState(heroes = aMatrixUserList()),
|
||||||
aRoomDetailsState(pinnedMessagesCount = 3),
|
aRoomDetailsState(pinnedMessagesCount = 3),
|
||||||
|
aRoomDetailsState(knockRequestsCount = null, canShowKnockRequests = true),
|
||||||
|
aRoomDetailsState(knockRequestsCount = 4, canShowKnockRequests = true),
|
||||||
// Add other state here
|
// Add other state here
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ private fun KnockRequestsItem(knockRequestsCount: Int?, onKnockRequestsClick: ()
|
||||||
trailingContent = if (knockRequestsCount == null || knockRequestsCount == 0) {
|
trailingContent = if (knockRequestsCount == null || knockRequestsCount == 0) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
ListItemContent.Text(knockRequestsCount.toString())
|
ListItemContent.Counter(knockRequestsCount)
|
||||||
},
|
},
|
||||||
onClick = onKnockRequestsClick,
|
onClick = onKnockRequestsClick,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
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.atomic.atoms.RedIndicatorAtom
|
||||||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||||
|
|
@ -91,6 +92,9 @@ sealed interface ListItemContent {
|
||||||
/** Displays a badge. */
|
/** Displays a badge. */
|
||||||
data object Badge : ListItemContent
|
data object Badge : ListItemContent
|
||||||
|
|
||||||
|
/** Displays a counter. */
|
||||||
|
data class Counter(val count: Int) : ListItemContent
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun View() {
|
fun View() {
|
||||||
when (this) {
|
when (this) {
|
||||||
|
|
@ -125,6 +129,9 @@ sealed interface ListItemContent {
|
||||||
) {
|
) {
|
||||||
RedIndicatorAtom()
|
RedIndicatorAtom()
|
||||||
}
|
}
|
||||||
|
is Counter -> {
|
||||||
|
CounterAtom(count = count)
|
||||||
|
}
|
||||||
is Custom -> content()
|
is Custom -> content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d3ecde943af214c1c2012edf6f7fa4db2e1f8b81e912fc44e3452aced3dcac3f
|
||||||
|
size 41454
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d215f0c099c5bdf410c777392f6089a8441aea42a57a2b188a1f701c7519d502
|
||||||
|
size 42036
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e457078f488ce08554849e214ab45404217627e2d253f21d8a2cbd08009bf75b
|
||||||
|
size 42405
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4086a1ea9bc4cca80ceeb8f41f52d11551a0f1e702f3b72b65dbe244edaff867
|
||||||
|
size 43019
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:7a2a171ac0edac9cb734d418b7baf68dd294d9feb93f005cf445420a7538a8ed
|
||||||
|
size 7687
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:56508c5827cfda4c672f924e3e9280659b729b772455c65dbae76ba7815e18dd
|
||||||
|
size 7502
|
||||||
Loading…
Add table
Add a link
Reference in a new issue