shadcn.io is an independent project built on shadcn/ui
The trigger reads Notifications with a badge of 2. The sheet lists four people, with initials, what they did, and a time. Unread rows have a dot. Mark All as Read sits at the bottom.
Use it for a feed people open and clear. A Sonner toast is better for a single new event. In Svelte, Ark UI does not track which rows are unread.
Installation
Anatomy

Usage
<Sheet><SheetTrigger>{#snippet asChild(props)}<Button {...props()} variant="outline">Notifications<Badge>{UNREAD_COUNT}</Badge></Button>{/snippet}</SheetTrigger><SheetContent><SheetHeader><SheetTitle>Notifications</SheetTitle><SheetDescription>You have {UNREAD_COUNT} unread notifications</SheetDescription></SheetHeader><ul class="flex flex-col gap-3 p-4">{#each NOTIFICATIONS as notification (notification.id)}<li class={cn(
"flex gap-3 rounded-md border p-3",
notification.unread ? "bg-muted/50" : undefined
)}><Avatar class="size-10"><AvatarFallback class="bg-primary text-primary-foreground">{notification.initials}</AvatarFallback></Avatar><div class="flex flex-1 flex-col gap-1"><div class="flex items-start justify-between gap-2"><div class="flex flex-col"><span class="font-medium text-sm">{notification.author}</span><span class="text-muted-foreground text-xs">{notification.message}</span></div>{#if notification.unread}<span class="mt-1 size-2 shrink-0 rounded-full bg-primary"><span class="sr-only">Unread</span></span>{:else}{/if}</div><span class="text-muted-foreground text-xs">{notification.time}</span></div></li>{/each}</ul><div class="px-4 pb-4"><Button class="w-full" variant="outline">Mark All as Read</Button></div></SheetContent></Sheet>FAQ
How are unread notifications marked?
Unread rows get bg-muted/50 and a small dot at the end of the row. The dot holds a visually hidden Unread, so the state isn't color alone.
Where does the unread count come from?
From the data: the demo counts the items with unread: true, and both the trigger's Badge and the description use that number. Two of the four start unread.
Why initials instead of photos?
The rows use AvatarFallback with the sender's initials on the primary color. Add an AvatarImage before the fallback to show a photo; the initials stay as the fallback while it loads or if it fails.
Does Mark All as Read clear the dots?
Not in this demo: the list is static and the button has no handler. Keep the items in state and set unread to false on every one when it's pressed.
API Reference
Sheet
No extra props in this demo. The rest is on the Sheet page.
Button
Sets props and variant="outline". The rest is on the Button page.
Badge
No extra props in this demo. The rest is on the Badge page.
Avatar
No extra props in this demo. The rest is on the Avatar page.




