Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Empty Inbox Notification Block for React

A whole-screen empty inbox that can change: a drawn empty tray and one sentence, with muted conversations that come back when you unmute them and go away again when you mute them.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Make the moment of nothing to read worth looking at, with this empty inbox page for React with Base UI. The page keeps the rails and the single ruled band of a whole screen. Inside it a drawn tray in the theme's greys with a tick, the heading "You're all caught up", one sentence and a Shine Button link to notification preferences, the page's one primary. Under them a Collapsible called "Muted conversations (3)" lists three muted threads, each with the day it was muted and an Unmute button. Unmuting one brings it back: the tray gives way to a list of the threads that returned, each with a Mute button, the heading counts them ("1 new notification"), and muting the last one empties the page again. The tray and the list share one fixed-height cell, so the page keeps its height, and the heading takes focus after each change so the new state is read. It's built from Collapsible, Button, Shine Button and Guides, with a CSS entrance only. For an email client, a notification centre or any list that can be emptied.

FAQ

How do I fill it with my own threads?

Edit THREADS at the top of the file. Each has an id, a title, the who and last text of its latest reply, an ISO at time of that reply and an ISO muted day. START_MUTED lists which ids are muted when the page opens (all three here); a thread that isn't muted shows in the inbox list. Every count, the heading and the sentence are worked out from that one list. Times are shown against AS_OF: today as a clock time, yesterday as a word, older as a weekday and date.

What stays local, and how do I make it real?

Muting and unmuting live in the page and reset on reload; nothing is sent and nothing is saved. In your app, load the muted ids from your API, call it from mute and unmute (the id each handler receives is the one to send), and render the inbox from your real unread threads rather than from the unmuted ones. The preferences button is a link: point its href at your settings route.

How do I reach the empty state again?

Unmute a thread, then press Mute on its row. The first time, the page opens empty; after an Unmute it shows the list, and muting the last returned thread brings the tray and "You're all caught up" back, with a polite status that says so. The empty state is a designed state, not a missing one: it has a picture, a sentence and the way forward.

Why does the page not jump between the tray and the list?

The tray and the list sit in one grid cell of a fixed height, and the one not shown is unseen, so the heading, the button and the disclosure never move when it changes. The page is also aligned to the top rather than centred: the Muted conversations disclosure grows when it opens, and a centred page would move its heading by half of that.

Is it accessible?

The heading takes focus after each Unmute or Mute, and a polite status line says what changed ("Unmuted “Launch plan”. It is back in your inbox."), so the removed button never leaves focus on nothing. The disclosure is a real button with an expanded state, each Unmute and Mute names its thread ("Mute Launch plan"), and the drawing is decorative and hidden from assistive technology. On a phone the Mute button shows only its icon, and its name still begins with the word.

How does it look on a phone?

The band keeps its padding and the content its single column. The drawing sits at the same height, the primary button fills the width and is on the first screen, and each returned thread keeps one row: its title, its latest reply with the time, and a Mute button reduced to an icon.

  • Pro

    Loading Skeleton Notification

    Live and empty states

    A narrow activity list that shows its loading state as the exact shape of what loads: six rows of skeleton boxes that give way to the real rows without anything moving.

  • Pro

    A notification centre as a narrow panel: tabs for All, Mentions and Alerts with their own unread counts, rows you press to mark read, a mark all read for the open tab and a clear with an undo.

  • Pro

    A shared support inbox as an app window: a list of notifications under All, Unread and Archived views, and a reading pane with the sender, the time, the text, a context list and mark read, archive and undo.

  • Pro

    An inbox with an unread-only switch and a live count, where a row you read stays in place until you turn the switch off, and zero unread is a designed Inbox zero state.

  • Pro

    Notifications split into Pinned and Recent with a pin on every row and a limit of three: the pinned ones stay on top in the order you pinned them, and at three the other pins say to unpin one first.

  • Pro

    Notifications grouped into Messages, Updates and Alerts in an accordion, each group with an unread count, its own mark read beside the trigger, a one-line summary when folded, and collapse and clear for the whole list.