Badge
badgeOverlays a count, capped count, custom value, or dot on wrapped content.
Usage
Package Count
When wrapping child elements, the sub-element overlaps to the upper right corner and displays 99+ when exceeding max.
<>
<Badge count={5}>
<Icon />
</Badge>
<Badge count={1000} max={99}>
<Icon />
</Badge>
</>Dot only
dot only displays small dots and does not display numbers (commonly used for "unread" prompts).
<Badge dot tone="danger">
<Icon />
</Badge>Tone color
tone provides danger (default) / brand / success / warning / neutral.
<>
<Badge count={3} tone="danger" />
<Badge count={3} tone="brand" />
<Badge count={3} tone="success" />
<Badge count={3} tone="warning" />
</>Avatar online status
placement nails the corner mark to the specified corner; content puts custom content (such as green check) in the slot.
<>
<Badge dot tone="success" placement="bottom-right">
<Avatar fallback="Hu" />
</Badge>
<Badge tone="success" placement="bottom-right" content={<Check className="size-2.5" />}>
<Avatar fallback="EM" />
</Badge>
</>When to use
Use Badge to overlay unread counts, presence dots, or verification marks on icons and avatars. It represents a quantity or binary presence. Use Chip for removable category or status labels, or Dot for an independent semantic status point.
Import
import { Badge } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| count | number | - | Numeric count; zero is hidden unless showZero is true. |
| max | number | 99 | Values above this limit render as max+. |
| dot | boolean | false | Renders only a dot and takes precedence over count. |
| showZero | boolean | false | Keeps a zero count visible. |
| invisible | boolean | - | Hides the badge while retaining its wrapped child. |
| tone | "neutral"|"brand"|"success"|"warning"|"danger" | danger | Semantic color. |
| variant | "signal"|"themed" | signal | Color policy (#295). signal uses one solid color plus white text in both themes, which is how notification badges normally look. themed follows the theme like any other semantic surface (bg-danger text-danger-foreground); pick it when the badge is an inline status chip. neutral is unaffected and always follows the theme. |
| size | "sm"|"md" | md | Badge size. |
| placement | "top-right"|"top-left"|"bottom-right"|"bottom-left" | top-right | Overlay corner when children is supplied. |
| offset | [number, number] | - | [x, y] pixel adjustment, where positive values move right and down. |
Slots
| Slot | Type | Description |
|---|---|---|
| content | ReactNode | Custom badge content, such as an icon; takes precedence over count and dot. |
| children | ReactNode | Host element for an overlaid badge; omit it to render the badge independently. |
Pitfalls
Precedence is content over dot over count. A zero count hides the badge unless showZero is explicit. Circular hosts often need a small outward offset to place the badge precisely on their edge.
Related
Sparkline · ImageViewer · LiveProductCard · DiffStat · ScoreRing · Dot
Pitfalls
- The `signal` variant needs `@hulianui/tokens` >= 0.10.0 (that release adds
--color-signal-*). On older versions the component's built-in fallback chain degrades to thethemedcolors rather than rendering a transparent chip; upgrading the tokens package switches it on. - Do not override the colors just because the badge is "red with black text" in dark mode. That is not a bug, it is what
themednecessarily produces: in dark mode--color-dangermoves up to the 400 step (#fc5855), so its paired foreground has to flip to near-black for contrast (white text would only reach 3.15, below AA). If you want red with white text, use the defaultsignal, whose steps hold up in both themes (danger-600 #d40924: 5.43 against white text, 3.66 against a dark page, 5.21 against a light one). - The four signal colors are not the same numeric step (danger/brand use 600, success/warning use 700): green and amber are naturally lighter at the same step, and their 600 step only reaches 3.97 / 3.76 against white text, short of the 4.5 AA threshold. The steps were picked by contrast, not by aligning numbers.
Playground
<Badge count={5} max={99} tone="danger" placement="top-right">
<Icon />
</Badge>