Guide
Differences from gpui-component
This library is built on gpui-component. Here is what is new, what extends it, and what is upstream's own work inside something new.
gpui-ai is built on gpui-component, and is not a replacement for it. If you need a button, an input, a dialog or a dock, that is the library to reach for — this one does not wrap them and does not re-export them. What it adds is the layer above: the surfaces an application grows when a model is doing the work, where the data arrives while it is being drawn and a person has to be able to follow, check and stop it.
The line between the two moves, and this page moves with it: gpui-component has since grown chat parts of its own — a message scroller, an attachment surface, bubbles and markers — and where they meet something here, the row below says so rather than leaving you to find out.
Every component below says which of three things it is. The words are the library’s own, exported from the same place its API documentation comes from.
- 21New. Built from primitives. Upstream has no component for the thing at all, or has one whose look cannot be brought into line with this library’s.
- 3Extends. Upstream’s component does the work; this adds what an agent surface needs and hands the rest back.
- 13Composes. An upstream component is mounted inside a surface upstream has no equivalent for — you could not reach it by configuring anything it ships.
There is no fourth kind. Nothing in the catalogue is an upstream component under a new name: the library re-exports none of them, so every page you can open is one of the three above. Button, icon, spinner and text rendering count as primitives here — nearly everything uses them, and counting them would put every component in one bucket and tell you nothing.
Every component
| Component | Kind, and what it stands on | What it adds, and why it is here |
|---|---|---|
| Progress | ||
| LoadingState | Newnot built on one | An animated pixel grid with elapsed time, for waits long enough that a spinner stops meaning anything. |
| StatusBadge | Newnot built on one | One status vocabulary - pending, running, completed, failed - mapped onto the theme's semantic colours once and shared by chips, task rows, tool calls and plan steps. Upstream's badge is a pill with no lifecycle in it. |
| Thinking | Newnot built on one | A reasoning trace that opens itself while it runs, follows the newest steps, holds the reader's place when they scroll back, and collapses to a single line when it settles. |
| Orbs | Newnot built on one | Ambient motion for the moments when a model is alive but has nothing to show yet: one dot lattice, several choreographed personalities. |
| ContextMeter | ComposesProgressCircle, HoverCard | How much of the model's context window a conversation has spent, as a ring, a bar or plain text, with the tone changing as it fills and the numbers exposed semantically so the level never depends on colour alone. |
| Agent work | ||
| ToolChip | Newnot built on one | The compact form of the same thing, for a transcript that should not become a list of cards. |
| ToolCall | Newnot built on one | One invocation: name, summary, status, and on expansion the input sent, the output returned or the reason it failed, with Allow and Deny where a person has to decide. Groups fold a burst of them. |
| TaskRow | Newnot built on one | Live status for long-running agent work. |
| SearchResults | Newnot built on one | Web-search tool output: the query, its results, and the sources behind them. |
| TodoList | Newnot built on one | The plan an agent is working through, with completion arriving item by item. |
| ImageGeneration | Newnot built on one | A picture revealed as it is produced rather than swapped in when it is done. |
| Readable output | ||
| StreamingText | ComposesTextView, HoverCard, Link | Markdown that arrives a token at a time, with citations that resolve on hover and follow-up suggestions underneath. Upstream renders markdown it already has. |
| CodeBlock | Composeshighlighter, Clipboard | Upstream's highlighting with a streaming reveal, so a block can be syntax-coloured while the model is still writing it, and copied while it is. |
| CodeDiff | Composeshighlighter, Clipboard | The same, as a reviewable patch: accept and reject per hunk, with the decision handed back to the application. |
| SelectionActions | ComposesTextViewState, Positioner | Actions anchored to a selection inside rendered Markdown, which needs the text view's own selection state rather than a copy of it. |
| Composites | ||
| Chat | ComposesTextarea, list | A virtualized, controlled transcript: unread reconciliation, jump to latest, and an anchor that survives messages arriving off screen. Upstream now has a MessageScroller that follows the tail and holds the anchor too; what it leaves to the application is the meaning of unread, and what this adds above it is the transcript itself - streaming answers, tool calls, and the prompt bar under them. |
| Suggestions | Newnot built on one | The prompts an assistant offers before it has been asked anything. |
| AttachmentStrip | Newnot built on one | Files on their way into a prompt, with upload progress and failure shown per item. Upstream ships an Attachment of its own now, and is explicit that it is a composition primitive: it lays out a preview, a title and actions, and leaves upload state, retry and selection to the application. This owns that lifecycle, which is the part an agent surface cannot avoid. |
| ArtifactPanel | Composestab::TabBar | A generated document beside the conversation, with preview and source, a version switcher, and streamed content so the panel renders while the agent is still writing. |
| FineTuneCard | ComposesColorPicker, Slider, Input | Upstream's own controls arranged as one controlled inspector that reports every change rather than owning it. |
| PromptBar | ComposesTextarea, Positioner | Native text editing with the apparatus around it that makes a prompt: attachments, a context meter, a slash-command popup and a queue. |
| VoiceControls | Newnot built on one | Idle, listening, transcribing, speaking: a lifecycle no upstream control models. |
| MessageQueue | Newnot built on one | Messages typed while the model was busy, and the means to clear them. |
| Navigation | ||
| CommandSearch | Extendscommand::CommandState | Stable-ID items over the native palette, so a result keeps its identity as the ranking moves under it and the selection does not jump to whatever now sits at that index. |
| SidebarNav | Extendssidebar::SidebarMenuItem | Flattens the tree into one virtualized list, so a section holding ten thousand items costs what the viewport shows rather than what the section holds. Adds a retained filter input, roving focus with tree semantics, and a rail that glides between its widths. |
| ThreadList | ComposesInput, Popover, PopupMenu | Conversations grouped into sections, with search, an archive toggle and a per-row overflow menu. Every intent goes back to the application rather than being acted on here. |
| Data tables | ||
| RecordsTable | Extendstable::DataTable | Adds controlled snapshots with stable row IDs, so a row keeps its identity when the data is replaced; progressive states drawn inside the grid; columns that divide the table's width; and a footer. Upstream's grid draws data that has arrived, and an agent's grid has to draw while it is still arriving. |
| DiffTable | ComposesRecordsTable | Before and after values for one proposal, with accept and reject per row. Reviewing a change an agent wants to make is a different surface from browsing data, even though both are grids. |
| FilterTable | ComposesRecordsTable | Filter chips over a grid whose rows animate to their new places rather than cutting, so a reader can see what the filter did to the set they were looking at. |
| ComparisonTable | Newnot built on one | A matrix rather than a data grid: rows are features, columns are the things compared, and every column header carries its own control. Bounded and virtualized, with columns that divide the width and titles that wrap. |
| Decisions | ||
| ApprovalCard | Newnot built on one | One decision about something already proposed, with the consequence stated and the tone matched to how far it reaches. |
| PlanCard | Newnot built on one | The steps an agent intends, each carrying the shared status vocabulary as it runs. |
| RecommendationCard | Newnot built on one | A suggested next step with its reasoning, which a reader accepts or dismisses. |
| Evidence | ||
| ContextCard | Newnot built on one | The document, file or record an answer drew on, shown beside the answer. |
| InsightCard | Composeschart::LineChart | Metrics and a time series in a paged card, so an analytical answer arrives as evidence rather than as a paragraph about numbers. |
| Human in the loop | ||
| ChoiceGroup | Newnot built on one | One choice from a set, and one switch between two states. Upstream's radio and checkbox are styled on their outer frame only - the box, its radius, its fill and its size are fixed inside render - so a wrapped one arrives with a look no styling can bring into line with the controls beside it. |
| QuestionFlow | Newnot built on one | The short sequence an agent asks before it acts: one question at a time, the place in the sequence stated, and a way past a question that does not apply. |
One extension that is not a component
ButtonLabelExt is the one place the library extends an upstream primitive in public API. Upstream’s label squeezes its glyphs into a one-em box; this composes the button’s child slot instead, so descenders and accents keep the theme’s leading. Everything else about the button — sizes, colours, focus, activation, disabled states — stays upstream’s.
Which library you want
If you are building an application interface — settings, forms, panels, menus — gpui-component is the whole answer and this library has nothing to add to it. If your interface has a model in it, the difference is not decoration: a grid that has to draw while its rows are still arriving, a transcript that keeps its place as messages land off screen, a tool call a person can allow or deny, a reasoning trace that folds itself away when it settles. Those are the 37 surfaces here, and each one names above what it is standing on.