Data display & Filters

Badge

Badges surface a count, short status, or presence indicator on top of another element.

Components · Data display

A badge is a small, saturated marker that surfaces a count, a short status word, or a presence dot — usually anchored to the corner of another element. Namirial badges are built from --nm-badge-* tokens defined in namirial-theme.css, and ship in seven intents and a dot variant.

12BETA

Overview

A badge draws the eye to a number or a state without demanding a click. It carries very little content — a count, a short label, or nothing at all (the dot variant) — and almost always overlays or sits directly beside the element it describes.

When to use

  • To show an unread or pending count (12 unread messages)
  • To flag a short, glanceable status (NEW, BETA, LIVE)
  • To indicate presence or activity without a count — the dot variant (online, unread, has update)

When not to use

  • For removable, text-first labels — use a tag.
  • For a longer status message that needs explanation — use an alert or tooltip.
  • As a standalone clickable element — a badge never carries its own interaction; wrap the element it's attached to instead.

Anatomy

A badge is a small pill or circle: a saturated fill, a contrasting outline, and centered content. The dot variant strips the content and padding down to a single 8px circle.

Tokens and values that drive each part

PartRoleSource
FillBackground--nm-badge-bg
OutlineBorder--nm-badge-border (fixed to a surface-contrast color, not per-intent)
ContentLabel / count color--nm-badge-fg
ContainerShapeborder-radius: 999px, min 20×20px (8×8px for --dot)

Intents

Unlike tags, badges use a saturated (not soft) background so a small chip still reads clearly at a glance.

12374299518

Seven intents · saturated background + solid label

Text labels

Badges aren't limited to numbers — short, all-caps labels work the same way and are common for feature flags or lifecycle markers.

NEWBETAINFOLIVEHOTDRAFT

Keep labels to one short word — the pill doesn't wrap and isn't meant to hold a phrase.

Dot indicators

The nm-badge--dot modifier drops padding and content to an 8px circle — use it to signal presence or an update without a count.

In context

Badges almost always attach to another element — most often absolutely positioned over its top-right corner.

12NEW

Anchor the parent with position: relative and absolutely position the badge over the corner that reads most naturally for the surface (usually top-right).

Light & dark theme

Badge intents resolve through the same --palette-tag-badge-* primitives the theme layer already remaps per data-theme — no badge-specific dark overrides are needed, the saturated fill and outline just follow the palette.

Light data-theme="light"
12NEW
Dark data-theme="dark"
12NEW

Both previews are locked — they don't follow the page theme switcher. Toggle the page theme to see the rest of the documentation cascade.

Do & don't

✓Do
999
Keep counts short — cap at a value like 99 and consider a "99+" style label beyond that.
✕Don't
2,481
Don't stretch a badge to fit a long number — it breaks the pill shape and stops reading as a quick glance marker.
✓Do
Use the dot variant when presence matters more than an exact count.
✕Don't
3
Don't make the badge itself clickable — attach it to a button or link and let that element carry the interaction.

Accessibility

  • A badge is decorative-adjacent: it reinforces information that should also exist elsewhere (e.g. a count in an aria-label on the parent button, like aria-label="Inbox, 12 unread").
  • Never rely on the dot variant's color alone to convey status — pair it with a text label nearby or in an aria-label, since color alone isn't accessible to all users.
  • All seven intents meet WCAG 2.2 AA contrast for content-over-fill.

Token reference

TokenRole
--nm-badge-bgContainer fill
--nm-badge-borderContainer outline (fixed, not per-intent)
--nm-badge-fgContent color

Each nm-badge--{intent} modifier reassigns --nm-badge-bg and --nm-badge-fg. {intent} = primary · secondary · accent · info · positive · negative · warning.

Index palette — categorical colors beyond the 7 intents

The same 10-hue categorical palette documented on the Tag page is available for badges: --palette-index-{'{n}'}-50 (soft), -75 (mid), and -100 (solid), for {'{n}'} = 1–10 — fixed hex values that don't remap per theme. There's no dedicated nm-badge--index-{'{n}'} modifier class, so wire them up per instance:

12345678910
<span class="nm-badge" style="
  --nm-badge-bg: var(--palette-index-3-50);
  --nm-badge-border: var(--palette-index-3-75);
  --nm-badge-fg: var(--palette-index-3-100);
">
  3
</span>

Implementation

<link rel="stylesheet" href="namirial-theme.css">

<span style="position:relative; display:inline-block;">
  <button class="nm-button nm-button--secondary">
    <i class="icon-bell"></i> Alerts
  </button>
  <span class="nm-badge nm-badge--negative" style="position:absolute; top:-8px; right:-8px;">
    12
  </span>
</span>

CSS classes

ClassValuesDefault
nm-badge--{intent}primary · secondary · accent · info · positive · negative · warningnone (base tokens)
nm-badge--dotstrips content/padding to an 8px circleomit for count/label badges