# Prebuilt Inbox Component

This guide covers the prebuilt Notification Inbox components for a Mass Notification Inbox.

native-notify ships a prebuilt Notification Inbox: a bell icon for your app header with an unread dot, and a full-screen inbox screen that opens when the bell is tapped. In `mode="mass"` the inbox displays your app-wide (mass) notifications — the same data returned by the [getNotificationInbox function](/docs/mass-notification-inbox/getNotificationInbox).

## Quick start

Add the `<NotificationInboxBell>` component to your header with `mode="mass"` (the default):

```jsx
import { NotificationInboxBell } from 'native-notify';

// Expo Router / React Navigation header:
<Stack.Screen
  name="index"
  options={{
    headerRight: () => (
      <NotificationInboxBell
        appId={yourAppId}
        appToken="yourAppToken"
        mode="mass" // default — can be omitted
      />
    ),
  }}
/>
```

Tapping the bell opens the built-in inbox screen, which fetches your mass notifications and shows an unread dot when there are new ones.

`appId` and `appToken` are optional on every inbox component when you set them once with [`NativeNotify.init()` or `<NativeNotifyProvider>`](/docs/setup/installation) — pass them explicitly only if you prefer.

## Mass mode notes

> **Note:**
>
> **The unread dot needs a real device.** Read state is tracked per device using the device's Expo push token, so the dot only appears on a physical device that has registered a token. On Android, test on a development build — Expo Go can't mint Expo push tokens since SDK 53. On web and simulators the bell simply never shows the unread dot.

- **Delete is not available in mass mode.** The mass delete endpoint removes a notification for every user, so it is an admin action handled from the Native Notify dashboard — it is intentionally not wired into the component.
- **Opening the inbox marks the fetched notifications as read**, so the unread dot clears when the inbox opens.
- **The app icon badge follows the unread count** — whenever the unread count refreshes, it is synced to the app icon badge with `Notifications.setBadgeCountAsync()`. Pass `syncBadge={false}` to opt out.

## Props

`NotificationInboxBell` accepts the following props:

| Prop                  | Type                               | Default                  | Description                                                                      |
| --------------------- | ---------------------------------- | ------------------------ | -------------------------------------------------------------------------------- |
| `appId`               | `number \| string`                 | —                        | Your Native Notify App ID.                                                       |
| `appToken`            | `string`                           | —                        | Your Native Notify App Token.                                                    |
| `mode`                | `'mass' \| 'indie'`                | `'mass'`                 | Which inbox to load.                                                             |
| `subId`               | `number \| string`                 | —                        | Required when `mode="indie"` (the user's unique ID).                             |
| `take`                | `number`                           | `20`                     | Number of notifications fetched per page.                                        |
| `syncBadge`           | `boolean`                          | `true`                   | Sync the unread count to the app icon badge.                                     |
| `colors`              | `object`                           | light/dark theme         | Partial theme override — see [Colors](#colors).                                  |
| `title`               | `string`                           | `'Notifications'`        | Inbox header title.                                                              |
| `emptyText`           | `string`                           | `"You're all caught up"` | Empty-state body text.                                                           |
| `allowDelete`         | `boolean`                          | —                        | Per-row delete button — only ever shown in indie mode. Mass mode never shows it. |
| `onNotificationPress` | `(notification) => void`           | —                        | Called when a row is tapped.                                                     |
| `onOpen`              | `() => void`                       | —                        | If set, called instead of opening the built-in inbox screen.                     |
| `showCount`           | `boolean`                          | `false`                  | Show a numeric unread badge instead of a plain dot.                              |
| `maxCount`            | `number`                           | `99`                     | Badge cap — shows "99+" past it.                                                 |
| `renderIcon`          | `({ unreadCount, color }) => node` | bundled bell icon        | Custom bell icon.                                                                |
| `iconSize`            | `number`                           | `24`                     | Bell icon size.                                                                  |
| `iconStyle`           | `StyleProp<ImageStyle>`            | —                        | Style override for the bell icon.                                                |
| `containerStyle`      | `StyleProp<ViewStyle>`             | —                        | Style override for the bell container.                                           |

### Colors

Colors follow the device's light/dark mode automatically. Pass any subset of the keys below in `colors` to override the theme:

```jsx
<NotificationInboxBell
  appId={yourAppId}
  appToken="yourAppToken"
  colors={{ dot: '#EF4444', accent: '#2563EB' }}
/>
```

- `icon`, `dot`, `badgeText`
- `background`, `headerBackground`, `card`, `border`
- `title`, `text`, `mutedText`, `emptyTitle`, `emptyText`
- `accent`, `delete`

## Custom screen and headless hook

Want your own trigger instead of the bell? Render `<NotificationInboxScreen>` and control the modal yourself with `visible` / `onClose` — it accepts all of the props above plus these:

| Prop      | Type         | Default | Description                         |
| --------- | ------------ | ------- | ----------------------------------- |
| `visible` | `boolean`    | —       | Whether the inbox modal is shown.   |
| `onClose` | `() => void` | —       | Called when the modal is dismissed. |

To build a fully custom UI, use the headless hook:

```jsx
import { useNotificationInbox } from 'native-notify';

const {
  notifications,   // fetched inbox rows
  unreadCount,     // unread count for your own badge
  loading,         // initial load in progress
  refreshing,      // pull-to-refresh in progress
  loadingMore,     // next page in progress
  hasMore,         // more pages available
  error,           // error message, if any
  openInbox,       // marks fetched notifications as read
  refresh,
  refreshUnread,
  loadMore,
  deleteNotification,
} = useNotificationInbox({
  appId: yourAppId,
  appToken: 'yourAppToken',
  mode: 'mass',
  take: 20,
  syncBadge: true, // sync the unread count to the app icon badge
});
```

Exact pagination is available for custom UIs: [`getNotificationInboxPage()`](/docs/mass-notification-inbox/getNotificationInbox) returns `{ rows, total }` — the server's `X-Total-Count` — so "load more" is exact instead of a guess.

## Inbox row data

Each row in the inbox is shaped like this:

```jsx
{
  notification_id, // unique notification ID
  date,            // notification date
  title,           // notification title
  message,         // notification message
  pushData,        // data object sent with the push notification
}
```
