Thread panel

The session history, one rail

Thread panel is the left edge of a chat or agent product: the brand, a new-thread action with its shortcut hint, standing controls, the grouped history, and the profile footer. It is fully controlled and surface-less, so the host owns the active thread, the navigation, and the band colour it sits on. It began as the agent workbench template's threads panel and graduated into the library once the shape proved out.

The full anatomy

Every section is optional and renders only when its props do. Here the panel carries all of them; clicking a thread moves the controlled selection, and the history is the one region that scrolls.

Skylark

Collapse to a rail

With onExpandedChange wired, the header grows a toggle and the panel folds to App sidebar's 64px icon rail: the panel animates its own width, labels fade under the sweeping clip, rows become circular icon buttons, and the history steps out of the way. Collapsed, the logo is the expand button. Try it.

Skylark

Threads alone

With nothing but groups, the panel is a bare history list. A flat list is one group with no label.

The thread lifecycle

Rows carry a real history's lifecycle, all controlled from outside. A pending thread holds its title's place with a shimmer while the host generates a name; threadActions hangs an overflow menu on every row, revealed only on hover or focus and built from the compact Dropdown menu; and renamingThreadId swaps a row to an inline rename field, where Enter commits and Escape cancels. Long titles fade out under a trailing mask rather than clipping, so the revealed trigger never collides with text. Try it: start a new chat, then rename or delete it from the row's menu.

Timestamps on the trailing edge

Each thread can carry a small meta caption, the usual home for a relative time.

Detail rows

A row scales from a bare title to the full detail anatomy: an unread dot leading the title, a quiet description line under the same trailing fade, and a trailing cluster pairing a session glyph with the meta caption.

Pinned threads

Pinning is a grouping the host owns: a pinned thread carries the pin mark and lives in its own leading group, and pin or unpin travel through the row menu like any other thread action. Try it from a row's overflow menu.

Projects

Between the standing controls and the history, the panel can carry a projects section: rows with the controls' anatomy under their own overline header, with a quiet new-project button. The active project fills like an active thread, and collapsed the rows fold to icon circles while the header steps aside.

Skylark
Projects

Rows as links

Give a thread an href and its row renders as a real anchor, with the active row announcing aria-current. Rendered this way the panel needs no callbacks at all, so it can come straight from a Server Component.

tsx
// From the npm package
import { ThreadPanel } from 'rift-ds/components/ThreadPanel/ThreadPanel';

// Or as source you own, via the shadcn CLI
npx shadcn@latest add https://rift-ds.com/r/thread-panel.json