# Notifications

> A bell with the count of what's new, and the list it opens, grouped by day, with Mark all as read.

- Name: `notifications`
- Status: beta
- Categories: overlays, feedback
- File: the install writes `notifications.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `@base-ui/react`, `lucide-react`. The install adds them.
- Other registry items: `@arbokui/action-keys`, `@arbokui/avatar`, `@arbokui/badge`, `@arbokui/button`, `@arbokui/popover`, `@arbokui/tool-button`. The install adds them.
- Gallery: https://arbokui.com/components/notifications
- Registry item: https://arbokui.com/r/notifications.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/notifications
   ```

## Use it for

- The bell in an app's header: what happened elsewhere while you were away, like an approval or a meeting moved.
- Give each item a title for what happened, the person who did it (or an icon), and meta for when and where: "18:04 · Design".
- Group items with group: "Today", "Yesterday", "Earlier". Groups show in the order they first appear.
- Opening one marks it read, closes the list, and calls onOpenItem. Take people to what it is about there.
- Mark all as read clears the dots at once, with Undo for 8 seconds. ⌘Z takes it back too. onReadAll runs when the window ends.
- Use inline to draw the open list in a card or a doc, with no bell.

## Avoid it for

- News with a place on the screen. Show it there, like a status on its row.
- The result of something you just did. Show it on the control you pressed.
- Messages people reply to. Use a messages list.

## Props

- `items`: `NotificationItem[]`. Required. { id, title, person?, photo?, icon?: ReactNode, meta?, group?, read? }.
- `onOpenItem`: `(item: NotificationItem) => void`. Opens what it is about.
- `onRead`: `(ids: string[]) => void`. Marked read by opening it.
- `onReadAll`: `(ids: string[]) => void`. Mark all as read, once its 8-second undo window ends.
- `inline`: `boolean`. Default `false`. Draws the open list in the page's flow, with no bell.
- `className`: `string`. Extra classes on the bell, or on the list with inline. Later classes win.

## Accessibility

- The bell is a button named with the count, like "Notifications, 3 new". It says it opens a dialog.
- The list is a dialog named "Notifications". Tab moves through Mark all as read, Close, and the rows, and wraps inside the list, even when pressed fast. The rows carry tabindex="0", so Safari keeps them in Tab too. Esc or Close shuts it and puts focus back on the bell.
- Each row is a button. A new one ends with a dot, which screen readers hear as "New", and forced-colors mode draws as a ring.
- Mark all as read says how many it marked in a polite live region. Its Undo undoes only once 1.2 seconds have passed, so a double press never undoes.

## Examples

### In a header

```tsx
import { CalendarDays } from "lucide-react";

<Notifications
  items={[
    { id: "1", person: "Kate Clarke", title: "Kate Clarke agreed to the launch plan", meta: "18:04 · Design", group: "Today" },
    { id: "2", icon: <CalendarDays />, title: "Saturday's workshop moved to 11:00", meta: "Calendar", group: "Yesterday", read: true },
  ]}
  onOpenItem={(item) => console.log("open", item.id)}
/>
```
