shadcn.io is not affiliated with official shadcn/ui
Notification Center Skeleton Block for React Aria
A task manager's bell panel that loads in place: All, Mentions and Alerts tabs, Today, Yesterday and Earlier groups, and seven notifications a tab that reload when you change tabs.
Installation
Overview
Show a notification centre while a tab loads, then swap its notifications in without moving anything, with this notification center skeleton for React with React Aria. A card as wide as a bell's popover holds a heading, three Tabs (All, Mentions, Alerts), the groups Today, Yesterday and Earlier and a Notification settings button, from Intaglio, a task manager. The heading, the tabs, the group labels and the button are real from the first paint; each avatar or bell, title, second line and time is a Skeleton bar that becomes the data in the same cell, row by row. Changing tab is what reloads: each tab holds its own seven typed notifications, split three, two and two across the groups, so the card is the same height on every tab. The control is an outline Button, the bands are ruled by Guides, and a polite line says what loaded. For bell menus, notification drawers and any grouped feed behind tabs.
FAQ
What stays local, and how do I wire it to a real query?
Nothing is fetched. The three lists of seven notifications are typed in ALL, MENTIONS and ALERTS, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the data swaps in; Reload goes back to the bars and in again. To wire it for real, delete the timer, the Load button and the polite line, and set data-state (loading or ready) and aria-busy on the region from your query's pending state, or use the bars as a Suspense fallback and render the real rows when they arrive. Changing tab would request that tab's list; keep the tab in state and let your query key depend on it. The bars are derived from the same array as the data, so keep one row component for both.
Why doesn't the page jump when the data arrives?
Each bar and its data sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. All three tabs have seven rows in the same three groups, every row is a fixed height with single-line text, and the tab's panel is only rendered while it is selected, so the card is the same height on every tab. The polite line under the panel reserves two lines, so the panel is exactly as tall before, during and after loading at every width.
Why does changing tab show the bars again?
In a real app the next tab's notifications have to come from somewhere, so the tab is a reload source: choosing one puts the card back to loading for 700 milliseconds and then shows that tab's typed list. Choosing the tab you're on does nothing. The keyboard works as in any tab list: arrow keys move between tabs, and the panel is reachable by Tab.
Why do alerts have a bell instead of initials?
A person's notification shows two initials. A system alert, such as a sprint closing or a failed sync, has no author, so it shows a bell in the same circle. The two share one box, so rows keep their size.
Is it accessible?
The region is marked busy while it loads and carries a screen-reader-only "Loading notifications…", and the polite line announces what loaded once. The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The pulse stops when the data is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant.