Elements

Elements · AUI connected · AUI

Thread list sidebar

A complete sidebar shell that places the runtime thread list beside the active conversation.

How can I help you today?

fig. 01

Installation

npx shadcn@latest add "@assistant-ui/threadlist-sidebar"
First time? Set up a runtime

Runtime components read their state from an assistant-ui runtime. Add one to an existing project:

npx assistant-ui@latest init

Then wrap your app in a runtime provider:

import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useChatRuntime, AssistantChatTransport } from "@assistant-ui/ai-sdk";

export default function App() {
  const runtime = useChatRuntime({
    transport: new AssistantChatTransport({ api: "/api/chat" }),
  });

  return (
    <AssistantRuntimeProvider runtime={runtime}>
      {/* your components */}
    </AssistantRuntimeProvider>
  );
}

The installation guide covers new projects, templates, and API routes.

Thread list sidebar wraps the runtime Thread list in a full collapsible sidebar shell: a header, a footer, and an optional rail for collapsing it. It has no standalone form, since it renders the runtime-only thread list internally and forwards every other prop straight to the underlying Sidebar shell.

Getting started

ThreadListSidebar needs a runtime provider and the sidebar shell's own layout provider around it.

Compose it with a Thread

app/layout.tsx
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
import { ThreadListSidebar } from "@/components/assistant-ui/elements/threadlist-sidebar.aui";
import { Thread } from "@/components/assistant-ui/elements/thread.aui";

export default function Layout() {
  return (
    <SidebarProvider>
      <ThreadListSidebar />
      <SidebarInset>
        <Thread />
      </SidebarInset>
    </SidebarProvider>
  );
}

Needs an AssistantRuntimeProvider ancestor around the whole tree. SidebarProvider is the sidebar shell's own layout context, unrelated to the runtime; both are required.

Anatomy

<Sidebar {...props}>
  <SidebarHeader>{/* assistant-ui wordmark, links out */}</SidebarHeader>
  <SidebarContent>
    <ThreadList />
  </SidebarContent>
  {props.collapsible !== "none" && <SidebarRail />}
  <SidebarFooter>{/* GitHub link */}</SidebarFooter>
</Sidebar>

The header links out to assistant-ui.com and the footer to its GitHub repository; both are placeholders meant to be replaced with your own branding and support links. The collapse rail renders only when collapsible is not "none", following whatever Sidebar itself was given.

Examples

Change the collapse behavior

<ThreadListSidebar collapsible="icon" />

Every Sidebar prop passes straight through, collapsible, side, and variant included, since ThreadListSidebar only adds the header, footer, and thread list between them.

ThreadListSidebar does not expose header or footer content as props. Replace the literal links in your copy of threadlist-sidebar.aui.tsx with your own product name and support link.

Add a trigger to open it

import { SidebarTrigger } from "@/components/ui/sidebar";

<SidebarTrigger />;

Place it inside SidebarInset, on the main-pane side, to toggle the sidebar from anywhere in your app.

API reference

ThreadListSidebarProps

Extends React.ComponentProps<typeof Sidebar>; every prop is forwarded.

PropTypeDefaultDescription
side"left" | "right""left"Which edge the sidebar docks to.
variant"sidebar" | "floating" | "inset""sidebar"Sidebar chrome style.
collapsible"offcanvas" | "icon" | "none""offcanvas"How it collapses. "none" also removes the rail.