Panel dock
A resizable panel docked beside or under the chat for files, previews and sources, which collapses out of the way.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/panel-dock-side.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/panel-dock-side.json
Usage & API
Example
import { SidePanelDock } from "@/components/ai/panel-dock-side"
<SidePanelDock
children={children}
tabs={[]}
activeTab="…"
onTabChange={() => {}}
panel={panel}
width={1}
onWidthChange={() => {}}
collapsed={true}
onCollapsedChange={() => {}}
sheetOpen={true}
onSheetOpenChange={() => {}}
/>Props SidePanelDock
| Prop | Type & description | Required |
|---|---|---|
children | ReactNodeThe main area, usually the chat. | Required |
tabs | DockTab[] | Required |
activeTab | string | Required |
onTabChange | (id: string) => void | Required |
panel | ReactNodeContent for the active tab. | Required |
width | number | Required |
onWidthChange | (width: number) => void | Required |
collapsed | boolean | Required |
onCollapsedChange | (collapsed: boolean) => void | Required |
sheetOpen | booleanBelow the md breakpoint the panel opens as a bottom sheet instead. | Required |
onSheetOpenChange | (open: boolean) => void | Required |
defaultWidth | number | Optional |
minWidth | number | Optional |
maxWidth | number | Optional |
minMainWidth | numberRoom the main area always keeps, in px. | Optional |
actions | ReactNodeExtra buttons in the panel header, before the collapse button. | Optional |
label | string | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
The side dock sits on the right of the chat. A resize handle changes the width. Collapse panel hides it, Expand panel brings it back, and on a small screen Open and Close panel run the sheet. Tabs can show a count. The preview's panel is a document preview with Reload preview, a preview-width control, and a sources list. The composer asks for a change. The header names the page being discussed. Dragging stops at the minimums you set, so the thread never shrinks to nothing.
Example
import { BottomPanelDock } from "@/components/ai/panel-dock-bottom"
<BottomPanelDock
children={children}
tabs={[]}
activeTab="…"
onTabChange={() => {}}
panel={panel}
height={1}
onHeightChange={() => {}}
collapsed={true}
onCollapsedChange={() => {}}
maximized={true}
onMaximizedChange={() => {}}
summary={summary}
/>Props BottomPanelDock
| Prop | Type & description | Required |
|---|---|---|
children | ReactNodeThe main area above the panel, usually an editor. | Required |
tabs | BottomDockTab[] | Required |
activeTab | string | Required |
onTabChange | (id: string) => void | Required |
panel | ReactNodeContent for the active tab. | Required |
height | number | Required |
onHeightChange | (height: number) => void | Required |
collapsed | boolean | Required |
onCollapsedChange | (collapsed: boolean) => void | Required |
maximized | boolean | Required |
onMaximizedChange | (maximized: boolean) => void | Required |
summary | ReactNodeOne line shown in the status bar, e.g. "2 problems · tests passing". | Required |
status | ReactNodeLeft side of the status bar. | Optional |
statusEnd | ReactNodeRight side of the status bar, before the panel toggle. | Optional |
sidebar | ReactNodeOptional column to the left, e.g. the agent's thread. Becomes its own tab on phones. | Optional |
sidebarLabel | string | Optional |
mainLabel | string | Optional |
defaultHeight | number | Optional |
minHeight | number | Optional |
minMainHeight | numberRoom the main area always keeps, in px. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
The bottom dock sits under the thread. Resize panel changes the height. Collapse panel leaves the summary and the status visible. A maximize control takes the height up. Tabs in the preview cover changed files, terminal output and agent steps, and a warning count can show on a tab. The terminal has Clear terminal, and after a clear it says output from the next run will show there. The file list marks files the agent changed. The main area keeps a minimum height so the composer does not disappear.
Choosing a layout
Use the side dock when the extra material is read beside the thread, a preview or a source, and should become a sheet on a narrow window. Use the bottom dock when the extra material is a log or a file list that people expect under the work, and when a one-line summary is enough while it is collapsed.
Several chats open at once are session tabs. A single cited page with the quote highlighted is the source viewer. The dock is the frame those tools can sit in. It does not page through quotes or keep session state.
Does the dock decide what the Files or Preview tab contains?
No. You pass the tabs and the panel for the active one. The preview happens to show a preview and sources on the side, and files, a terminal and steps on the bottom. Another screen can pass different tabs without changing the dock.
Where does the side panel go on a narrow window?
It stops being a column. sheetOpen controls a bottom sheet, with Open and Close panel. The width you stored is for the column, when there is room for it beside the thread.