Data display

Badge

Display a count or status marker on its children.

Rust
1use herogpui::components::badge::{Badge, BadgeAnchor, BadgeLabel};

Usage

Rust
1use herogpui::prelude::{Badge, BadgeAnchor, BadgeLabel, BadgePlacement, Color, Size};
2use gpui::prelude::*;
3
4row(vec![
5    BadgeAnchor::new()
6        .child(avatar_box(("badge-anchor", 0usize), "Jane Doe"))
7        .child(
8            Badge::new()
9                .color(Color::Danger)
10                .size(Size::Sm)
11                .child(BadgeLabel::new().child("5")),
12        )
13        .into_any_element(),
14    BadgeAnchor::new()
15        .child(avatar_box(("badge-anchor", 1usize), "Alex Brown"))
16        .child(
17            Badge::new()
18                .color(Color::Accent)
19                .size(Size::Sm)
20                .child(BadgeLabel::new().child("New")),
21        )
22        .into_any_element(),
23    BadgeAnchor::new()
24        .child(avatar_box(("badge-anchor", 2usize), "Chris Davis"))
25        .child(
26            Badge::new()
27                .color(Color::Success)
28                .size(Size::Sm)
29                .placement(BadgePlacement::BottomRight),
30        )
31        .into_any_element(),
32])

Live HeroGPUI compiled to WebAssembly. Select any example without loading another WASM instance.

Anatomy

Rust types

BadgeBadgeAnchorBadgeLabel

Badge is assembled from these builders. The API reference lists each one.

Customization

Appearance builders and theme tokens Badge uses.

Styling

Badge styling
StyleDescription
flex + items_center + justify_center + gap(px(2.)) + min_w(px(28.)) + min_h(px(28.)) + control_radius + text_size(px(12.)) + line_height(1.34) + FontWeight::MEDIUM + flex_shrink_0 + border_1(colors.background)28px min square, 12px medium text at the 1.34 leading, 2px gap, and the unconditional 1px page-background ring. Is a block-level flex (no inline-flex) and GPUI 0.2.2 has no background-clip, so the ring paints over the fill edge instead of clipping the fill to the padding box.
(px(16.), px(10.), small_radius) / (px(28.), px(12.), control_radius) / (px(32.), px(14.), soft_radius)16px/28px/32px min squares at the 12px/24px/16px radii with 10/12/14px text; `--md` only restates the base. The radius is a step per size, not a pill, and the leadings are Tailwind's unitless multipliers resolved against each size's own text.
relative + flex + flex_shrink_0Positioning wrapper; `inline-flex` is not portable, so is a block-level flex that hugs content inside a flex parent and keeps `shrink-0`.
BadgeLabel => px(px(2.))Two-pixel label padding — the only horizontal padding in the badge sheet; the badge itself has none.
muted_foreground() => role.soft_foreground(colors.foreground); colors.default.foreground for defaultThe five color classes only relabel the badge; they set no fill. The soft foreground is the muted label color shared by secondary and soft.
BadgeVariant::Primary => paint() => (role.color, role.foreground)The base tokens hold until a compound rule fills with the role; resolves the whole pair in `paint()`.
BadgeVariant::Secondary => paint() => (colors.default.color, muted_foreground())Keeps the base `--badge-bg: var(--default)` whatever the color; only the label follows the color class.
BadgeVariant::Soft => paint() => (role.soft(), role.soft_foreground(colors.foreground))The soft compound cells fill with the per-role soft mix, lighter than the role itself, and keep the soft label.
BadgePlacement::TopRight => top(-size/4) + right(-size/4)Corner overlay overhanging a quarter of the badge's own box (4px sm, 7px md, 8px lg). GPUI 0.2.2 has no div-level transform and a percentage inset would resolve against the containing block, so insets the corner by -size/4 — a quarter of the min box; a badge grown past its min box overhangs less than v3's translate would, and only dot and min-box-fitting badges are exact.
BadgePlacement::TopLeft => top(-size/4) + left(-size/4)Same quarter-box overhang at the top-left corner, with the same min-box approximation as top-right.
BadgePlacement::BottomRight => bottom(-size/4) + right(-size/4)Same quarter-box overhang at the bottom-right corner, with the same min-box approximation.
BadgePlacement::BottomLeft => bottom(-size/4) + left(-size/4)Same quarter-box overhang at the bottom-left corner, with the same min-box approximation.

API reference

Builders

Badge builders
BuilderTypeDefaultDescription
ParentElement::extendAnyElementBadge content (text, number, or icon); omitted children render the dot badge. Auto-wraps plain string and number children in `Badge.Label`; GPUI elements carry no type a parent can intercept, so the wrap is explicit via `BadgeLabel` and bare `Badge` children draw without the label padding.
color(Color)ColorColor::DefaultColor role of the badge; fills and label colors resolve through the badge.css cascade.
variant(BadgeVariant)BadgeVariantBadgeVariant::PrimaryVisual style variant: solid role fill, default fill with a colored label, or the soft mix.
size(Size)SizeSize::MdSets the min square, radius step, and type size of the badge.
placement(BadgePlacement)BadgePlacementBadgePlacement::TopRightCorner of the anchor the badge points at.

Parts

Badge parts
PartDescription
BadgeRoot indicator on the `.badge` BEM classes: an absolutely positioned min-box square (`min-h-7 min-w-7` by size) with a radius step per size, medium text, a 2px gap, and the unconditional 1px page-background ring; empty children render the dot. Is a block-level flex (no inline-flex) and approximates v3's corner translate with a fixed inset, so it is Partial.
BadgeAnchorPositioning wrapper on the `.badge-anchor` BEM class: `relative inline-flex shrink-0`, carrying the anchored element plus the badge. GPUI 0.2.2 has no inline-flex, so the wrapper hugs its content only inside a flex parent; the ported `flex_shrink_0` keeps it from compressing in an overflowing row.
BadgeLabelLabel text slot on the `.badge__label` BEM class — `px-0.5`, the only horizontal padding in the badge sheet. Auto-wraps plain string and number children of the root here; makes that wrap explicit with the `BadgeLabel` part.