Notification Dot
<span> + ring-2 ring-[#09090b]
A small dot or count badge overlaid on an icon, avatar, or nav item. Used to signal unread notifications, online status, or pending actions.
Overview
Preview
3
AM
Notifications12
Count badge on icon
Preview
html
<div class="relative inline-flex">
<button aria-label="Notifications (3 unread)" class="...">
<!-- bell icon -->
</button>
<!-- Badge: aria-hidden because the count is in aria-label above -->
<span aria-hidden="true"
class="absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center
rounded-full bg-[#D40C37] text-[9px] font-bold text-white
ring-2 ring-[#09090b]"
>3</span>
</div>Pulse dot (no count)
Preview
html
<!-- Double-span creates the ping animation -->
<span aria-hidden="true" class="absolute -top-1 -right-1 flex h-3 w-3">
<span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#D40C37] opacity-75"></span>
<span class="relative inline-flex h-3 w-3 rounded-full bg-[#D40C37] ring-2 ring-[#09090b]"></span>
</span>On an avatar
html
<div class="relative inline-flex">
<div class="flex h-10 w-10 items-center justify-center rounded-full bg-[#D40C37]/20 text-sm font-semibold text-[#D40C37]">
AM
</div>
<span aria-hidden="true" class="absolute -top-0.5 -right-0.5 h-3.5 w-3.5 rounded-full bg-[#D40C37] ring-2 ring-[#09090b]"></span>
</div>In a nav item
html
<a href="/notifications" class="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-zinc-300 hover:bg-zinc-800">
<!-- icon -->
<span>Notifications</span>
<span aria-hidden="true" class="ml-auto inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-[#D40C37] px-1 text-[9px] font-bold text-white">
12
</span>
</a>Status dots (online / away / offline)
html
<!-- Online -->
<span class="inline-flex h-2 w-2 rounded-full bg-emerald-400"></span>
<!-- Away -->
<span class="inline-flex h-2 w-2 rounded-full bg-amber-400"></span>
<!-- Busy / do not disturb -->
<span class="inline-flex h-2 w-2 rounded-full bg-[#D40C37]"></span>
<!-- Offline -->
<span class="inline-flex h-2 w-2 rounded-full bg-zinc-500"></span>Dynamic count with Vue
vue
<script setup>
import { computed } from 'vue'
const props = defineProps({ count: { type: Number, default: 0 } })
const label = computed(() => props.count > 99 ? '99+' : String(props.count))
</script>
<template>
<div class="relative inline-flex">
<slot />
<span v-if="count > 0"
aria-hidden="true"
class="absolute -top-1 -right-1 flex min-w-4 h-4 items-center justify-center rounded-full
bg-[#D40C37] px-1 text-[9px] font-bold text-white ring-2 ring-[#09090b]"
>{{ label }}</span>
</div>
</template>Accessibility notes
- The count badge should be
aria-hidden="true"when the count is already communicated in the trigger'saria-label(e.g.aria-label="Notifications (3 unread)") - Never rely solely on the dot to convey meaning — ensure the parent element has an accessible name that includes the notification state
- For live updates (new messages arriving), wrap the count in
aria-live="polite"so screen readers announce changes