What it is
A small indicator — a number or a plain dot — layered on the corner of another element to signal a count or an unread/active status. It wraps the underlying element’sBadge unmodified; Titan’s
contribution is entirely in the theme, not the component code.
Live example
Exports
Hand-confirmed props, from
Badge.tsx’s own JSDoc and its Storybook argTypes:
Vocabulary
Do not confuse a Badge with a status label. Badge carries only a number or a dot — it has no text-label slot of its own. A word like “Active” or “Pending” belongs on Tag, not squeezed intobadgeContent.
color="secondary" is Titan’s neutral badge. The override for colorSecondary points at
badge-neutral-background / badge-neutral-text, not a purple “secondary” brand color — Titan
uses the underlying element’s secondary slot to carry its own neutral intent, the same way
TITAN-DIV-11 describes Button’s
primary/secondary/tertiary riding on top of the underlying element’s variant values
rather than its color ones. Say neutral when that’s the intent you mean.
Choose Badge when
- A count or a simple on/off status needs to attach to the corner of another element — an icon, an avatar, a button — rather than stand on its own.
- The information is genuinely secondary to whatever it’s attached to: an unread count, an active-session dot.
Choose something else when
Anatomy
Variants, sizes, and states
Hand-confirmed fromBadge.overrides.ts and the component’s own Storybook stories — no
per-component matrix emitter exists yet for this concept.
Edge and failure states
Confirmed directly against the component’s ownMaximumValue, BadgeVisibilityOverride, and
BadgeOverlap stories:
Tokens
Hand-confirmed fromBadge.overrides.ts — no per-component token emitter exists yet for this
concept, so this table is hand-confirmed rather than generated.
text-invert is set on the root and would apply to every color, but colorPrimary,
colorSecondary, colorSuccess, colorError, and colorWarning each set their own text color on
top of it — confirmed in Badge.overrides.ts, where those five keys are declared after root. So
text-invert only actually reaches the screen for default and info, the two colors without a
matching override. For the other five, background and contrast text pull straight from the palette
(theme.vars.palette.{color}.main / theme.vars.palette.{color}.contrastText), except
secondary, which uses badge-neutral-background / badge-neutral-text instead.
Composition
Badge wraps a single child element — most often an icon or an Avatar. Pairoverlap="circular" with a circular child (an Avatar) and leave the default
overlap="rectangular" for square or icon children — the BadgeOverlap story demonstrates this
pairing directly, and mismatching them positions the badge visibly off the child’s curve.
Content
badgeContent should stay short — a count, or nothing at all for the dot variant. It has no
typography treatment for longer text.
Accessibility
- Badge has no test file in the Titan checkout, so nothing here beyond the stories’ visible behavior is independently verified.
- Unconfirmed: whether
badgeContentis announced by assistive technology as part of the wrapped element’s accessible name, or read as a separate, disconnected number. Nothing in source addresses this. - A
dotvariant carries no accessible information at all beyond whatever the wrapped element itself announces — a caller relying on the dot alone to convey “unread” needs to supply that meaning elsewhere (e.g., in the wrapped element’s ownaria-label).
Constraints
Known issues
Badge: open issues
Divergences, open decisions, and undocumented gaps for Badge.
Why it works this way
Badge, like Tag, is a bare pass-through component wrapping the underlying element unmodified — its entire Titan-specific contribution lives in the theme override, not the component file. Routingcolor="secondary" to a neutral gray rather than a purple brand color is a real, deliberate
choice recorded in that file. Leaving default and info untouched is not explained anywhere in
source, which is why it is recorded as an edge case here rather than assumed to be intentional.
Status
Package@invoca/titan-core, version 3.6.3. Single export: Badge. No deprecation marker,
since field, or changelog entry specific to this component exists in source.
Related
Titan’s ownutilization.md records exactly 3 usages, all three inside
dashboards/src/components/Tile/TileTitle.stories.js — a Storybook stories file, not application
code. No production usage of Badge outside of Titan’s own demos is evidenced in the tracked data.