Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

Components

Badge

A badge is a small status indicator that can be placed on other elements.

Use the label property to add content inside the Badge.
Full support Supported since v144. Full support Supported since v148. Full support Supported since v26.

Variants

Default, and dot.

5
---
import { Badge } from "@opui/astro"
---
<Badge label="5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge dot>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<span class="anchor badge" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>
<span class="anchor badge dot" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating"> <span class="badge-indicator"></span> </span>
</span>

Severities

critical, info, neutral, success, warning.

5 5 5 5 5
---
import { Badge } from "@opui/astro"
---
<Badge color="critical" label="5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge color="info" label="5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge color="success" label="5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge color="warning" label="5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge color="neutral" label="5">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<span class="anchor badge critical" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>
<span class="anchor badge info" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>
<span class="anchor badge success" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>
<span class="anchor badge warning" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>
<span class="anchor badge neutral" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>

Visibility

Change the badge's visibility using the invisible prop.

---
import { Badge } from "@opui/astro"
---
<Badge label="5" invisible>
<!-- -->
</Badge>
<Badge dot invisible>
<!-- -->
</Badge>
<script type="module">
function o() {
const c = document.querySelectorAll("#badge-visibility-toggle"),
n = new Set();
c.forEach((e) => {
const t = e.closest(".example-container");
t && t.querySelectorAll(".badge").forEach((i) => n.add(i));
});
function a(e) {
(n.forEach((t) => {
t.classList.toggle("invisible", e);
}),
c.forEach((t) => {
t.checked !== e && (t.checked = e);
}));
}
(c.forEach((e) => {
e.addEventListener("change", () => a(e.checked));
}),
c.length > 0 && a(c[0].checked));
}
o();
document.addEventListener("astro:after-swap", o);
</script>
<span class="anchor badge invisible" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="5">5</span>
</span>
</span>
<span class="anchor badge dot invisible" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating"> <span class="badge-indicator"></span> </span>
</span>

Alignment

Where the badge should be placed over the child.

start-start, default, end-start, end-end.

35 99+ OK! 3K
---
import { Badge } from "@opui/astro"
---
<Badge alignment="start-start" label="35">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge label="99+">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge alignment="end-start" label="OK!">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<Badge alignment="end-end" label="3K">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
><path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path></svg
>
</Badge>
<span
class="anchor badge start-start"
style="
--anchor-position-area: start start;
--_anchor-inset: auto 100% 100% auto;
"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="35">35</span>
</span>
</span>
<span class="anchor badge" style="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="99+">99+</span>
</span>
</span>
<span
class="anchor badge end-start"
style="
--anchor-position-area: end start;
--_anchor-inset: 100% 100% auto auto;
"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="OK!">OK!</span>
</span>
</span>
<span
class="anchor badge end-end"
style="--anchor-position-area: end end; --_anchor-inset: 100% auto auto 100%"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
fill="currentColor"
d="M2.004 9.303A4.5 4.5 0 0 1 6.5 5h19a4.5 4.5 0 0 1 4.496 4.303l-1.476.82L16 16.864L3.48 10.123zM2 11.588V22.5A4.5 4.5 0 0 0 6.5 27h19a4.5 4.5 0 0 0 4.5-4.5V11.588l-.526.293l-13 7a1 1 0 0 1-.948 0L2.514 11.874z"
></path>
</svg>
<span class="anchor-floating">
<span class="badge-indicator" aria-label="3K">3K</span>
</span>
</span>

Anatomy

The badge component is composed of two main elements:

  1. Element to wrap
  2. Badge
5

API

Prop Type Default Description
alignment "start-start" | "start-end" | "end-start" | "end-end" "start-end" Position of the badge relative to its container.
color "critical" | "ok" | "good" | "warning" - The color variant of the badge.
dot boolean false Renders the badge as a simple dot.
invisible boolean false Hides the badge.
label string | number - Screen reader label for the badge.

Browser support

Full support Supported since v144. Full support Supported since v148. Full support Supported since v26.

See also the full browser support guide.

Installation

Dependencies

@layer components.extended {
:where(.badge) {
--_anchor-tx: -50%;
--_anchor-ty: 50%;
--_badge-inset: auto auto 100% 100%;
--_bg-color: var(--primary);
--_border-color: var(--primary);
--_dot-size: var(--size-2);
--_size: var(--size-4);
--_text-color: var(--gray-1);
display: inline-flex;
position: relative;
vertical-align: middle;
/* Floating wrapper: traditional inset-based positioning so this works
in browsers without position-area support (Firefox, older Safari). */
&>.anchor-floating:not([popover]) {
inset: var(--_badge-inset);
position-anchor: auto;
position-area: none;
}
/* Indicator */
&>.anchor-floating>.badge-indicator {
background-color: var(--_bg-color);
block-size: var(--_size);
border: 2px solid var(--_border-color);
border-radius: var(--radius-round);
color: var(--_text-color);
display: grid;
font-size: 12px;
font-weight: 500;
inline-size: max-content;
line-height: normal;
min-inline-size: var(--_size);
padding-inline: var(--size-1);
place-items: center;
text-align: center;
transition: opacity 0.2s var(--ease-out-1);
}
/* Colors */
&.critical {
--_bg-color: var(--critical);
--_border-color: var(--critical);
}
&.success {
--_bg-color: var(--success);
--_border-color: var(--success);
}
&.info {
--_bg-color: var(--info);
--_border-color: var(--info);
}
&.warning {
--_bg-color: var(--warning);
--_border-color: var(--warning);
}
&.neutral {
--_bg-color: var(--neutral);
--_border-color: var(--neutral);
}
/* Alignment */
&.start-start {
--_anchor-tx: 50%;
--_anchor-ty: 50%;
--_badge-inset: auto 100% 100% auto;
}
&.end-start {
--_anchor-tx: 50%;
--_anchor-ty: -50%;
--_badge-inset: 100% 100% auto auto;
}
&.end-end {
--_anchor-tx: -50%;
--_anchor-ty: -50%;
--_badge-inset: 100% auto auto 100%;
}
/* Dot */
&.dot {
--_anchor-tx: calc((var(--_dot-size) - 2px) * -1);
--_anchor-ty: var(--_dot-size);
}
&.dot>.anchor-floating>.badge-indicator {
block-size: var(--_dot-size);
inline-size: var(--_dot-size);
min-inline-size: var(--_dot-size);
padding: 0;
}
/* Visibility */
&.invisible>.anchor-floating>.badge-indicator {
opacity: 0;
pointer-events: none;
}
}
}
@layer components.root {
:where(.anchor) {
anchor-name: --anchor;
anchor-scope: --anchor;
display: inline-block;
inline-size: fit-content;
/* Always-visible */
&>.anchor-floating:not([popover]) {
block-size: max-content;
inline-size: max-content;
position: absolute;
position-anchor: --anchor;
position-area: var(--anchor-position-area, start end);
translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0);
}
/* Hover-triggered */
&>.anchor-floating[popover] {
inset: unset;
margin: 0;
position: absolute;
position-area: var(--anchor-position-area, start end);
translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0);
}
}
}