Badges

mandatory

Small visual marker attached to another element, signalling presence of notifications, unread count, or status. Material parity (`/components/badges`). Covers small (dot) and large (numeric) variants, anchoring rules, and overflow formatting.

Spec — Badges

Facet *isual*of Koder Design. Material parity: https://m3.material.io/components/badges.

2 variants

Variant Size Content Use
*mall (dot)* 6 px circle None Presence-only marker
*arge (numeric)* 16 px height 1-3 digits or text Count or short label

Pick variant by need: dot when count is irrelevant ("you have new messages"); numeric when count itself is information ("3 unread").

Anatomy (large badge on icon button)

        ┌───┐
   ┌─── │ 3 │   ← badge (top-right anchor)
   │    └───┘
   ▼
  ┌─────┐
  │  ✉  │      ← host (icon button)
  └─────┘
  • *ot diameter* 6 px
  • *arge height* 16 px
  • *arge minwidth* 16 px (square at 1 digit); autoexpands
  • *arge padding* 4 px horizontal
  • *ext* label-small (11/16, weight 600)
  • *ackground* error color role by default
  • *oreground* on-error
  • *order* 1 px surface background (separation from host)

R1 — Anchor position

Anchor Offset Use
*op-right*(default) -2 px x, -2 px y Icon buttons, list items, avatar
*op-left* +2 px x, -2 px y RTL mirror of top-right
*nline* After text, 4 px gap Inside list row, after label

Never anchor below or center — badge always sits at top corner OR inline after text.

R2 — Numeric formatting

Count Display
0 Hide badge entirely (don't show "0")
1-9 Single digit 3
10-99 Two digits 42
100-999 Three digits 512
1000+ 999+ (cap)

Custom cap allowed per surface: 99+ for notifications, 9+ for inbox folders. Document per surface; pick one.

R3 — Color roles

Meaning Background Foreground
*rror / urgent* error on-error
*arning* warning (extended) on-warning
*nfo / neutral count* primary on-primary
*uccess / new* success (extended) on-success
*tatus — online* success dot
*tatus — away* warning dot
*tatus — offline* outline dot

Default to error for unread/attention counts (matches Material default and user expectation).

R4 — Animation

  • *ppear* fadein + scale 0 → 1 (motionfast, ~150 ms)
  • *ount change* crossfade old → new digit (motionfast)
  • *isappear* fadeout (motionfast)
  • *o bouncing / pulsing*— distracting and ignored by users after

    habituation

  • Reduced motion: instant appear/disappear, no animation

R5 — Accessibility

  • Badge content is part of host's accessible name:
    • Icon button: aria-label="Inbox, 3 unread" (concat, not separate)
    • Or use aria-describedby referencing a hidden span with badge

      text

  • Dot-only badge: include presence in host label

    ("Profile, online")

  • Color alone never carries meaning — always pair with text or

    icon-shape difference

  • Hit target: badge is decorative; host's hit target stays unchanged

R6 — Hit target

Badge is non-interactive. Tapping it triggers the host's action. Don't add a separate click handler on the badge — defeats user expectation and confuses screen readers.

R7 — Density

Density Dot Large Padding
Compact 4 px 14 px 3 px
Default 6 px 16 px 4 px
Comfortable 8 px 20 px 6 px

Inherits surface density from customization.kmd.

R8 — Per-preset variation

Preset Visual
material3 Rounded pill, no border, error-color default
material2 Circle (numeric), filled background
ios_cupertino Red filled circle, white text, slight gradient
gnome Rectangle with 4 px radius, accent color
windows_11 Pill shape, system accent color, subtle outline
brutalist Sharp square, thick 2 px border, no animation
terminal_classic ASCII suffix (3) next to icon, no shape

R9 — Forbidden patterns

  • ❌ Showing 0 — hide badge entirely instead
  • ❌ Animating count change with bounce/pulse (distracting)
  • ❌ Putting interactive elements (buttons, links) inside a badge
  • ❌ Using badge to display arbitrary long text — use chip instead
  • ❌ Color-only differentiation (status dot WITHOUT label text)
  • ❌ Anchoring at bottom or center of host
  • ❌ Stacking multiple badges on the same host
  • themes/color-roles.kmderror / success / warning token sources
  • themes/typography.kmdlabel-small for numeric text
  • foundations/elements.kmd — Marker family
  • components/chips.kmd — sibling for longer textual labels with interaction

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/badges.kmd