shadcn.io is not affiliated with official shadcn/ui
Case Timeline Table Block for Vue
A support case history as a table that reads like a timeline: a continuous rail with a node per event, Today and Yesterday day rows, times in a narrow column and chips that filter by event type with counts.
Installation
Overview
Turn a table into a history, with this case timeline table for Vue with Ark UI. Nine events of one support case sit in a native table whose first column draws a continuous rail with a node per event, an icon for a message, a reply, a status change or an internal note. Day rows break the rail into Today, Yesterday and the dates before, worked out from a fixed "as of" day rather than from the clock, and the time of each event sits in a narrow end-aligned column. Each event has its text, a type Badge and an initials Avatar for who wrote it. A rail of four ToggleGroup chips at the start filters by event type, each with its count; they can all be off, which shows an Empty state with a button to turn them back on. The frame has a fixed height, so filtering never moves the page, and on a phone the rail becomes a row of chips above the table. For case histories, audit trails, order tracking and any list that is read as a story.
FAQ
How do I use my own events?
Replace EVENTS with your records, newest first: an id, an ISO instant in UTC, a kind, who wrote it and the text. groupsOf splits them into runs of one day and dayLabel names each run from the AS_OF constant, so "Today" and "Yesterday" are exact whenever you set it. In an app, set AS_OF from the server's clock at render time and format on the server, so the page and the client agree. Kinds and their icons are in KINDS and IconFor.
How is the rail drawn through table rows?
Each row's first cell is positioned and holds a one-pixel line at a fixed distance from the start, behind a round node with the event's icon. Day rows draw the same line, so it is unbroken from the top row to the bottom, and because the node is a span rather than a pseudo-element the cell keeps its table semantics. The distance uses logical properties, so the rail sits at the start of the row in a right-to-left page too.
How do the chips filter, and can all of them be off?
The chips are a multiple-selection ToggleGroup whose value is the list of kinds to show; the count in each is the number of events of that kind in the case. Turning every chip off is allowed on purpose: the table shows its empty state, the polite line says "Showing 0 of 9 events" and Show all turns them back on and puts focus on the first chip. A new filter scrolls the frame back to the top.
What stays local, and how do I connect it to a help desk?
The events are typed and nothing is sent or saved; the demo has no reply box. To make it live, load the case's events from your help desk's API into EVENTS (or a query), keep groupsOf as it is, and add new events to the top as they arrive. A real reply or note is a form that posts, then adds its event to the list; this block only draws the history.
Is it accessible?
Yes. It is a native table with a caption, column heads, a row header for every event and a rowgroup heading for each day. The nodes and icons are decorative because the type is written as a Badge on every event, and times are real time elements read with "UTC". The chips are real toggle buttons in a labelled group, the frame is a keyboard-reachable scroll region, and one polite line reports how many events are shown after each change.
How does it look on a phone?
All three columns stay, since nothing is hidden: the rail, the event and the time. The chips move above the table as a row that scrolls sideways with snapping, and the same frame height holds the events, scrolling inside it. Event text wraps and the type, avatar and name sit on a line under it.