# Parts and the default composition

> Why the panel is made of parts, how containers fall back to their defaults, where parts stop and slots begin, and why the default panel looks the way it does.

The panel comes ready-made: one line renders a header, a conversation and a composer that work with whatever the provider has. It is also made of parts, and the host can move, swap or leave out any of them. This page is about how those two fit.

## Three levels of change

Most apps never go past the first level, and each level costs only what it changes.

- **Use it.** `<AssistedPanel mode="floating" />` and its props: where it sits, what it is called, which threads and models it offers.
- **Rearrange it.** Compose the parts by hand. Move the model picker to the header, drop the attachment button, put a context bar in a footer.
- **Replace a part.** Write your own component against `useAssisted`, `useAui`, `useAuiState` and the primitives, and drop it where the part went.

The panel's source is not a level. There is nothing to copy into your app and keep in step with a release: a part you have not replaced updates with the package.

## Containers fall back to their defaults

A container part with no children renders its default. With children, it renders exactly those and nothing else. So `<AssistedPanel.Header />` is the whole default header, while a `Header` with two children is those two.

This keeps a change local. To trim the composer, you write the composer's children and leave `<AssistedPanel.Header />` and `<AssistedPanel.Conversation />` bare. You never restate a default to keep it.

The one-liner is the same rule one level up: `AssistedPanel` with a `mode` is a root with no children.

## Any part anywhere

Parts read the panel's state from the root above them, not from their parent. A `ModelSelector` works in the header as well as in the composer, and a `ContextDisplay` in a footer as well as in the header. The groups on the Components pages say where a part sits by default, not where it must sit.

The root holds what several parts share: whether the panel is open, the picked model, the thread drawer, the conversation search, the settings. That is why a toggle and the thing it toggles may sit in different containers: `SettingsToggle` in the header swaps `Conversation` for `SettingsPanel` below it.

`Trigger` goes one step further. It reads only the provider's open state, so it sits anywhere under `AssistedProvider`, in the host's own toolbar.

## Your buttons, our behavior

A button part takes `asChild`. With it, the part renders your element and hands it the click, the label and the pressed state. The host's design system keeps its buttons, and the part keeps what the button does.

Only the button a part shows by default is replaced. `Send` with `asChild` replaces the send button, while the stop button that takes its place during a reply stays the package's. A part's behavior is more than one element, and the host replaces only the element it sees.

## Where parts stop and slots begin

Parts end where a single message begins. Inside `Messages`, the panel renders each message, each tool call, each day line, and the host changes them through `components` slots: `AssistantMessage`, `UserMessage`, `DaySeparator`, `ToolFallback` and the groups.

A message is not a place to arrange. It is a sequence of parts the model produced, text, reasoning, tool calls, rendered in order. A slot replaces how one kind of thing renders, which is the change a host wants there. Tool calls have their own seam on top: `cards` on `AssistedProvider` replaces the card of one tool everywhere.

## Why the default looks the way it does

Several default panels were tried in the example shop. The chosen one is quiet:

- **One header row.** The icon, the title and the page line, the thread menu, a new-thread button, a search icon, the devtools when given, the window controls and Close.
- **The model picker in the composer.** It sits beside Send, where the choice applies, and only when the host passes `models`.
- **Threads in a menu.** `threads` alone opens a searchable menu with each thread's preview. A select row and a drawer are the other styles.
- **Search behind an icon.** The conversation search opens from the header and stays out of the way until then.
- **Cards inline.** A card stands in the conversation where the call happened, never folded into a group of tool calls.
- **Settings and usage opt-in.** The settings panel, the context display, the breakdown and the quota banner need data the host may not have, so the host places them.

Underneath is one rule: the default renders only what is real with the provider's data. No model picker without models, no thread menu unless the host says its runtime has a thread list, no devtools button without devtools, no context ring without usage. A part with nothing to show renders nothing, so a bare default never shows a control that does nothing.
