Badges
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 min
width* 16 px (square at 1 digit); autoexpands - *arge padding* 4 px horizontal
- *ext*
label-small(11/16, weight 600) - *ackground*
errorcolor role by default - *oreground*
on-error - *order* 1 px
surfacebackground (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* fade
in + scale 0 → 1 (motionfast, ~150 ms) - *ount change* cross
fade old → new digit (motionfast) - *isappear* fade
out (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-describedbyreferencing a hidden span with badgetext
- Icon button:
- 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
Cross-link
themes/color-roles.kmd—error/success/warningtoken sourcesthemes/typography.kmd—label-smallfor numeric textfoundations/elements.kmd— Marker familycomponents/chips.kmd— sibling for longer textual labels with interaction