Skip to content

Badge ​

A hint red dot mirroring ColorOS's COUIHintRedDot, with three forms: a plain 6dp dot, a 16dp-high number capsule that widens with the digit count, and a three-dot ellipsis for counts of 1000 and above. BadgeBox anchors a badge at the top end corner of an icon like COUIRedDotFrameLayout.

Import ​

kotlin
import io.github.suqi8.coui.kmp.basic.Badge
import io.github.suqi8.coui.kmp.basic.BadgeBox
import io.github.suqi8.coui.kmp.basic.BadgeDefaults

Basic Usage ​

kotlin
Badge()                // plain dot
Badge(count = 8)       // number capsule
Badge(count = 1000)    // three-dot ellipsis (1000+)
Badge(stroke = true)   // white outline for colored surfaces

Badge Forms ​

Dot Badge ​

Counts of 0 or below (the default) render a plain 6dp dot (COUI POINT_ONLY_MODE):

kotlin
Badge()

Count Badge ​

Counts from 1 to 999 render a 16dp-high capsule that widens with the digit count (16dp under 10, 20dp under 100, 26dp under 1000). Count changes ease the capsule width over 517ms while the old and new numbers crossfade over 150ms:

kotlin
var unread by remember { mutableIntStateOf(8) }

Badge(count = unread)

Overflow Ellipsis ​

Counts of 1000 and above render a 20dp-wide capsule with a three-dot ellipsis (COUI red_dot_more):

kotlin
Badge(count = 1000)

Stroke Outline ​

stroke = true draws a 1dp white outline around the dot or capsule, for badges placed on colored surfaces (COUI POINT_ONLY_MODE_STROKE / POINT_NUM_MODE_STROKE):

kotlin
Badge(stroke = true)              // dot with outline
Badge(count = 99, stroke = true)  // capsule with outline

Anchoring with BadgeBox ​

BadgeBox anchors a badge at the top end corner of its content. A positive overhang lets the badge stick out of the corner by that amount and grows the layout accordingly (COUI rectangular anchors such as icons):

kotlin
BadgeBox(
    badge = { Badge(count = 8) },
    overhang = BadgeDefaults.CountOverhang,
) {
    Icon(
        imageVector = COUIIcons.Settings,
        contentDescription = "Settings",
    )
}

A negative overhang insets the badge inside the corner instead (COUI circular anchors such as avatars):

kotlin
BadgeBox(
    badge = { Badge() },
    overhang = (-2).dp,
) {
    Image(
        painter = avatarPainter,
        contentDescription = "Avatar",
        modifier = Modifier.size(40.dp).clip(CircleShape),
    )
}

Properties ​

Badge ​

PropertyTypeDescriptionDefault ValueRequired
modifierModifierModifier applied to the badgeModifierNo
countIntNumber shown in the badge; values <= 0 show a dot0No
strokeBooleanWhether to draw a white outlinefalseNo
colorsBadgeColorsColor configurationBadgeDefaults.badgeColors()No
dotDiameterDpDiameter of the plain dot formBadgeDefaults.DotDiameterNo
heightDpHeight of the number capsule formBadgeDefaults.HeightNo

BadgeBox ​

PropertyTypeDescriptionDefault ValueRequired
badge@Composable () -> UnitThe badge to anchor-Yes
modifierModifierModifier applied to the layoutModifierNo
overhangDpHow far the badge extends beyond the top end cornerBadgeDefaults.DotOverhangNo
content@Composable () -> UnitThe anchor content, typically an icon-Yes

BadgeDefaults ​

ConstantTypeDefault Value
DotDiameterDp6.dp
HeightDp16.dp
SmallWidthDp16.dp
MediumWidthDp20.dp
LargeWidthDp26.dp
TextSizeDp10.dp
StrokeWidthDp1.dp
EllipsisDotDiameterDp2.dp
EllipsisSpacingDp2.dp
DotOverhangDp2.dp
CountOverhangDp3.dp
ScaleAnimDurationMillisInt520

badgeColors() factory ​

ParameterTypeDefault
containerColorColorCOUI additional red (#EB3B2F in light themes, #EB493D in dark)
contentColorColorColor.White
strokeColorColorColor.White

Behavior ​

  • count <= 0 shows the plain dot; 1..9 a 16dp capsule, 10..99 a 20dp capsule, 100..999 a 26dp capsule; 1000 and above a 20dp capsule with a three-dot ellipsis (COUI red_dot_more).
  • Count changes animate like COUIHintRedDot: the capsule width eases over 517ms (COUIMoveEaseInterpolator) while the old and new numbers crossfade over 150ms.
  • The count text renders at a density-scaled 10dp (sans-serif medium), ignoring the user font scale like the original.
  • stroke = true draws a 1dp white outline; the dot form shrinks its red core by the stroke width, the capsule form insets the red fill inside the white outline.
  • A positive BadgeBox overhang lets the badge stick out beyond the content's top end corner and grows the layout accordingly (COUI rectangular anchors); a negative overhang insets the badge inside the corner (COUI circular anchors such as avatars).
  • To animate badge visibility like COUIHintRedDot's show / hide scale animation, wrap it in AnimatedVisibility with scaleIn / scaleOut over BadgeDefaults.ScaleAnimDurationMillis.

Changelog

Released under the Apache-2.0 License