Chat History Sidebar React component
The history sidebar of an AI chat app: conversations grouped by date with pinned chats on top, project folders that filter the list, search with highlighted matches, a row menu to rename, pin, archive, move or delete with undo, a collapsible icon rail and a drawer on small screens.
About the Chat History Sidebar component
Chat History Sidebar is the left-hand column of an AI chat app. Conversations are grouped into Today, Yesterday, the last week, the last month and older, with pinned chats kept at the top, so the one you want is usually a glance away.
Projects work like folders: pick one and the list shows only its chats. Search filters as you type and highlights the matching words. Each chat has a menu to rename it in place, pin it, archive it, move it to another project or delete it, and a toast lets you undo the last delete or archive. Collapse it to a slim icon rail on desktop; on a phone it slides in as a drawer.
When to use it
Use it as the history panel of an AI assistant, a support copilot, an internal knowledge chat or any app where people come back to earlier conversations.
Pass daysAgo from your own dates so the groups match the reader's day, and keep project names short so they fit the rail tooltips and row dots.
Installation
Add the Chat History Sidebar component to your project with the shadcn CLI. It lands in components/chat-history-sidebar.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/chat-history-sidebarOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<ChatHistorySidebar /> accepts 13 props, all optional.
| Prop | Type | Default |
|---|---|---|
| workspace | string | "Lumen" |
| model | string | "Lumen 3" |
| chats | { id: string; title: string; daysAgo: number; prompt: string; answer: string; project?: string; pinned?: boolean; archived?: boolean }[] | — |
| projects | { id: string; name: string; color: string }[] | DEFAULT_PROJECTS |
| user | { name: string; plan?: string } | { name: "Mara Okafor", plan: "Pro" } |
| defaultActiveId | string | null | "c2" |
| defaultCollapsed | boolean | false |
| onSelect | (id: string) => void | — |
| onNew | () => void | — |
| onRename | (id: string, title: string) => void | — |
| onDelete | (id: string) => void | — |
| theme | "dark" | "light" | "dark" |
- workspacestringDefault: "Lumen"
- modelstringDefault: "Lumen 3"
- chats{ id: string; title: string; daysAgo: number; prompt: string; answer: string; project?: string; pinned?: boolean; archived?: boolean }[]
- projects{ id: string; name: string; color: string }[]Default: DEFAULT_PROJECTS
- user{ name: string; plan?: string }Default: { name: "Mara Okafor", plan: "Pro" }
- defaultActiveIdstring | nullDefault: "c2"
- defaultCollapsedbooleanDefault: false
- onSelect(id: string) => void
- onNew() => void
- onRename(id: string, title: string) => void
- onDelete(id: string) => void
- theme"dark" | "light"Default: "dark"
Show all 13 propsShow fewer
| className | string | — |
- classNamestring
npm dependencies
Installed for you by the shadcn CLI.
Chat History Sidebar FAQ
- How are chats sorted into Today, Yesterday and the rest?
- By daysAgo: 0 is Today, 1 is Yesterday, up to 7 is Previous 7 days, up to 30 is Previous 30 days and anything older is Older. Work it out from your timestamps on the server so it never changes during hydration.
- Are rename, pin, move and delete saved?
- They update the block's own state straight away. Save them with onRename and onDelete, and pass the latest chats back in when your data changes. Pin, archive and project moves are easy to add in the same way.
- What happens on small screens?
- Below 720px of its own width the sidebar becomes a drawer. A button in the header opens it, the scrim or the close button shuts it, and picking a chat closes it for you. The width is measured on the block, not the window, so it also works inside narrow panels.
- Does it have keyboard shortcuts?
- ⌘K or Ctrl+K while focus is inside the block opens the sidebar if needed and focuses search. The row menu supports arrow keys, and Escape closes it and returns focus to the ⋯ button.
- Is it accessible?
- The sidebar is a labelled aside with a section per date group, the current chat has aria-current, project filters are toggle buttons, the row menu uses menu and menuitemradio roles, search results are announced and the closed drawer is inert so it can't be tabbed into.