New

Badge

Compact label for statuses, counts, and metadata.

NewVerifiedPendingDown12
import { RiCheckLine, RiSparklingFill } from "@create-ui/assets/icons"

import { Badge } from "@/components/ui/badge"

Description

Badge is a small, non-interactive label used to tag content with a status, count, or category. It is a single-element component rendered as a <span> by default, with optional leading and trailing icons.

Reach for it when you need to surface a piece of metadata next to other content — an item state next to a row, a count on a navigation item, a tag in a list, a category on a card. The visual weight is intentionally low so it complements the content it sits beside instead of competing with it.

Don't use Badge when the user needs to interact with it. If it triggers an action, use Button. If it represents an inline call-to-attention with title and body copy, use Alert. If it's a colored dot indicating presence (online / offline / away), use Status Badge. Reserve Badge for passive labels.

Installation

pnpm dlx createui@latest add badge

Usage

import { Badge } from "@/components/ui/badge"
<Badge>New</Badge>

Examples

Variants

variant sets the semantic color. Eleven options cover product intents (primary), neutral metadata, status tones (success, error, warning, info), and specialty tones (verified, highlighted, away, inverse, disabled).

PrimaryNeutralSuccessErrorWarningInfoVerifiedHighlightedAwayInverseDisabled
import { Badge } from "@/components/ui/badge"

export function BadgeVariants() {

Appearance

appearance controls fill weight. soft is the default and works well in dense lists. solid is high-contrast for emphasis, outline is quiet, and ghost strips the background entirely.

SolidOutlineSoftGhost
SolidOutlineSoftGhost
import { Badge } from "@/components/ui/badge"

export function BadgeAppearance() {

Sizes

Three sizes — xs, sm, md — match the surrounding type scale. sm is the default.

xssmmd
import { Badge } from "@/components/ui/badge"

export function BadgeSizes() {

Shape

shape="pill" makes the badge fully rounded; rounded (default) follows the size's radius scale.

RoundedPill
import { Badge } from "@/components/ui/badge"

export function BadgeShape() {

With Icon

Use leadingIcon and trailingIcon to render an icon inline. The component handles spacing and sizing per the active size.

LeadingTrailingBoth
import { RiArrowRightLine, RiSparklingFill } from "@create-ui/assets/icons"

import { Badge } from "@/components/ui/badge"

Icon Only

iconOnly removes horizontal padding and forces a square footprint. Always pair with an aria-label so screen readers can announce the meaning.

import { RiSparklingFill } from "@create-ui/assets/icons"

import { Badge } from "@/components/ui/badge"

Number Only

numberOnly is the count style — square-ish, centered, designed for notification numerals (1, 12, 99+) on navigation items or avatars.

11299+
import { Badge } from "@/components/ui/badge"

export function BadgeNumberOnly() {

Accessibility

Badge is a passive label. By default it renders as a <span> and is not focusable; there are no keyboard interactions to document. If you render it as a link or button via the asChild prop, focus and keyboard behavior come from that underlying element.

KeyDescription
Not focusable by default.

ARIA notes:

  • The component sets no implicit role; treat purely-decorative badges as such (e.g. add aria-hidden="true").
  • For badges that carry meaning beyond their visible label (e.g. an unread count), make sure the surrounding context exposes that meaning — either through the badge's text content or with aria-label on the parent control.
  • When using iconOnly, always provide an aria-label because the visual icon alone is not announced.

Styling

Tailwind override — pass className to merge Tailwind classes with the component's CVA classes (via cn()):

<Badge className="tracking-wide uppercase">Beta</Badge>

Data slots and attributes — the component sets these for CSS targeting:

  • data-slot="badge" on the root element.
  • data-slot="badge-icon" on each icon wrapper (leading and trailing).
  • data-slot="badge-label" on the inner text wrapper.
  • data-variant="<variant>", data-appearance="<appearance>", data-size="<size>" on the root.

Target a specific state in CSS:

[data-slot="badge"][data-variant="error"] {
  /* … */
}

Design Tokens

The component reads from the unified semantic token set. Color tokens are picked per variant × appearance:

  • Solid backgrounds: --color-primary-base, --color-strongest, --color-error-base, --color-success-base, --color-warning-weak, --color-info-base, --color-verified-base, --color-highlighted-base, --color-away-base, --color-static.
  • Soft backgrounds: matching *-weakest (or --color-weak for neutral, --color-heavy for inverse).
  • Outline borders: matching *-base (or --color-strong for neutral, --color-weakest for inverse, --color-medium for disabled).
  • Text: matching *-base for non-solid, --color-static for solid, --color-strongest for inverse solid, --color-disabled for disabled.
  • Radius: rounded-sm (xs), rounded-md (sm), rounded-lg (md), rounded-full (pill).

Token definitions live in apps/v4/styles/globals.css.

  • Status Badge — colored dot + label for presence states (online, offline, away).
  • App Store Badge — branded download CTA for App Store / Play Store.
  • Button — use this when the element needs to be interactive.
  • Alert — use this for full callouts with title and description, not inline labels.

API Reference

Badge

Passive label for tagging content with a status, count, or category. Extends React.ComponentProps<"span">, so any standard span attribute (id, role, aria-*, onClick, etc.) is accepted.

Props

PropTypeDefaultDescription
asChildbooleanfalseRender as the child element via Radix Slot. Use to make the badge act as a link.
leadingIconReact.ReactNodeIcon rendered before the label. Ignored when iconOnly or numberOnly is true.
trailingIconReact.ReactNodeIcon rendered after the label. Ignored when iconOnly or numberOnly is true.
iconOnlybooleanfalseSquare footprint with no horizontal padding; renders children as the only content.
numberOnlybooleanfalseCount-style footprint (centered, min-width per size) for short numerals.
classNamestringTailwind classes merged with the component's CVA classes via cn().
childrenReact.ReactNodeBadge content. Text for default mode, an icon for iconOnly, a numeral for numberOnly.

Variants

VariantOptionsDefaultDescription
variant"primary" "neutral" "error" "success" "warning" "info" "verified" "highlighted" "away" "inverse" "disabled""primary"Semantic color intent.
appearance"solid" "outline" "soft" "ghost""soft"Fill weight. solid for emphasis, ghost for no surface.
size"xs" "sm" "md""sm"Size scale; controls height, padding, type, and icon size.
shape"rounded" "pill""rounded"pill is fully rounded; rounded follows the size scale.