Data Display · astro-ui · Badge

Badge

Status/count label — inline or overlay bubble with icon, dot, avatar, and dismiss.

Badge is a zero-JS status and count label. Inline it next to text, or use it as an overlay bubble pinned to another element’s corner with content + position. Inline badges compose: an icon slot (or any image, e.g. a flag) sized via –aui-badge-icon, a variant-tinted status dot, optically aligned avatars, and a labeled dismiss button. Counts stay real text so screen readers announce them.

Features

  • 11 variants incl. soft, muted, destructive
  • 5 sizes: xs → 2xl
  • Overlay bubble mode with 4 corner positions
  • Icon slot, status dot, avatar alignment, dismiss button
  • content prop for counts (keeps text announcement)
  • Logical-property positioning — mirrors in RTL

Usage

---
import { Badge } from "astro-ui";
---

<Badge variant="success">Active</Badge>
<Badge content="3" position="top-right" variant="destructive" ariaLabel="3 notifications" />
  Inbox

Demos

Variants

PrimarySecondaryOutlineActivePendingFailedNew
<Badge>Primary</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="success">Active</Badge>
<Badge variant="warning">Pending</Badge>
<Badge variant="destructive">Failed</Badge>
<Badge variant="info">New</Badge>

Sizes

smmdlgxl
<Badge size="sm">sm</Badge>
<Badge size="md">md</Badge>
<Badge size="lg">lg</Badge>
<Badge size="xl">xl</Badge>

Badge with icon

Verified Action required

Anything in the icon slot is boxed at--aui-badge-icon (default 0.875em) and scales with the badge size.

<Badge variant="outline" size="lg">
  <svg slot="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M20 6L9 17l-5-5" />
  </svg>
  Verified
</Badge>
<Badge variant="soft" size="lg">
  <svg slot="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="10" />
<path d="M12 8v4M12 16h.01" />
  </svg>
  Action required
</Badge>

Badge with status dot

OperationalDegradedOutage

The dot inherits the variant's text color — set it and forget it.

<Badge variant="success" dot>Operational</Badge>
<Badge variant="warning" dot>Degraded</Badge>
<Badge variant="destructive" dot>Outage</Badge>

Badge with avatar

Ada Grace

Drop an Avatar in the default slot — optical alignment against the pill padding is built in.

<Badge variant="outline" size="xl">
  <Avatar name="Ada Lovelace" size="xs" />
  Ada
</Badge>
<Badge variant="muted" size="xl">
  <Avatar name="Grace Hopper" size="xs" status="online" />
  Grace
</Badge>

Badge with flag image

United States Germany

Pass a flag through the icon slot and size it via --aui-badge-icon.

<Badge variant="outline" size="lg" style="--aui-badge-icon: 1rem">
  <img slot="icon" src="/flags/us.svg" alt="" width="16" height="16" style="border-radius: 2px" />
  United States
</Badge>
<Badge variant="outline" size="lg" style="--aui-badge-icon: 1rem">
  <img slot="icon" src="/flags/de.svg" alt="" width="16" height="16" style="border-radius: 2px" />
  Germany
</Badge>

Badge with dismiss button

DesignResearchDocs

closable renders a labeled, focusable × button — Badge stays zero-JS, so wire the removal app-side.

<Badge variant="outline" size="lg" closable>Design</Badge>
<Badge variant="outline" size="lg" closable closeLabel="Remove Research filter">Research</Badge>
<Badge variant="soft" size="lg" closable>Docs</Badge>

Overlay bubble

3New8

The bubble anchors to the marked parent (position: relative) — place the Badge inside any positioned element. A dot bubble renders when no content is passed.

<span class="relative inline-block">
  <Badge position="top-right" content="3" variant="destructive" ariaLabel="3 items" />
  Inbox
</span>

API

Props

PropTypeDefaultDescription
variant"primary" | "secondary" | "outline" | "ghost" | "soft" | "success" | "warning" | "info" | "muted" | "destructive""primary"Color scheme.
size"sm" | "md" | "lg" | "xl" | "2xl""md"Font/padding scale.
contentstring—Count/content when no default slot is provided.
position"top-right" | "top-left" | "bottom-right" | "bottom-left"—Overlay bubble corner (logical start/end — mirrors in RTL).
contentPropsRecord<string, any>{}Forwarded to the bubble element.
dotbooleanfalseLeading status dot tinted by the variant (inline mode).
closablebooleanfalseRenders an accessible dismiss button (inline mode).
closeLabelstring"Dismiss"Accessible label for the dismiss button.
classstring—Merged via cn(); Tailwind classes welcome.
idstring—Element id.
ariaLabelstring—Accessible name.

Accessibility

Implemented accessibility features — semantics, ARIA wiring, and keyboard behavior that ship with the component.

  • Status changes announced via aria-label on status badges
  • Purely presentational by default — no extra semantics to announce

FAQ

How do screen readers handle counts?

The count is real text inside the badge. Add ariaLabel for context, e.g. ariaLabel="3 unread messages".

Does the dismiss button remove the badge?

No — Badge ships zero JS. The button is real, focusable, and labeled via closeLabel; wire the removal with a small script or a form action on your side.

How do I put an image or flag inside a badge?

Anything in the icon slot is boxed at --aui-badge-icon (default 0.875em) and scales with the badge. Set the variable inline, e.g. style="--aui-badge-icon: 1rem", for a 16px flag.

Changelog

Version history mentioning Badge.

v0.1.0 — 2026-11-11
added
  • Data display (10): Badge, Avatar, Attachment, Table, Progress, Bubble, Chart, Empty, Tag, Timeline.