Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Pin Limit List Notification Block for Radix UI

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.

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

Keep the few notifications that matter on top, with this pinned list for React with Radix UI. Inside a hairline frame with a plus mark on each corner, two columns share one divider: Pinned on the start side and Recent on the end side. Every row has a type tile, a title, its time and detail and a pin Toggle. Pinning moves a row to Pinned, in the order you pinned, with a limit of three and a count ("2 of 3"); at three, the other pins are marked unavailable and the status says to unpin one to pin another. Unpinning sends a row back to its place in time order. Pinned always shows three slots, with free ones drawn quiet or an Empty state when nothing is pinned, and Recent scrolls in one fixed height, so pinning never changes the block's height. On a phone the columns become one list with two section heads. It's built from Toggle, Empty and Guides, with a CSS entrance only. For a planning tool, a notification list that has favorites or any list with a limit.

FAQ

How do I fill it with my own notifications and a different limit?

Edit NOTES (an id, a kind that picks the icon, a title, a line of desc and an ISO at time) in newest-first order, START_PINNED (the ids pinned when the page opens, in pin order) and LIMIT. The count, the free slots, the Recent heading and the status are worked out from those. Times are written in UTC and shown against AS_OF, so the page reads the same everywhere.

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

The pinned list lives in the page and resets on reload; nothing is sent. To make it real, send the new ordered list of pinned ids from the pin handler and load it from your API with the notifications. Enforce the limit on the server too: the page only stops you from asking.

What happens at the limit?

When three are pinned, the pins on the Recent rows are marked unavailable (a quieter icon, still focusable) and pressing one says "Unpin one to pin another." instead of pinning. Unpinning one frees a slot straight away. The pins on pinned rows always work.

Why doesn't the block change height when I pin?

Pinned keeps room for three rows whatever is in it (a quiet Free slot stands in for each unused one), and Recent is a list of one fixed height that scrolls when there are more rows than fit. Rows are one height too, so a pinned row takes exactly the room of the row it replaced.

Is it accessible?

Every pin is a toggle button named for its notification and says whether it is pressed, so pinned state never depends on the filled icon alone. After pinning or unpinning, focus returns to that row's pin in its new place. The status line is a polite live region present from the start. The row's text is plain, not a link, and the pin is its one control. An unavailable pin stays focusable, so a keyboard user hears why it is unavailable instead of skipping past it.

How does it look on a phone?

The two columns stack into one list: a Pinned head with its three slots, then a Recent head with the scrolling rows. Titles wrap to two lines, and the status line has two lines reserved.