Badge

ui-badge is an inline label with a filled or outlined background. It has no behaviour of its own. Put it next to the text it describes, or inside a link or button when it should be interactive.

Previewindex.html
Badge Secondary Destructive Outline
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Badge demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/badge.html"></import-element>

  <ui-badge>Badge</ui-badge>
  <ui-badge variant="secondary">Secondary</ui-badge>
  <ui-badge variant="destructive">Destructive</ui-badge>
  <ui-badge variant="outline">Outline</ui-badge>
</body>
</html>

Examples

With an icon

A slotted <svg> is sized to calc(var(--spacing) * 3).

Previewindex.html
Verified Pending
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Badge demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/badge.html"></import-element>

  <ui-badge variant="secondary">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
    Verified
  </ui-badge>
  <ui-badge variant="outline">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
    Pending
  </ui-badge>
</body>
</html>

Shapes

shape="pill" rounds the ends fully. shape="round" makes a 20px circle for counts, with tabular numbers so the width stays steady as the count changes.

Previewindex.html
Pill Beta 8 99 20+
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Badge demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/badge.html"></import-element>

  <ui-badge shape="pill">Pill</ui-badge>
  <ui-badge variant="secondary" shape="pill">Beta</ui-badge>
  <ui-badge shape="round">8</ui-badge>
  <ui-badge variant="destructive" shape="round">99</ui-badge>
  <ui-badge variant="outline" shape="round">20+</ui-badge>
</body>
</html>

Wrap the badge in an <a> to make it a link. The badge itself has no interactive behaviour.

Previewindex.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Badge demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/badge.html"></import-element>

  <a href="#badge"><ui-badge variant="outline">#release-notes</ui-badge></a>
</body>
</html>

Status from state

Bind variant with _variant to pick the style from component state, using a lookup table.

Previewindex.htmlbadge-status-demo.html
Next status
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Badge demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/badge.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>

  <import-element from="./badge-status-demo.html"></import-element>
  <badge-status-demo></badge-status-demo>
</body>
</html>
<custom-element name="badge-status-demo">
  <script>
    const VARIANTS = { paid: "default", pending: "secondary", failed: "destructive" };

    const order = useState({
      status: "pending",
      get variant() {
        return VARIANTS[this.status];
      },
    });

    function cycle() {
      const statuses = Object.keys(VARIANTS);
      order.status = statuses[(statuses.indexOf(order.status) + 1) % statuses.length];
    }
  </script>
  <style>
    :host {
      display: flex;
      align-items: center;
      gap: calc(var(--spacing) * 3);
    }
  </style>
  <ui-badge _variant="#order.variant"><slot name="#order.status"></slot></ui-badge>
  <ui-button size="sm" variant="outline" onclick="cycle()">Next status</ui-button>
</custom-element>

API

Parts

Part Slot Renders
ui-badge (default) An inline label. Its default slot takes any content: text and an optional <svg> icon.

Attributes

Attribute Type Default Description
variant "default" | "secondary" | "destructive" | "outline" "default" Colour scheme of the badge.
shape "default" | "pill" | "round" "default" pill is fully rounded. round is a 20px circle for counts, with tabular numbers.

CSS parts

None. The badge renders only a slot, so style the element itself.

Accessibility

The badge has no role and is read as plain text. If the colour carries meaning (for example red for failed), make sure the text says the same thing.

Edit this page on GitHub · View as Markdown