Skip to content
Components

Badge

Display-only pill for contextual metadata - status, category, or counts. Pass label+value for a split badge; compose BadgeDot/BadgeButton as children.

New

Usage

import { Badge, BadgeButton, BadgeButtonProps, BadgeDot, BadgeDotProps, BadgeEmphasis, BadgeProps, BadgeSize, BadgeTone, pillVariants } from "@instruments/materia-ui/components/badge";

Best practices

  • Badge is display-only - never attach onClick; use Tag (interactive) or wrap a Button.

  • For a notification count use mode="count" (circular, tabular figures), not radius="full" + manual classes.

  • A standalone count needs an accessibleLabel ("3 unread"); inside an icon-only trigger, mark the badge aria-hidden and fold the count into the trigger's aria-label.

  • A badge overlapping a corner of another surface takes ring so a 2px background-coloured ring separates it from what's beneath; set it only where the badge truly overlaps, and the page surface should be background.

Props

Badge

PropTypeDefaultDescription
renderuseRender.RenderProp<Record<string, unknown>> | undefined

Replace the rendered span with another element or component.

refReact.Ref<HTMLElement> | undefined

Ref to the rendered element.

sizeResponsiveValue<PillSize>"base"

Badge size - a single token or a per-breakpoint object like { base: "sm", md: "lg" }. Forwarded to the underlying Pill.

disabledboolean
focusedboolean

Force focus ring display (for documentation/testing)

hoveredboolean

Force hover state display (for documentation/testing)

iconLucideIcon | React.ComponentType<React.SVGProps<SVGSVGElement>>
iconPlacement"end" | "start""start"
labelstring

Left segment of a split badge; renders a divider before value.

loadingboolean

Show loading spinner

loadingLabelstring

Label shown during loading

testidstring
valuestring

Right (emphasised) segment; shown alone when no label is set.

mode"default" | "count""default"

Badge display mode. "count" renders a circular number badge (full radius + tabular-nums) for notification/count use; it **owns the radius axis** and overrides any radius prop. Pair with accessibleLabel when standalone.

accessibleLabelstring

Accessible name for a standalone mode="count" badge (e.g. "3 unread"). Renders as sr-only text with the visible number hidden from assistive tech. When the badge sits inside an icon-only trigger, instead set aria-hidden on the badge and fold the count into the trigger's own aria-label ("Notifications, 3 unread").

ringbooleanfalse

Draw a 2px ring in the page's background colour around the badge, to separate it from the surface it overlaps when it sits on a corner.

tone"neutral" | "brand" | "danger" | "warning" | "success" | "info" | null | undefined
radius"rounded" | "square" | "full" | null | undefined
emphasis"outline" | "solid" | "ghost" | "soft" | "transparent" | null | undefined
asInputboolean | null | undefined

Input-style chip: white bg + subtle shadow (unselected state).

BadgeButton

PropTypeDefaultDescription
iconReact.ReactNode
variant"default" | null | undefined

Also exports

  • interfaceBadgeButtonProps
  • componentBadgeDot
  • typeBadgeDotProps
  • typeBadgeEmphasis
  • interfaceBadgeProps
  • typeBadgeSize
  • typeBadgeTone
  • constpillVariants