v1.1.1

Notification Badge

Small indicators for counts, status, or attention on elements.

Default

Simple notification dots on icon buttons.

html
<div class="vt-relative vt-inline-flex">
  <button class="vt-notification-btn">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-bell vt-w-5 vt-h-5 vt-text-foreground-primary">
      <path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path>
    </svg>
  </button>
  <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
</div>

<div class="vt-relative vt-inline-flex">
  <button class="vt-notification-btn">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-mail vt-w-5 vt-h-5 vt-text-foreground-primary">
      <path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>
    </svg>
  </button>
  <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
</div>

<div class="vt-relative vt-inline-flex">
  <button class="vt-notification-btn">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-message-circle vt-w-5 vt-h-5 vt-text-foreground-primary">
      <path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>
    </svg>
  </button>
  <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
</div>

With Count

Badges showing numeric counts positioned on icon buttons.

html
3
12
99+
<div class="vt-relative vt-inline-flex">
  <button class="vt-notification-btn">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-bell vt-w-5 vt-h-5 vt-text-foreground-primary">
      <path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path>
    </svg>
  </button>
  <span class="vt-absolute vt--top-1.5 vt--right-1.5 vt-count-badge">3</span>
</div>

<div class="vt-relative vt-inline-flex">
  <button class="vt-notification-btn">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-mail vt-w-5 vt-h-5 vt-text-foreground-primary">
      <path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>
    </svg>
  </button>
  <span class="vt-absolute vt--top-1.5 vt--right-1.5 vt-count-badge">12</span>
</div>

<div class="vt-relative vt-inline-flex">
  <button class="vt-notification-btn">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-message-circle vt-w-5 vt-h-5 vt-text-foreground-primary">
      <path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>
    </svg>
  </button>
  <span class="vt-absolute vt--top-1.5 vt--right-2 vt-count-badge">99+</span>
</div>

Colors

Notification dots in different semantic colors.

html

Red

Blue

Green

Orange

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-bell vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Red</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-mail vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-info-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Blue</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-message-circle vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-info-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Green</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-bell vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-warning-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Orange</p>
</div>

On Avatars

Status indicator dots on avatar circles.

html
User

Online

User

Busy

User

Away

JD

Offline

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <div class="vt-avatar vt-avatar-md">
      <img src="https://i.pravatar.cc/80?img=1" alt="User">
    </div>
    <span class="vt-absolute vt-bottom-0 vt-right-0 vt-w-3 vt-h-3 vt-rounded-full vt-bg-info-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Online</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <div class="vt-avatar vt-avatar-md">
      <img src="https://i.pravatar.cc/80?img=2" alt="User">
    </div>
    <span class="vt-absolute vt-bottom-0 vt-right-0 vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Busy</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <div class="vt-avatar vt-avatar-md">
      <img src="https://i.pravatar.cc/80?img=3" alt="User">
    </div>
    <span class="vt-absolute vt-bottom-0 vt-right-0 vt-w-3 vt-h-3 vt-rounded-full vt-bg-warning-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Away</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <div class="vt-avatar vt-avatar-md">
      <span class="vt-text-sm vt-font-medium vt-text-foreground-muted">JD</span>
    </div>
    <span class="vt-absolute vt-bottom-0 vt-right-0 vt-w-3 vt-h-3 vt-rounded-full vt-bg-foreground-muted vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Offline</p>
</div>

On Text / Tab

Badge counts next to text labels.

html
Inbox 3
Messages 12
Notifications 99+
<div class="vt-flex vt-flex-wrap vt-items-center vt-gap-4">
  <div class="vt-inline-flex vt-items-center vt-gap-2">
    <span class="vt-text-sm vt-font-medium vt-text-foreground-primary">Inbox</span>
    <span class="vt-count-badge vt-px-1.5">3</span>
  </div>
  <div class="vt-inline-flex vt-items-center vt-gap-2">
    <span class="vt-text-sm vt-font-medium vt-text-foreground-primary">Messages</span>
    <span class="vt-count-badge vt-px-1.5">12</span>
  </div>
  <div class="vt-inline-flex vt-items-center vt-gap-2">
    <span class="vt-text-sm vt-font-medium vt-text-foreground-primary">Notifications</span>
    <span class="vt-count-badge vt-px-1.5">99+</span>
  </div>
</div>

