# Output List

Package: @commenda/pathfinder@0.1.0
Page: /docs/components/output-list
Figma: https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=670-38136

```tsx
import { OutputList } from '@commenda/pathfinder/output-list';

<OutputList
  items={outputs}
  selectedId={activeArtifactId}
  onSelectionChange={setActiveArtifactId}
  onOpen={openArtifact}
  actionConfig={{
    onDownload: downloadArtifact,
    onSaveToDocuments: saveArtifact,
  }}
/>;
```


## Usage [#usage]

```tsx
import { OutputList } from '@commenda/pathfinder/output-list';

<OutputList
  items={outputs}
  selectedId={activeArtifactId}
  onSelectionChange={setActiveArtifactId}
  onOpen={openArtifact}
  actionConfig={{
    onDownload: downloadArtifact,
    onSaveToDocuments: saveArtifact,
  }}
  disclosureConfig={{ open: outputsOpen, onOpenChange: setOutputsOpen }}
/>;
```

Pass stable IDs and newest-first items. Opening, downloading, saving, permissions, and persistence belong to the application. The menu offers download/save only when callbacks are supplied; set an item's `actions.download` or `actions.saveToDocuments` to `false` to omit that action for a particular artifact. Menu actions never activate the row.

## Empty, loading, and collapsed [#empty-loading-and-collapsed]


```tsx
import { OutputList } from '@commenda/pathfinder/output-list';

<OutputList items={[]} onOpen={onOpen} />;
```


```tsx
import { OutputList } from '@commenda/pathfinder/output-list';

<OutputList items={[]} loadingConfig={{ isLoading: true }} onOpen={onOpen} />;
```


```tsx
import { OutputList } from '@commenda/pathfinder/output-list';

<OutputList
  items={items}
  disclosureConfig={{ defaultOpen: false }}
  onOpen={onOpen}
/>;
```


Initial loading shows four skeleton lines. Refreshing a populated list keeps its rows visible. A collapsed section shows the loaded artifact count. Use `disclosureConfig.defaultOpen` for local state, or `open` with `onOpenChange` to persist the preference in your app.

## Responsive output panel [#responsive-output-panel]


```tsx
import { Button } from '@commenda/pathfinder/button';
import { OutputList } from '@commenda/pathfinder/output-list';
import { RunList } from '@commenda/pathfinder/run-list';
import { Sheet } from '@commenda/pathfinder/sheet';

<Sheet
  title="Outputs and runs"
  side="bottom"
  open={open}
  onOpenChange={setOpen}
  trigger={<Button>Show outputs</Button>}
>
  <RunList items={runs} onOpen={openRun} />
  <OutputList items={outputs} onOpen={openArtifact} />
</Sheet>;
```


The example composes Output List and Run List in a 292px column. At viewport widths of 1280px and above it starts visible; from 1024px to 1279px it starts hidden with a header toggle. Below 1024px, the toggle opens a modal bottom Sheet. These layout and preference choices remain in the host, so a compact card is also usable outside chat.

## Complete workflow [#complete-workflow]


```tsx
import { Conversation } from '@commenda/pathfinder/conversation';
import { Message } from '@commenda/pathfinder/message';
import { Composer } from '@commenda/pathfinder/composer';

<Conversation
  messages={messages}
  getMessageKey={(message) => message.id}
  renderMessage={(message) => (
    <Message
      from={message.role}
      parts={message.parts}
      getPartKey={(part) => part.id}
      renderPart={renderPart}
    />
  )}
  footer={<Composer value={draft} onValueChange={setDraft} onSubmit={submit} />}
/>;
```


Choose a suggested prompt, add the simulated ledger attachment, send, answer the entity question, and open the generated workpaper. This example composes Composer, Attachment, Conversation, Message, Reasoning, Tool Call, Question Card, Response Recap, and the output panel. Timers simulate upload and processing; there is no backend, real file upload/download, artifact viewer, or editor. Stop cancels the pending simulated response; a temporarily dismissed question can be reopened.

## Overflow and interaction [#overflow-and-interaction]

Titles and kind labels truncate without moving the icon or menu. The full title remains in the accessible name and native title tooltip. Touch devices keep the menu button visible; hover devices reveal it on hover or keyboard focus. Removing a focused row moves focus to the next available row or section trigger.

## API reference [#api-reference]

| Prop | Type | Requirement | Behavior |
| --- | --- | --- | --- |
| `items` | `readonly OutputItem[]` | required | Stable IDs, newest-first order |
| `onOpen` | `((id: string) => void)` | required | Open the app's artifact preview |
| `selectedId` | `string \| null` | optional | Controlled active artifact |
| `onSelectionChange` | `((id: string) => void)` | optional | Selection request; does not persist internally |
| `actionConfig` | `{ onDownload?: (id: string) => void; onSaveToDocuments?: (id: string) => void; }` | optional | Callbacks receive the artifact ID |
| `disclosureConfig` | `OutputDisclosureConfig` | optional | Controlled or local disclosure |
| `loadingConfig` | `{ isLoading: boolean; label?: string; }` | optional | Initial skeletons / busy state |
| `title` | `string` | optional | Defaults to Outputs |
| `emptyLabel` | `string` | optional | Empty-state explanation |
| `className` | `string` | optional | Host width and placement |

### actionConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `onDownload` | `((id: string) => void)` | No |  |
| `onSaveToDocuments` | `((id: string) => void)` | No |  |

### disclosureConfig fields

Choose one shape; excluded fields cannot be combined.

#### Option 1

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `open` | `boolean` | Yes |  |
| `onOpenChange` | `(open: boolean) => void` | Yes |  |

Do not supply: `defaultOpen`.

#### Option 2

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `defaultOpen` | `boolean` | No |  |
| `onOpenChange` | `((open: boolean) => void)` | No |  |

Do not supply: `open`.

### loadingConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `isLoading` | `boolean` | Yes |  |
| `label` | `string` | No |  |

`OutputItem` includes `id`, `title`, optional `kindLabel`, `disabled`, and `actions`. `kind` is `document`, `plan`, `workpaper`, `pdf`, `csv`, `file`, or `record`. A file can specify `fileType`; a record requires an `icon` such as its country flag. Other kinds can override their icon too. Prefer user-facing artifact names and localized kind labels.

## Design rules [#design-rules]

- **OUTPUT-01:** Use 32px rows, a 40px header, 12px card radius, 6px body padding, and 2px row gaps. Do not add a shadow or bold the selected title.
- **OUTPUT-02:** Show artifact titles and kinds, never internal tool names. The host supplies newest-first order without date headers.
- **OUTPUT-03:** Keep row opening and menu actions independent. Do not place buttons inside another button. The app owns storage, routing, permissions, and disclosure persistence.
- **OUTPUT-04:** New rows fade in and displaced rows slide for the base duration; keyboard-focused lists and reduced-motion users get immediate updates. Retain stable keys and restore focus after removal.

Metadata uses Soft Pearl 800 for readable contrast at 12px, a deliberate contrast adjustment from Figma's lighter 700. The header disclosure uses the existing Base UI measured-height pattern; only infrequent disclosure changes animate height, while insertion animates opacity and transforms.
