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
Online
Busy
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
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
Don't
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" |