# Run List

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

```tsx
import { RunList } from '@commenda/pathfinder/run-list';

<RunList
  items={runs}
  selectedId={activeRunId}
  onOpen={openRun}
  onMarkRead={markRead}
  actionConfig={{
    onRunNow: runNow,
    onMarkAllRead: markAllRead,
    onSettings: openSettings,
  }}
  paginationConfig={{ hasMore, isLoading, onLoadMore: loadOlder }}
/>;
```


## Usage [#usage]

```tsx
import { RunList } from '@commenda/pathfinder/run-list';

<RunList
  items={runs}
  selectedId={activeRunId}
  onOpen={openConversation}
  onMarkRead={markRunRead}
  nextRun={{ label: 'Tomorrow at 9:00 AM', dateTime: '2026-10-14T09:00:00Z' }}
  actionConfig={{
    onRunNow: runNow,
    onMarkAllRead: markAllRead,
    onSettings: openSettings,
  }}
  paginationConfig={{ hasMore, isLoading, onLoadMore: loadOlder, error }}
/>;
```

The host provides newest-first runs and a localized timestamp label plus a machine-readable `dateTime`. Opening a row calls `onOpen` and requests `onMarkRead` only if it was unread. Update the controlled data after your app accepts that operation. Fetching, scheduling, routing, and unread persistence stay outside the component.

## Status and unread indicators [#status-and-unread-indicators]

Each row has a stable 16px leading slot. Awaiting input is amber, failures red, running uses a blue arc, and an unread completed run has a blue dot. Canceled and skipped runs remain neutral even when unread; their trailing label explains the outcome. Queued and read completed runs use a neutral ring. Status is included in the button's accessible name, so it is not communicated by color alone.

The header menu exposes only supplied actions: Run now, Mark all as read, and Agent settings. Its button is separate from the disclosure trigger. Output counts hide at zero and use compact formatting for large values. Unread counts describe the loaded items, not an assumed server total.

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


```tsx
import { RunList } from '@commenda/pathfinder/run-list';

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


```tsx
import { RunList } from '@commenda/pathfinder/run-list';

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


```tsx
import { RunList } from '@commenda/pathfinder/run-list';

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


A collapsed section shows the loaded unread count. Initial loading uses skeleton rows; refreshing retains the existing history. Supply `nextRun` only when there is a schedule. Pagination preserves existing items, disables repeated requests while loading, and displays `error` next to the retry control.

## Responsive behavior [#responsive-behavior]

Long dates, large counts, empty lists, row removal, and new-run insertion use the same controls as Output List. A mobile menu stays available without hover. The host should guard overlapping requests and retain IDs across page loads.

## API reference [#api-reference]

| Prop | Type | Requirement | Behavior |
| --- | --- | --- | --- |
| `items` | `readonly RunItem[]` | required | Newest-first run history |
| `onOpen` | `((id: string) => void)` | required | Navigate to the run conversation |
| `onMarkRead` | `((id: string) => void)` | optional | Request unread persistence |
| `selectedId` | `string \| null` | optional | Controlled active run |
| `onSelectionChange` | `((id: string) => void)` | optional | Notify selection intent |
| `nextRun` | `{ label: string; dateTime?: string; }` | optional | Optional scheduled run |
| `actionConfig` | `{ onRunNow?: () => void; onMarkAllRead?: () => void; onSettings?: () => void; }` | optional | Optional header actions |
| `paginationConfig` | `{ hasMore: boolean; isLoading: boolean; onLoadMore: () => void; error?: string; }` | optional | Older history and errors |
| `disclosureConfig` | `OutputDisclosureConfig` | optional | App-persisted or local disclosure |
| `loadingConfig` | `{ isLoading: boolean; label?: string; }` | optional | Initial skeletons / busy state |
| `title` | `string` | optional | Copy and host placement |
| `emptyLabel` | `string` | optional | Copy and host placement |
| `className` | `string` | optional | Copy and host placement |

### nextRun fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `label` | `string` | Yes |  |
| `dateTime` | `string` | No |  |

### actionConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `onRunNow` | `(() => void)` | No |  |
| `onMarkAllRead` | `(() => void)` | No |  |
| `onSettings` | `(() => void)` | No |  |

### paginationConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `hasMore` | `boolean` | Yes |  |
| `isLoading` | `boolean` | Yes |  |
| `onLoadMore` | `() => void` | Yes |  |
| `error` | `string` | 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 |  |

A `RunItem` has `id`, `timestamp: { dateTime, label }`, `status`, optional `outputCount`, `unread`, and `disabled`. Status accepts `queued`, `running`, `awaiting`, `completed`, `failed`, `canceled`, or `skipped`. Disabled rows cannot open. Pagination is explicit; this small rail does not virtualize an unbounded run history.

## Design rules and compatibility [#design-rules-and-compatibility]

- **RUN-01:** Match Output List's compact card and 32px row geometry. The status indicator leads; the date is the primary label.
- **RUN-02:** Canceled and skipped runs are neutral, never failures. Awaiting, failed, and running take precedence over unread; reduced motion stops the running animation.
- **RUN-03:** Opening an unread run requests marking it read. Keep all mutations and routing in host callbacks; selected and unread state remain controlled.
- **RUN-04:** Keep header actions independent from disclosure, retain existing rows during pagination, and preserve keyboard focus during removal.

The existing enterprise `AgentRunsRail` can map its IDs, formatted timestamps, selected conversation, paging, and mutation callbacks into this API. Its current canceled-as-failed mapping must change intentionally to the neutral Figma behavior. No consumer migration is included here. Compose [Output List](/docs/components/output-list) beside it for the responsive panel and complete simulated workflow.
