Badged Box
Puts badge on content, with its middle on a corner of it, and takes no room for it.
import com.pantrixui.components.elements.badge.PantrixBadgedBox
- A count or a dot. With a
countthe badge is a pill that writes the number; without one, a dot. A number of one digit sits in a circle. - A count that overflows. A number above
maxCountis written "99+", and the pill stops growing there. - Zero is a count too. Zero is drawn as "0": taking the badge away when there is nothing left to count is the caller's to do. A number below zero is drawn as "0" as well.
- Six tones.
tonefills the badge from one of the theme's roles;colorsgives a colour that no role has. - On the corner of something.
PantrixBadgedBoxsets the badge on a corner of its content; on round content it sets it on the circle, not on the box (BadgeOverlap.Circular). - Font scale. The number is set in the theme's
captionstyle and grows with the system's text size, and the pill with it.
Examples
On the corner of an icon
PantrixBadgedBox sets the badge on a corner of its content: by default the top corner on the side where lines end.
The badge is hidden from screen readers; the icon's own description says the number ("Inbox, 5 unread"). When the number gets down to zero no badge is put there at all: it is the caller that does this, not the badge. Raise the number with the buttons: past 99 it reads "99+", and the pill grows away from the icon.
var unread by rememberSaveable { mutableIntStateOf(START_UNREAD) }
Row(
horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg),
verticalAlignment = Alignment.CenterVertically
) {
PantrixBadgedBox(badge = { if (unread > 0) PantrixBadge(count = unread, tagKey = "unread") }) {
PantrixIcon(
imageVector = PantrixIcons.Inbox,
contentDescription = if (unread > 0) "Inbox, $unread unread" else "Inbox",
tagKey = "inbox"
)
}
PantrixButton(
text = "+1",
onClick = { unread += 1 },
variant = ButtonVariant.Outline,
size = ButtonSize.Small,
tagKey = "one_more"
)
PantrixButton(
text = "+50",
onClick = { unread += MANY },
variant = ButtonVariant.Outline,
size = ButtonSize.Small,
tagKey = "many_more"
)
PantrixButton(
text = "Mark as read",
onClick = { unread = 0 },
variant = ButtonVariant.Text,
size = ButtonSize.Small,
tagKey = "read"
)
}
private const val START_UNREAD = 5
private const val MANY = 50
On avatars
On round content the badge stands on the circle, not on the corner of the box: overlap = BadgeOverlap.Circular. alignment says which corner; the status dot is at the bottom, on the side where lines end.
The status dots are made larger with BadgeStyle(dotSize = 12.dp): large enough to be made out on an avatar. The avatar's description says what the dot means ("İbrahim Öztürk, online"); the dot is hidden from screen readers.
val statusDot = BadgeStyle(dotSize = 12.dp)
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.xl)) {
PantrixBadgedBox(
badge = { PantrixBadge(count = 2, tagKey = "messages") },
overlap = BadgeOverlap.Circular
) {
PantrixAvatar(contentDescription = "Ayşe Yılmaz, 2 new messages", initials = "AY", tagKey = "badged_ayse")
}
PantrixBadgedBox(
badge = { PantrixBadge(tone = BadgeTone.Success, style = statusDot, tagKey = "online") },
alignment = Alignment.BottomEnd,
overlap = BadgeOverlap.Circular
) {
PantrixAvatar(
contentDescription = "İbrahim Öztürk, online",
initials = "İÖ",
tone = AvatarTone.Info,
tagKey = "badged_ibrahim"
)
}
PantrixBadgedBox(
badge = { PantrixBadge(tone = BadgeTone.Neutral, style = statusDot, tagKey = "offline") },
alignment = Alignment.BottomEnd,
overlap = BadgeOverlap.Circular
) {
PantrixAvatar(
contentDescription = "ilker kaya, offline",
initials = "ik",
tone = AvatarTone.Success,
tagKey = "badged_ilker"
)
}
PantrixBadgedBox(
badge = { PantrixBadge(count = MANY * 3, tagKey = "team") },
overlap = BadgeOverlap.Circular
) {
PantrixAvatar(
contentDescription = "Team, more than 99 new messages",
icon = PantrixIcons.Person,
tone = AvatarTone.Primary,
tagKey = "badged_team"
)
}
}
private const val MANY = 50
Beside a text
A badge can stand on a text too. PantrixBadgedBox keeps the baseline of its content: with alignByBaseline the "new" label stands on the same line as the title beside it, and the dot on the label's corner.
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixText(
text = "Campaigns",
modifier = Modifier.alignByBaseline(),
style = PantrixTheme.typography.callout
)
PantrixBadgedBox(
badge = { PantrixBadge(tone = BadgeTone.Primary, tagKey = "new") },
modifier = Modifier.alignByBaseline()
) {
PantrixText(text = "new", style = PantrixTheme.typography.footnote)
}
}
API
badge
Puts badge on content, with its middle on a corner of it, and takes no room for it.
| Parameter | Type | Default | What it is |
|---|---|---|---|
badge | @Composable () -> Unit | what is put on the content: usually a PantrixBadge. Nothing, where there is nothing to show. | |
modifier | Modifier | Modifier | the box's modifier. |
alignment | Alignment | Alignment.TopEnd | where on content the middle of the badge is. |
overlap | BadgeOverlap | BadgeOverlap.Rectangular | whether that is on the box around content, or on the circle in it. |
content | @Composable () -> Unit | what the badge belongs to. |
Accessibility
- Screen reader. Without a
contentDescriptionthe badge is hidden from screen readers: a lone "3" read out says nothing, and the number is said by the description of the element the badge sits on.