Indicator
An indicator pins a count bubble or a status dot to the corner of any element: unread counts on an inbox button, a “new” dot on a nav item, a mention count on an avatar. CSS-only. The inline badge stays the in-flow label; this is the positioned overlay.
Wrap the target in .re-indicator and add a .re-indicator__badge after it.
A single digit renders as a circle; longer counts grow into a pill. Overflow
(“99+”) is authored content, not CSS.
<div class="row">
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Inbox</button>
<span class="re-indicator__badge">3<span class="re-sr-only"> unread messages</span></span>
</span>
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Notifications</button>
<span class="re-indicator__badge">99+<span class="re-sr-only"> notifications</span></span>
</span>
</div> data-dot renders a small dot with no visible text, for a binary “something
new” signal.
<span class="re-indicator">
<button class="re-button" data-variant="ghost">Alerts</button>
<span class="re-indicator__badge" data-dot><span class="re-sr-only">New alerts</span></span>
</span> data-tone: danger (default, the notification convention), info,
success, warning, neutral. Fills use the solid *-700 scale with
--re-color-text-on-accent so the count text keeps AA contrast.
<div class="row">
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Danger</button>
<span class="re-indicator__badge">5<span class="re-sr-only"> alerts</span></span>
</span>
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Info</button>
<span class="re-indicator__badge" data-tone="info"
>2<span class="re-sr-only"> updates</span></span
>
</span>
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Success</button>
<span class="re-indicator__badge" data-tone="success"
>4<span class="re-sr-only"> completed</span></span
>
</span>
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Warning</button>
<span class="re-indicator__badge" data-tone="warning"
>7<span class="re-sr-only"> pending</span></span
>
</span>
<span class="re-indicator">
<button class="re-button" data-variant="secondary">Neutral</button>
<span class="re-indicator__badge" data-tone="neutral"
>9<span class="re-sr-only"> archived</span></span
>
</span>
</div> Position
Section titled “Position”data-position="bottom-end" moves the badge to the lower corner. Corners are
logical, so both positions mirror automatically under RTL.
<span class="re-indicator">
<span class="re-avatar" role="img" aria-label="Grace Hopper, 2 mentions">GH</span>
<span class="re-indicator__badge" data-position="bottom-end" data-tone="info">2</span>
</span> Accessibility
Section titled “Accessibility”The badge reads after its target in source order, and a bare number (or an empty dot) means nothing to assistive tech, so always provide real text:
- Count on a normal target: append an
.re-sr-onlysuffix inside the badge, e.g.3<span class="re-sr-only"> unread messages</span>. - Dot: the sr-only text is the entire content,
<span class="re-sr-only">New alerts</span>. - On a
role="img"initials avatar: descendant text is presentational (same trap as the avatar presence dot), so fold the meaning into the avatar’saria-label(“Grace Hopper, 2 mentions”) and leave the badge visual-only. - Forced colors: backgrounds flatten, which would erase the bubble and the
dot, so both are re-established with system
Highlight/HighlightText(tone variants included, at matched specificity). - Keep counts truthful and fresh: a stale visual count that contradicts the spoken text is worse than none.
See the accessibility guide for the project-wide stance.