<div class="vt-flex vt-items-center vt-gap-1 vt-border-b vt-border-border-default">
  <button class="vt-inline-flex vt-items-center vt-gap-2 vt-px-4 vt-py-2 vt-text-sm vt-font-medium vt-border-b-2 vt-border-info-fill vt-text-foreground-primary vt--mb-px">
    Inbox
    <span class="vt-count-badge vt-px-1.5 vt-bg-info-fill">3</span>
  </button>
  <button class="vt-inline-flex vt-items-center vt-gap-2 vt-px-4 vt-py-2 vt-text-sm vt-font-medium vt-text-foreground-muted vt-border-b-2 vt-border-transparent vt-hover:text-foreground-primary vt-transition-colors vt--mb-px">
    Sent
  </button>
  <button class="vt-inline-flex vt-items-center vt-gap-2 vt-px-4 vt-py-2 vt-text-sm vt-font-medium vt-text-foreground-muted vt-border-b-2 vt-border-transparent vt-hover:text-foreground-primary vt-transition-colors vt--mb-px">
    Drafts
    <span class="vt-count-badge vt-px-1.5 vt-bg-surface-moderate vt-text-foreground-muted">5</span>
  </button>
</div>

Animated

Notification dots with a ping animation to draw attention.

html

Static

Pinging

7

Pinging count

User

Online ping

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-bell vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1 vt--right-1 vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Static</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-bell vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1 vt--right-1 vt-flex vt-h-3 vt-w-3">
      <span class="vt-animate-ping vt-absolute vt-inline-flex vt-h-full vt-w-full vt-rounded-full vt-bg-error-fill vt-opacity-75"></span>
      <span class="vt-relative vt-inline-flex vt-rounded-full vt-h-3 vt-w-3 vt-bg-error-fill vt-ring-2 vt-ring-surface-page"></span>
    </span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Pinging</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <button class="vt-notification-btn">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-mail vt-w-5 vt-h-5 vt-text-foreground-primary">
        <path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>
      </svg>
    </button>
    <span class="vt-absolute vt--top-1.5 vt--right-1.5 vt-flex">
      <span class="vt-animate-ping vt-absolute vt-inline-flex vt-h-5 vt-w-5 vt-rounded-full vt-bg-error-fill vt-opacity-75"></span>
      <span class="vt-relative vt-count-badge">7</span>
    </span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Pinging count</p>
</div>

<div class="vt-text-center">
  <div class="vt-relative vt-inline-flex">
    <div class="vt-avatar vt-avatar-md">
      <img src="https://i.pravatar.cc/80?img=5" alt="User">
    </div>
    <span class="vt-absolute vt-bottom-0 vt-right-0 vt-flex vt-h-3 vt-w-3">
      <span class="vt-animate-ping vt-absolute vt-inline-flex vt-h-full vt-w-full vt-rounded-full vt-bg-info-fill vt-opacity-75"></span>
      <span class="vt-relative vt-inline-flex vt-rounded-full vt-h-3 vt-w-3 vt-bg-info-fill vt-ring-2 vt-ring-surface-page"></span>
    </span>
  </div>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Online ping</p>
</div>

Guidelines

Dot or count indicator overlaid on a bell/icon (error-red dot = attention).

Do
Use a small red dot to flag unseen items needing attention.
Don't
Don't put attention dots on every icon at once.

API Reference

All CSS classes available for the Notification Badge component.

Class Type Description
vt-relative vt-inline-flex Container Relative container for absolute badge positioning
vt-absolute vt--top-1 vt--right-1 Position Dot badge position — offset to top-right corner
vt-absolute vt--top-1.5 vt--right-1.5 Position Count badge position — slightly more offset for larger badge
vt-w-3 vt-h-3 vt-rounded-full Size Dot indicator size (12px circle)
vt-min-w-5 vt-h-5 vt-px-1 Size Count badge size — expands with content
vt-text-xs vt-font-bold Typography Count badge text — 12px bold
vt-bg-error-fill vt-text-generic-white Color Default red badge with white text
vt-bg-info-fill Color Blue badge variant for informational status
vt-bg-warning-fill Color Orange badge variant for warning status
vt-ring-2 vt-ring-surface-page Effect White ring to separate badge from parent element
vt-animate-ping Animation Pulsing animation to draw attention

Accessibility

Keyboard and screen reader support.

Feature Details
Screen reader Badge count should have aria-label, e.g. "5 notifications"
Hidden badge Visual-only dot indicators need sr-only text describing the status
Updates Dynamic count changes should use aria-live="polite" to announce updates
Decorative If count is also shown elsewhere, badge can be aria-hidden="true"
Built with: