shadcn.io is not affiliated with official shadcn/ui
Project Activity Feed Notification Block for Svelte
A project's history as a vertical timeline split in two: six event types as chips with live counts in a start column, and the timeline of who did what beside them, filtered by the types you press, with Load earlier events and a designed empty state.
Installation
Overview
Follow a project by the kind of thing that happened, with this activity feed for Svelte with Ark UI. It is Scopewick, a project manager, in a framed panel with a plus mark on each corner and a hairline divide: a start column of six event types (Joined, Files, Comments, Deploys, Billing, Settings) as a Toggle Group of chips, each with how many events of that type are loaded, and a timeline beside it on a rail of type tiles, each event written as who did what with its type, a detail and its time. Pressing chips narrows the timeline to those types (pressing none shows everything), a status line says how many of the loaded events are showing, and "Load earlier events" adds four older ones to the same scroller, moves focus to the first of them and updates every count. Billing has nothing in the first ten events, so its chip leads to an Empty state that offers the way out. Lines come from Guides. For project tools, workspaces and any shared history people filter by type.
FAQ
How do I fill it with my own events?
Edit ENTRIES: each has an id, a kind (joined, files, comments, deploys, billing or settings), a who, the text that follows the name, a short detail and an ISO at in UTC, newest first. FIRST is how many are loaded when the page opens, and the rest wait behind "Load earlier events". AS_OF is the page's fixed now, so a time reads "09:12", "Yesterday 17:40" or "Mon 12 Oct, 16:20" and never "3 minutes ago".
How does the type filter work?
Each chip is a toggle: press Files and Deploys and only those two types show, press them again to take them back. With nothing pressed every type shows, so the filter never starts empty. The count on a chip is how many events of that type are loaded, and it grows when you load earlier ones. A chip with zero stays pressable and leads to a designed empty state with a button that shows every type.
What does Load earlier events do, and what stays local?
It reveals the four older events typed in the same list, keeps the filter you chose, says "Loaded 4 earlier events" in the status line and moves focus to the first new row so a keyboard or screen reader user lands on what arrived. Nothing is requested: the events are typed in the file and a reload starts again from the first ten. In your app call your history endpoint from loadEarlier, append the page and keep the focus line.
Does a type rely on its icon or colour?
No. Every row says its type in words ("Files, 14.2 MB, 08:47 UTC") next to a glyph, the chips carry the word and the count, and a pressed chip is solid foreground with the same text. The block uses no status colour at all, so it reads the same in every theme and for people who do not see colour.
How does it look on a phone?
The chips become a row above the timeline that scrolls sideways inside itself, and the timeline keeps its own scroller so the page does not grow with every event. The status line and the Load button are in the same places as on a desktop.
Is it accessible?
The chips are a labelled group of toggle buttons, each reading its type and count. The timeline is an ordered list inside a scroll region the keyboard can reach, every time is a time element with its machine value, and the one status line is polite. Arrow keys move between chips, down and up from the medium breakpoint and sideways below it, and pressing a chip never moves the page.