Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Notification List Sheet for Ark UI

A Notifications button with a badge of 2 opens four notes, two of them unread, and a Mark All as Read button.

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 React, Ark UI does not track which rows are unread.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Sheet anatomy: content, close, title, description, footer

Usage

<Sheet>
  <SheetTrigger asChild>
    <Button variant="outline">
      Notifications
      <Badge>{UNREAD_COUNT}</Badge>
    </Button>
  </SheetTrigger>
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Notifications</SheetTitle>
      <SheetDescription>
        You have {UNREAD_COUNT} unread notifications
      </SheetDescription>
    </SheetHeader>
    <ul className="flex flex-col gap-3 p-4">
      {NOTIFICATIONS.map((notification) => (
        <li
          className={cn(
            "flex gap-3 rounded-md border p-3",
            notification.unread ? "bg-muted/50" : undefined
          )}
          key={notification.id}
        >
          <Avatar className="size-10">
            <AvatarFallback className="bg-primary text-primary-foreground">
              {notification.initials}
            </AvatarFallback>
          </Avatar>
          <div className="flex flex-1 flex-col gap-1">
            <div className="flex items-start justify-between gap-2">
              <div className="flex flex-col">
{/* The rest of the file is under Installation. */}

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.

How does the Notifications button open the sheet?

The outline button labeled Notifications is the trigger, and its text is the accessible name. The badge inside it is part of that name, so it's read as Notifications 2. SheetTrigger takes asChild and merges onto the one Button inside it.

What does the sheet announce?

SheetTitle names the dialog for assistive tech, so every sheet renders one; hide it with sr-only when the design has no visible heading. It reads Notifications, and the description reads You have 2 unread notifications.

API Reference

Sheet

Sets asChild. The rest is on the Sheet page.

Button

Sets 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.