Badge
A compact status or label chip: three fills across six semantic tones and twelve named hues.
Live demo
Badge labels, counts, and statuses inline. Fill treatment (variant) and color (tone) are independent axes: each of the three fills (solid, soft, outline) can carry any of the six semantic tones (accent, neutral, danger, success, warn, info) or any of the twelve named hues (red … black).
It adds a leading status dot, a tabular count affordance, and a dismissible form whose × is a real focusable <button>. A standalone .xoji-dot indicator covers the bare-dot case. Status tones (success, warn, danger, info) emit a screen-reader-only tone word so meaning never rides on color alone.
When to use
How this component composes with the rest of the set.
Props
8 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
Variants
solid
Filled with the tone color. The highest-emphasis treatment.
soft
A soft tone-tinted background with tone-colored text. The default.
outline
Transparent fill with a tone-colored border and text.
Sizes
sm
Compact.
md
Default.
lg
Large.
States
remove-hover
Pointer over the dismiss button. Its overlay paints the hover tint.
remove-active
Dismiss button pressed. Its overlay paints the press tint.
remove-focus-visible
Keyboard focus on the dismiss button: a token ring plus a transparent outline that becomes real in forced-colors mode.
Anatomy
The named parts that make up the component, with their selectors.
badge
The chip root carrying the variant, tone, and size classes.
dot
The optional leading status dot, painted in the badge's current text color.
label
The text content wrapper.
count
A tabular-numeric count affordance rendered after the label.
remove
A real <button> dismiss control with an accessible name, its own focus ring, and a state overlay.
indicator
A standalone dot indicator independent of any chip, tonable and sizable on its own.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xoji-default register
(derive(xojiDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--accent
--accent-2
--accent-2-bg
--accent-2-fg
--accent-2-text
--accent-3
--accent-3-bg
--accent-3-fg
--accent-3-text
--accent-4
--accent-4-bg
--accent-4-fg
--accent-4-text
--accent-bg
--accent-fg
--accent-text
--black
--black-bg
--black-fg
--black-text
--blue
--blue-bg
--blue-fg
--blue-text
--border-normal
--border-thick
--border-thin
--brown
--brown-bg
--brown-fg
--brown-text
--cyan
--cyan-bg
--cyan-fg
--cyan-text
--danger
--danger-bg
--danger-fg
--danger-text
--duration-fast
--ease-standard
--font-sans
--gray
--gray-bg
--gray-fg
--gray-text
--green
--green-bg
--green-fg
--green-text
--info
--info-bg
--info-fg
--info-text
--leading-tight
--neutral
--neutral-bg
--neutral-fg
--neutral-text
--orange
--orange-bg
--orange-fg
--orange-text
--pink
--pink-bg
--pink-fg
--pink-text
--purple
--purple-bg
--purple-fg
--purple-text
--radius-full
--red
--red-bg
--red-fg
--red-text
--ring
--space-0
--space-1
--space-2
--space-3
--state-hover
--state-press
--success
--success-bg
--success-fg
--success-text
--text-sm
--text-xs
--warn
--warn-bg
--warn-fg
--warn-text
--weight-medium
--weight-semibold
--white
--white-bg
--white-fg
--white-text
--yellow
--yellow-bg
--yellow-fg
--yellow-text
Slots
The badge label.
Accessibility
Code
Fills, tones, and affordances
The three fills cross all tones and hues; dot, count, and the removable form layer on top, with a standalone dot for the bare case.
<xoji-badge variant="soft" tone="accent">New</xoji-badge>
<xoji-badge variant="solid" tone="success" dot>Online</xoji-badge>
<xoji-badge variant="outline" tone="danger">Failed</xoji-badge>
<xoji-badge tone="info" count="12">Notifications</xoji-badge>
<xoji-badge variant="soft" tone="purple" removable remove-label="Remove tag">design</xoji-badge>
<span class="xoji-dot xoji-dot--success" role="img" aria-label="Online"></span>
<script lang="ts">
import { Badge } from "@xoji/svelte";
</script>
<Badge variant="soft" tone="accent">New</Badge>
<Badge variant="solid" tone="success" dot>Online</Badge>
<Badge variant="outline" tone="danger">Failed</Badge>
<Badge tone="info" count={12}>Notifications</Badge>
<Badge variant="soft" tone="purple" removable removeLabel="Remove tag" onremove={() => drop("design")}>design</Badge>
---
import { Badge } from "@xoji/astro";
---
<Badge variant="soft" tone="accent">New</Badge>
<Badge variant="solid" tone="success" dot>Online</Badge>
<Badge variant="outline" tone="danger">Failed</Badge>
<Badge tone="info" count={12}>Notifications</Badge>
<Badge variant="soft" tone="purple" removable removeLabel="Remove tag">design</Badge>
<span class="xoji-dot xoji-dot--success" role="img" aria-label="Online"></span>