# Composer context

Package: @commenda/pathfinder@0.1.0
Page: /docs/components/composer-context
Figma: https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=582-1565

```tsx
import { ComposerContext } from '@commenda/pathfinder/composer-context';

<ComposerContext items={contextItems} onRemove={removeContext}>
  {editor}
</ComposerContext>;
```


## Usage [#usage]

```tsx
import { ComposerContext } from '@commenda/pathfinder/composer-context';

<ComposerContext
  items={[
    { id: 'page', label: 'Legal entities', role: 'current' },
    {
      id: 'workflow',
      label: 'Incorporate in the UK',
      role: 'carried',
      removable: true,
    },
  ]}
  onRemove={removeContext}
>
  {editor}
</ComposerContext>;
```

The child is your editor surface. This phase demonstrates the existing TextArea; the AI Composer will be implemented in Phase 3. The wrapper never invents page context, adds it to prompts, or owns the request payload.

## Connector invitation [#connector-invitation]


```tsx
<ComposerContext
  position="bottom"
  connectorConfig={{
    label: 'Connect your tools to Commenda',
    onConnect: openConnectors,
    onDismiss: dismissSuggestion,
  }}
>
  {editor}
</ComposerContext>;
```


Use `position="bottom"` with `connectorConfig`. Its main action opens the application's connector flow; dismiss is independent. Supply existing Pathfinder logos through `logos`. After dismissal, set `connectorConfig={null}`. This removes the invitation and its colored footer while preserving the mounted editor and its draft.

## API reference [#api-reference]

| Prop | Type | Requirement | Behavior |
| --- | --- | --- | --- |
| `children` | `ReactNode` | required | Required editor surface |
| `position` | `"top" \| "bottom"` | conditional | Top default; determines the configuration branch |
| `items` | `readonly ComposerContextItem[]` | conditional | Top only: stable `id`, `label`, `role: current \| carried`, optional `removable` |
| `onRemove` | `((id: string) => void)` | optional | Top only; shown only on explicitly removable items |
| `connectorConfig` | `{ label: string; logos?: readonly ReactNode[]; onConnect: () => void; onDismiss?: () => void; } \| null` | conditional | Required for bottom position |
| `className` | `string` | optional | Outer wrapper |

### connectorConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `label` | `string` | Yes |  |
| `logos` | `readonly ReactNode[]` | No |  |
| `onConnect` | `() => void` | Yes |  |
| `onDismiss` | `(() => void)` | No |  |

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

- **CONTEXT-01:** Figma 582:1565 and 588:27564. Pearl-200 wrapper, top pills inset 12px and separated from the editor by 6px. Current context is white with pearl-1000 text; carried context uses pearl-100 and pearl-800. Pills use Label/12 Strong, radius 6px and a 0.5px border.
- **CONTEXT-02:** Only show context actually supplied by the host. Removal emits the stable ID; the application changes both displayed context and request data.
- **CONTEXT-03:** Bottom connector invitation uses stacked logos and a separate dismiss control. Native buttons preserve Enter/Space activation and visible focus.

## Migration notes [#migration-notes]

Map ChatPanelPill `label` and `onDismiss` to an item and `onRemove(id)`. Keep the existing decision about whether the assistant receives page content in the application. Current/carried presentation is explicit and does not replace stored conversation state.
