Badge
Status or counter pill.
Installation
npx axiom add badgepnpm dlx axiom add badgeyarn dlx axiom add badgebun x axiom add badgeColors come from badge.<variant>.default.{background,foreground,border} in the component tokens. Counters and dots use badge.count, whose border is the color of the ring.
Usage
import { Badge } from '@/components/ui/badge';
<Badge variant="success" dot>Ready</Badge>
<Badge count={3} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The label. One or two words. |
variant | 'neutral' | 'highlight' | 'info' | 'success' | 'warning' | 'error' | 'outline' | 'inverse' | 'neutral' | Color from the theme’s feedback colors: subtle background with a saturated label. highlight is the brand highlight fill; outline and inverse are neutral alternatives. |
dot | boolean | false | Small dot before the label in the label color, to reinforce a status. |
icon | IconName | — | Icon of your registry before the label. Replaces dot. |
count | number | — | Renders a round counter instead of a label, in feedback.error. 0 hides the badge. |
max | number | 99 | Above this, the counter shows 99+. |
size | 'sm' | 'md' | 'md' | Minimum height: 18 or 22pt. |
ring | boolean | — | For a counter or lone dot: a 2pt ring in badge.count.border around it, to detach it from what it sits on. Badge.Anchor turns it on for its badge; set it yourself to stack a counter on something without an anchor. |
accessibilityLabel | string | — | For counters, what is counted: "3 unread notifications". |
style | StyleProp<ViewStyle> | — | Extra styles for the pill. |
Badge.Anchor
Positions a count or dot badge on the corner of another element.
The ring that detaches the badge from the element belongs to the badge, not to the anchor: the anchor turns on the badge’s ring through context. So the ring is only there when the badge is: <Badge count={0} /> renders nothing, ring included, and an animated badge carries its ring with it.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The element to decorate: an IconButton, an Avatar. |
badge | ReactNode | — | The badge to place. Use count or dot. null shows none. |
placement | 'top-right' | 'bottom-right' | 'top-right' | Corner. |
The anchor doesn’t animate. It stays mounted when badge is null, so to animate the badge in and out, wrap it in an Animated.View with entering and exiting. The ring scales and fades with the badge:
import Animated, { ZoomIn, ZoomOut } from "react-native-reanimated";
<Badge.Anchor
badge={
online ? (
<Animated.View entering={ZoomIn} exiting={ZoomOut}>
<Badge dot />
</Animated.View>
) : null
}
placement="bottom-right"
>
<Avatar name="Jane Cooper" />
</Badge.Anchor>;Badges don’t handle presses. If the user can tap it to filter or remove it, use a Chip.
Use cases
Unread counter on an icon
Badge.Anchor with count on a navigation icon. The accessibility label says what the number means.
<Badge.Anchor
badge={
<Badge count={unread} accessibilityLabel={`${unread} unread messages`} />
}
>
<IconButton icon="inbox" accessibilityLabel="Inbox" onPress={openInbox} />
</Badge.Anchor>Order status
The variant carries meaning: success for delivered, warning for delayed. Keep the text, color alone isn’t enough.
const statusBadge = {
delayed: (
<Badge variant="warning" icon="clock">
Delayed
</Badge>
),
delivered: (
<Badge variant="success" icon="check">
Delivered
</Badge>
),
refunded: <Badge variant="error">Refunded</Badge>,
};Label on a card
A neutral or inverse badge on top of media to tag the content: “New”, “Live”, “Pro”.
<Badge variant="error" dot>LIVE</Badge>
<Badge variant="inverse">Pro</Badge>Related
- Chip
- BottomTabBar, which shows badges on tabs