# zidane-ui/chat/interactions

> Cards for the questions and plans an agent waits on.

Import: `import { … } from 'zidane-ui/chat/interactions'`. Source: [ui/src/chat/interactions/index.ts](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/index.ts).

Use this entry point to show `ask_user` forms and plan reviews. `HostInteractions` lists the interactions a `ChatHost` has pending for a session and sends the answers back. `QuestionForm`, `PlanCard` and the field components are exported when you build your own surface. See [Composer](https://zidane.si/docs/ui-composer.md) for how the cards sit above the prompt box.

```tsx
import type { ChatHost } from 'zidane-ui/chat/headless'
import { ChatProvider } from 'zidane-ui/chat'
import { HostInteractions } from 'zidane-ui/chat/interactions'

export function Questions({ host, id }: { host: ChatHost, id: string }) {
  return (
    <ChatProvider host={host}>
      <HostInteractions sessionId={id} autoFocus />
    </ChatProvider>
  )
}
```

## Components

### `AnsweredQuestions`

Component.

An answered `ask_user` form, read-only: the same intro and question cards
as the live form, each showing what was picked or typed, then the
additional instructions when some were given. Used by the transcript
(the call's details), so an answer reads the way it was given.

```ts
function AnsweredQuestions(props: AnsweredQuestionsProps): Element
```

**Parameters**

- `props` (`AnsweredQuestionsProps`): Component props: the `payload` that was asked, the `answers`, optional `instructions`, a unique `id`, and an optional `Markdown` renderer.

**Returns** `Element`

**Props**

- `answers` (`Readonly<Record<string, AnswerValue>>`): The submitted answers, keyed by question id.
- `className?` (`string`): Extra classes on the root element.
- `id` (`string`): Unique per call, for the fields' ids.
- `instructions?` (`string`): The additional instructions the user gave. Shown only when not blank.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the intro; defaults to the transcript's `Markdown` slot.
- `onOpenSecrets?` (`() => void`): Opens the Secrets panel from an answered secret. Absent: no button.
- `payload` (`QuestionPayload`): The questions that were asked.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/interactions/QuestionForm.tsx:279](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionForm.tsx#L279)

### `HostInteractions`

Component.

Renders the requests a session is waiting on as cards, oldest first, answered through the `ChatHost` in context. Renders nothing while none wait.

```ts
function HostInteractions(props: HostInteractionsProps): Element | null
```

**Parameters**

- `props` (`HostInteractionsProps`): The [`HostInteractionsProps`](https://zidane.si/docs/reference/ui-chat-interactions.md#HostInteractionsProps).

**Returns** `Element | null`

**Props**

- `autoFocus?` (`boolean`, default `false`): Focuses the oldest card as it arrives.
- `className?` (`string`): Extra class names for the list.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws an intro or a plan. Defaults to the transcript's `Markdown` slot.
- `sessionId` (`string`): Id of the session whose pending requests to show.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/interactions/HostInteractions.tsx:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/HostInteractions.tsx#L43)

### `InboxPanel`

Component.

Renders one session's pending requests as inbox cards, the head one open; an empty state while none wait.

```ts
function InboxPanel(props: InboxPanelProps): Element
```

**Parameters**

- `props` (`InboxPanelProps`): The [`InboxPanelProps`](https://zidane.si/docs/reference/ui-chat-interactions.md#InboxPanelProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra class names for the root.
- `focus?` (`boolean`): Hand keyboard focus to the head card once it is there (the panel's focus request).
- `inProgress?` (`ReactNode`): The "In progress" section's body: the plan being applied. Absent or null: no section.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws an intro or a plan. Defaults to the transcript's `Markdown` slot.
- `recent?` (`ReactNode`): The "Recent" section's body: closed plans. Absent or null: no section.
- `sessionId` (`string`): The session whose requests to show.
- `style?` (`CSSProperties`): Inline styles on the root element.
- `onEscape?` (`() => void`): Esc inside the list: give the keyboard back (the composer). Absent: Esc does nothing here.
- `onFocusTaken?` (`() => void`): The head card took `focus`: clear the request.

Source: [ui/src/chat/interactions/InboxPanel.tsx:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/InboxPanel.tsx#L68)

### `InteractionCard`

Component.

Renders one agent request as a card: a header naming its kind and subject, then the form that answers it. A question gets a form, a plan gets an approve, revise, or reject review, and an unknown kind shows its payload.

```ts
function InteractionCard(props: InteractionCardProps): Element
```

**Parameters**

- `props` (`InteractionCardProps`): The [`InteractionCardProps`](https://zidane.si/docs/reference/ui-chat-interactions.md#InteractionCardProps).

**Returns** `Element`

**Props**

- `autoFocus?` (`boolean`): Focus the card's first control.
- `className?` (`string`): Extra classes on the root element.
- `interaction` (`ChatInteraction`): The pending request to show.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws an intro or a plan; defaults to the transcript's `Markdown` slot.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onAnswer` (`(response: InteractionResponse) => Promise<void>`): Called with the user's response. The card waits on the returned promise.
- `onDismiss?` (`() => Promise<void>`): Withdraw the request unanswered (a question's Dismiss).

Source: [ui/src/chat/interactions/InteractionCard.tsx:44](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/InteractionCard.tsx#L44)

### `PlanBody`

Component.

The plan itself: its Markdown, then the numbered steps. Shared by this
card and the transcript (a `present_plan` call's details), so a plan
reads the same wherever it shows.

```ts
function PlanBody(props: PlanBodyProps): Element
```

**Parameters**

- `props` (`PlanBodyProps`): Component props: the `payload` and an optional `Markdown` renderer.

**Returns** `Element`

**Props**

- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the plan. Defaults to the transcript's `Markdown` slot.
- `payload` (`PlanProposal`): The plan to show: its markdown and optional numbered steps.

Source: [ui/src/chat/interactions/PlanCard.tsx:159](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/PlanCard.tsx#L159)

### `PlanCard`

Component.

Renders a `present_plan` request as a card the user approves, revises, or rejects. Revise and reject take an optional note.

```ts
function PlanCard(props: PlanCardProps): Element
```

**Parameters**

- `props` (`PlanCardProps`): The [`PlanCardProps`](https://zidane.si/docs/reference/ui-chat-interactions.md#PlanCardProps).

**Returns** `Element`

**Props**

- `autoFocus?` (`boolean`): Focus Approve (the card just became the one to answer).
- `className?` (`string`): Extra classes on the root element.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the plan; defaults to the transcript's `Markdown` slot.
- `request` (`PlanRequest`): The `present_plan` request: the plan's title, markdown, and steps.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onAnswer` (`(response: PlanResponse) => Promise<void>`): Called with the decision (approve, revise, or reject) and an optional note. The card waits on the returned promise and shows a rejection's message.

Source: [ui/src/chat/interactions/PlanCard.tsx:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/PlanCard.tsx#L43)

### `QuestionField`

Component.

Renders one question of an `ask_user` form as a card: the numbered prompt, its help, and the control its type takes.

```ts
function QuestionField(props: QuestionFieldProps): Element
```

**Parameters**

- `props` (`QuestionFieldProps`): Field props: `index`, `question`, `value`, `onChange`, `requestId`, `labels`, and `readOnly`.

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `index` (`number`): Zero-based position of the question. Shown as a number before the prompt.
- `labels` (`{ addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addToChat: string; agent: string; agentDraftNote: string; agentProfiles: string; archive: string; archived: string; attachFile: string; attachmentEmpty: (name: string) => string; attachmentExportPdf: (name: string) => string; attachmentNotices: string; attachmentReadFailed: (name: string) => string; attachments: string; attachmentTitle: (name: string, detail: string) => string; attachmentTooLarge: (name: string, size: string, limit: string) => string; attachmentUnreadableImage: (name: string) => string; attachmentUnsupported: (name: string) => string; authCancel: string; authCard: string; authCopied: string; authCopyDetails: string; authEnterCode: (code: string) => string; authFailed: (message: string) => string; authFixed: string; authHeadline: (auth: AuthFailure, label: string) => string; authOpeningBrowser: string; authOpenPage: string; authPaste: string; authPasteSend: string; authSettings: string; authSettingsHint: string; authSignedIn: string; authSignedInRetrying: string; authSignInAgain: string; authSwitching: (account: string) => string; authTryAgain: string; authUseAccount: (account: string) => string; authWaiting: string; autoDenied: string; back: string; badgeCopied: string; badgeNoComposer: string; badgeOpenIn: (app: string) => string; badgeOpenInBrowserPane: string; badgePathUnavailable: string; blockRunAgain: string; blockRunAttach: string; blockRunAttachmentName: string; blockRunCopy: string; blockRunFailed: (reason: string) => string; blockRunHere: string; blockRunInTerminal: string; blockRunMenu: string; blockRunNeedsTerminal: string; blockRunning: string; blockRunOutput: string; blockRunRemove: string; blockRunStop: string; blockRunStopped: string; blockRunTimedOut: string; blockRunTruncated: string; cancel: string; chats: string; chipBranch: (name: string) => string; chipChat: (name: string) => string; chipCommand: (name: string) => string; chipCommit: (sha: string) => string; chipFactAliases: string; chipFactBranch: string; chipFactChanges: string; chipFactContext: string; chipFactDate: string; chipFactModel: string; chipFactPrompts: string; chipFactSize: string; chipFactTurns: string; chipFactUpdated: string; chipLoading: string; chipNotAmongChats: string; chipNotFound: (title: string) => string; chipRemoteFile: (path: string, host: string) => string; chipSessionError: string; chipSessionRunning: string; chipSkill: (name: string) => string; chipTokens: (count: string) => string; chipUntitledChat: string; chooseModel: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; commandDetail: string; commandSuggestions: string; completionSuggestions: string; composerBadges: string; composerLabel: string; composerPlaceholder: string; composerPlaceholderQueue: string; composerPlaceholderSteer: string; confirm: string; confirmNo: string; confirmYes: string; contextActiveSkills: string; contextAutoCompact: (pct: number) => string; contextCacheRead: string; contextCacheWrite: string; contextClickToCopy: (hasDescription: boolean) => string; contextCopied: string; contextDeferred: string; contextDetail: string; contextEstimated: string; contextFreshInput: string; contextLastTurn: string; contextNoBreakdown: string; contextOutput: string; contextRunCount: (runs: number) => string; contextSessionCost: string; contextSummary: (used: string, window: string, pct: number) => string; contextSummaryCost: (summary: string, cost: string) => string; contextWindow: string; continue: string; continueHint: string; continueRun: string; copied: string; copy: string; copyCode: string; copyDiagramSource: string; copyImage: string; copyImageBase64: string; copyImageDataUrl: string; current: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; delete: string; diagnosticsCheckedBy: (source: string) => string; diagnosticsChecking: string; diagnosticsNone: string; diagram: (type: string | null) => string; diagramError: (message: string, at: string) => string; diagramErrorAt: (line: number, column: number) => string; dismiss: string; dismissHint: string; dotAttached: string; dotAttention: string; dotCompleted: string; dotError: string; dotIdle: string; dotPending: string; dotRunning: string; earlierHistory: string; earlierLines: (count: number) => string; earlierMessages: (count: number) => string; editorConflict: string; editorConflictDetail: string; editorEmpty: string; editorOverwrite: string; editorReadFailed: (message: string) => string; editorReload: string; effortLevel: (level: string) => string; errorFailed: (region: string) => string; errorStack: string; errorTryAgain: string; estimateDue: string; estimateDueTitle: string; estimateOver: string; estimateOverTitle: string; estimatePausedTitle: (left: string) => string; estimateProblemTitle: (reason: string, message?: string) => string; estimateTitle: (left: string) => string; expandGroup: (label: string) => string; favorites: string; filePath: (path: string) => string; fileReadOnly: (path: string) => string; fileTree: string; fileUnsaved: string; fileUnsavedTitle: (path: string) => string; filterActivities: { '1d': string; '30d': string; '3d': string; '7d': string; all: string }; filterActivity: string; filterAgent: string; filterAllAgents: string; filterAllAgentsOption: string; filterAllProjects: string; filterAllProjectsOption: string; filterAny: string; filterNoAgents: string; filterNoProjects: string; filterOrigin: string; filterOrigins: { all: string; scheduled: string; unscheduled: string }; filterPicked: (count: number) => string; filterProject: string; filterSaveView: string; filterSessions: string; filterSort: string; filterSorts: { alphabetical: string; createdTime: string; recency: string }; filterSpaceDefault: string; filterStatus: string; filterStatuses: { active: string; all: string; archived: string }; filterView: string; filterViews: { agent: string; date: string; host: string; none: string; project: string; state: string }; findClose: string; findCloseHint: string; findInConversation: string; findInConversationClose: string; findInFile: string; findMatchCase: string; findNext: string; findNextHint: string; findNoResults: string; findPrevious: string; findPreviousHint: string; findReferences: string; fitDiagram: string; foldOutcomes: (ok: number, failed: number) => string; foldSteps: (count: number) => string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hostBadgeTitle: (host: string, status: string) => string; hostCollapse: (name: string) => string; hostExpand: (name: string) => string; hostOpenSettings: (host: string) => string; hostPicker: string; hostRunsOn: (name: string) => string; hostRunsOnSection: string; hostStatusError: (status: string, error: string) => string; hostStatuses: { 'auth-refused': string; connected: string; connecting: string; identity: string; local: string; offline: string; reconnecting: string; 'version-mismatch': string }; hostThisMachine: string; imageModelReferences: string; imageModelReferencesHint: string; imageModelsNone: string; imageModelsPill: string; imageModelTransparency: string; imageModelTransparencyHint: string; inboxEmpty: string; inboxInProgress: string; inboxNeedsYou: string; inboxPreviousSession: string; inboxRecent: string; inputCaption: string; interactionAnsweredBy: (who: string) => string; interactionApproved: string; interactionDismissed: string; interactionPlan: string; interactionQuestion: string; interactionRejected: string; interactionRevise: string; interactionsLabel: string; interactionWaitingAnswers: string; interactionWaitingDecision: string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mentionSuggestions: string; modalBack: string; modalFailed: string; modelAccountBlocked: (provider: string) => string; modelChain: string; modelChainNoModel: string; modelChainOrderHint: string; modelFallback: string; modelFallbackHint: string; modelFallbackPosition: (n: number) => string; modelFeatures: string; modelForNextChat: string; modelInUse: string; modelKinds: string; modelLegacy: string; modelLegacyHint: string; modelNotInCatalog: string; modelNotInCatalogHint: string; modelOptions: string; modelOptionsEmpty: string; modelOptionsHint: string; modelPrimary: string; modelPrimaryHint: string; modelReasoning: string; modelReasoningHint: string; modelRemoveFallback: (n: number) => string; modelRemoveFromChain: string; modelRemovePrimary: string; modelsChatTab: string; modelsCustomId: string; modelServing: (picked: string, serving: string) => string; modelServingFallback: string; modelsImageTab: string; modelsInUse: string; modelsJumpHint: (provider: string, digit: number | null) => string; modelsJumpToProvider: string; modelsLegacy: string; modelsLegacyHidden: (count: number) => string; modelsLoadFailed: (error: string) => string; modelsLoading: string; modelsNoMatch: (query: string) => string; modelsNoProviders: string; modelsSelected: (count: number) => string; modelsShowLegacy: string; modelsShowLegacyHint: string; modelsShownOf: (shown: number, total: number) => string; modelsTypeAnId: string; modelUnavailable: string; modelVerdictTitle: (approved: boolean, model: string, confidence: string | null) => string; modelVia: string; modelViaHint: (modelId: string, provider: string) => string; months: readonly string[]; moreActions: string; moreAttachments: (count: number) => string; newSession: string; newSessionIn: (label: string) => string; next: string; noAnswer: string; noMatches: (query: string) => string; noReferences: string; noSessions: string; noSuggestions: string; of: (index: number, count: number) => string; openFiles: string; openGroup: (label: string) => string; openImageFile: (path: string) => string; openInNewTab: string; openNamedSession: (title: string) => string; openSecrets: string; openSession: string; outputCaption: string; paletteBack: string; paletteBackHint: string; paletteChoose: string; paletteEmpty: string; paletteFilter: string; paletteLabel: string; paletteLoading: string; paletteNoMatch: (query: string) => string; paletteOpen: string; paletteRun: string; paletteScopeHint: string; paletteTurnOff: string; paletteTurnOn: string; pickModel: string; pickOneOrMore: string; planApprove: string; planReject: string; planRejectAndStop: string; planRejectNote: string; planRejectPlaceholder: string; planRevise: string; planReviseNote: string; planRevisePlaceholder: string; planSendRevision: string; previewFailed: (name: string) => string; previewTooLarge: (name: string, size: string) => string; previous: string; questionCount: (count: number) => string; queueHint: string; queueMessage: string; reasoningEffort: string; receiptAgent: string; receiptAgentSwitched: string; receiptCost: string; receiptDuration: string; receiptModel: string; receiptModelOthers: (others: number) => string; receiptSpeed: string; receiptTokens: (sent: string, received: string) => string; receiptTurns: (turns: number) => string; reload: string; removeAttachment: (name: string) => string; removeFavorite: string; rename: string; requiredHint: string; requiredMark: string; resetsAt: (time: string) => string; retry: string; retryHint: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; saveSecurely: string; screenBack: (screen: string) => string; screenBackKey: string; scriptCallsDone: (done: number) => string; scriptCallsFailed: (failed: number) => string; scriptCallsOf: (done: number, total: number) => string; scriptCallsRunning: (running: number) => string; scriptLineCalls: (calls: number) => string; scriptLiveOutput: string; scriptLoop: string; scriptLoopRound: (round: number) => string; scriptLoopRounds: (rounds: number) => string; scriptLoopRuns: (runs: number) => string; scriptOptionOutput: string; scriptOptions: string; scriptOptionTimeout: string; scriptOptionTokens: (tokens: number) => string; scriptPercent: (percent: number) => string; scriptProgress: string; scriptWaitLeft: (seconds: number) => string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; secretDeclined: (name: string) => string; secretNote: (ttl: SecretTtl) => string; secretReused: (name: string) => string; secretSaved: (name: string, left: SecretTimeLeft) => string; secretSent: (name: string) => string; secretTtlLabel: string; secretTtlName: (ttl: SecretTtl) => string; secretValueLabel: string; secretValuePlaceholder: string; selectTurnCopied: string; selectTurnCopy: string; selectTurnDetails: string; selectTurnExit: string; selectTurnFork: string; selectTurnForkFailed: string; selectTurnMove: string; selectTurnNothingToCopy: string; selectTurnSelecting: string; sendAnswers: (count: number) => string; sendHint: string; sendMessage: string; sessionActions: string; sessionEventLabel: (title: string, verb: string, needsAttention: boolean) => string; sessions: string; setModelOptions: string; shellCancelled: string; shellExit: (code: number) => string; shellKilled: string; showDiagram: string; showDiagramSource: string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; signInCopyCode: string; signInDone: (account?: string) => string; signInEnterCode: (host: string) => string; signInFailed: string; signInInBrowser: (service: string) => string; signInNotOpened: string; signInOpenPage: string; signInPaste: string; signInStarting: string; signInSubmit: string; skip: string; spawnResumes: (childId: string) => string; spawnTask: string; stateCompleted: string; stateError: string; stateIdle: string; stateRunning: string; steerHint: string; steerMessage: string; stepDone: string; stepFailed: string; stepOf: (index: number, count: number) => string; stepResuming: string; stepRunning: string; steps: string; stepWaiting: string; stopCommand: string; stopHint: string; stopped: string; stoppedByYou: string; stopRun: string; switchAgent: string; switchingAgent: string; switchModel: string; terminal: string; terminalExited: (code: number) => string; terminalLoadFailed: (message: string) => string; thinkingLive: string; thoughtFor: (seconds: number) => string; thoughts: string; thoughtTimes: (count: number) => string; today: string; toolAttachments: string; transcriptLoading: string; turnMenuCopy: string; turnMenuCopySelection: string; turnMenuCopySelectionFailed: string; turnMenuDelete: string; turnMenuEdit: string; turnMenuEditNeedsComposer: string; turnMenuFork: string; turnMenuRewind: string; turnMenuSent: (age: string) => string; turnMenuStopFirst: (label: string) => string; turnsCompacted: string; unarchive: string; unsupportedInteraction: (tool: string) => string; viewAttachment: (name: string) => string; waitingForSlot: (max: number) => string; workerContinues: string; workerModel: string; workerSystemPrompt: string; workerSystemReplaced: string; workerType: string; working: string; wrapLines: string; yesterday: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string }`): The chat labels used for the field's strings.
- `onChange` (`(value: AnswerValue) => void`): Called with the new answer when the user edits the field.
- `onOpenSecrets?` (`() => void`): Opens the Secrets panel from an answered secret. Absent: no button.
- `onSubmit?` (`() => void`): Enter in a secret's password field (the form saves).
- `question` (`Question`): The question to draw. Its `type` picks the control.
- `readOnly?` (`boolean`): The answered form (transcript): the same card, showing what was picked, nothing editable.
- `requestId` (`string`): Id of the request. Builds unique element ids for the field.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `value` (`AnswerValue | undefined`): The current answer, or `undefined` when none is given.

Source: [ui/src/chat/interactions/QuestionField.tsx:58](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionField.tsx#L58)

### `QuestionForm`

Component.

Renders an `ask_user` request as a form: an optional intro, one card per question, and an "Additional instructions" field. Required questions block Send.

```ts
function QuestionForm(props: QuestionFormProps): Element
```

**Parameters**

- `props` (`QuestionFormProps`): The [`QuestionFormProps`](https://zidane.si/docs/reference/ui-chat-interactions.md#QuestionFormProps).

**Returns** `Element`

**Props**

- `autoFocus?` (`boolean`): Focus the first control (the card just became the one to answer).
- `className?` (`string`): Extra classes on the root element.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the intro; defaults to the transcript's `Markdown` slot.
- `request` (`QuestionRequest`): The `ask_user` request: its intro and questions.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onAnswer` (`(response: QuestionResponse) => Promise<void>`): Called with the answers when the user sends. The form waits on the promise and shows a rejection's message under the controls.
- `onDismiss?` (`() => Promise<void>`): Withdraw the question unanswered. Absent: no Dismiss button.

Source: [ui/src/chat/interactions/QuestionForm.tsx:62](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionForm.tsx#L62)

### `SecretInput`

Component.

Renders a password field, a TTL picker and the note on where the value is kept.

```ts
function SecretInput(props: SecretInputProps): Element
```

**Parameters**

- `props` (`SecretInputProps`): The [`SecretInputProps`](https://zidane.si/docs/reference/ui-chat-interactions.md#SecretInputProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `describedBy?` (`string`): Ids of the elements that describe the field (the question's help).
- `id` (`string`): Id of the password field: a `<label htmlFor>` names it.
- `inputRef?` (`Ref<HTMLInputElement>`): Ref to the password field.
- `onChange` (`(value: string, ttl: SecretTtl) => void`): Called on every keystroke with the typed value and the picked TTL. Keep the value out of anything logged or saved.
- `onSubmit?` (`() => void`): Called on Enter in the password field.
- `required?` (`boolean`): Marks the field required for assistive tech.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `ttl` (`SecretTtl`): The TTL picked.

Source: [ui/src/chat/interactions/SecretInput.tsx:41](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/SecretInput.tsx#L41)

## Functions

### `isRequired`

Function.

Same defaults as the TUI: select/confirm required, free text optional. A secret needs its value (Decline is the
way out).

```ts
function isRequired(q: Question): boolean
```

**Parameters**

- `q` (`Question`): The question. `required` wins; otherwise `select`, `confirm` and `secret` are required and free text is optional.

**Returns** `boolean`

Source: [ui/src/chat/interactions/QuestionField.tsx:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionField.tsx#L23)

### `seedDefaults`

Function.

Seed the form from the payload: `default` for free text, `selected`
pre-ticks for multi-select (an opt-out list arrives already ticked).

```ts
function seedDefaults(payload: QuestionPayload): Record<string, AnswerValue>
```

**Parameters**

- `payload` (`QuestionPayload`): The question payload to read defaults from.

**Returns** `Record<string, AnswerValue>`

Source: [ui/src/chat/interactions/QuestionForm.tsx:328](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionForm.tsx#L328)

### `useAllInteractions`

Function.

Every session's pending requests, in arrival order; empty when the host only lists them per session.

```ts
function useAllInteractions(): readonly ChatInteraction[]
```

**Returns** `readonly ChatInteraction[]`

Source: [ui/src/chat/interactions/hooks.ts:45](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/hooks.ts#L45)

### `useInteractionHead`

Function.

The oldest pending request of one session, or `null`. Re-renders only when that request changes, not when more queue
behind it (a sidebar dot reads it per row).

```ts
function useInteractionHead(sessionId: string | null): ChatInteraction | null
```

**Parameters**

- `sessionId` (`string | null`): The session, or `null`.

**Returns** `ChatInteraction | null`

Source: [ui/src/chat/interactions/hooks.ts:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/hooks.ts#L34)

### `usePendingInteractions`

Function.

One session's pending requests, oldest first; empty for no session or a host without interactions.

```ts
function usePendingInteractions(sessionId: string | null): readonly ChatInteraction[]
```

**Parameters**

- `sessionId` (`string | null`): The session, or `null`.

**Returns** `readonly ChatInteraction[]`

Source: [ui/src/chat/interactions/hooks.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/hooks.ts#L19)

## Interfaces

### `AnsweredQuestionsProps`

Interface.

Props for [`AnsweredQuestions`](https://zidane.si/docs/reference/ui-chat-interactions.md#AnsweredQuestions).

```ts
interface AnsweredQuestionsProps
```

**Properties**

- `answers` (`Readonly<Record<string, AnswerValue>>`): The submitted answers, keyed by question id.
- `className?` (`string`): Extra classes on the root element.
- `id` (`string`): Unique per call, for the fields' ids.
- `instructions?` (`string`): The additional instructions the user gave. Shown only when not blank.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the intro; defaults to the transcript's `Markdown` slot.
- `onOpenSecrets?` (`() => void`): Opens the Secrets panel from an answered secret. Absent: no button.
- `payload` (`QuestionPayload`): The questions that were asked.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/interactions/QuestionForm.tsx:252](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionForm.tsx#L252)

### `HostInteractionsProps`

Interface.

Props for [`HostInteractions`](https://zidane.si/docs/reference/ui-chat-interactions.md#HostInteractions).

```ts
interface HostInteractionsProps
```

**Properties**

- `autoFocus?` (`boolean`, default `false`): Focuses the oldest card as it arrives.
- `className?` (`string`): Extra class names for the list.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws an intro or a plan. Defaults to the transcript's `Markdown` slot.
- `sessionId` (`string`): Id of the session whose pending requests to show.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/interactions/HostInteractions.tsx:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/HostInteractions.tsx#L20)

### `InboxPanelProps`

Interface.

Props for [`InboxPanel`](https://zidane.si/docs/reference/ui-chat-interactions.md#InboxPanel).

```ts
interface InboxPanelProps
```

**Properties**

- `className?` (`string`): Extra class names for the root.
- `focus?` (`boolean`): Hand keyboard focus to the head card once it is there (the panel's focus request).
- `inProgress?` (`ReactNode`): The "In progress" section's body: the plan being applied. Absent or null: no section.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws an intro or a plan. Defaults to the transcript's `Markdown` slot.
- `recent?` (`ReactNode`): The "Recent" section's body: closed plans. Absent or null: no section.
- `sessionId` (`string`): The session whose requests to show.
- `style?` (`CSSProperties`): Inline styles on the root element.
- `onEscape?` (`() => void`): Esc inside the list: give the keyboard back (the composer). Absent: Esc does nothing here.
- `onFocusTaken?` (`() => void`): The head card took `focus`: clear the request.

Source: [ui/src/chat/interactions/InboxPanel.tsx:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/InboxPanel.tsx#L36)

### `InteractionCardProps`

Interface.

Props for [`InteractionCard`](https://zidane.si/docs/reference/ui-chat-interactions.md#InteractionCard).

```ts
interface InteractionCardProps
```

**Properties**

- `autoFocus?` (`boolean`): Focus the card's first control.
- `className?` (`string`): Extra classes on the root element.
- `interaction` (`ChatInteraction`): The pending request to show.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws an intro or a plan; defaults to the transcript's `Markdown` slot.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onAnswer` (`(response: InteractionResponse) => Promise<void>`): Called with the user's response. The card waits on the returned promise.
- `onDismiss?` (`() => Promise<void>`): Withdraw the request unanswered (a question's Dismiss).

Source: [ui/src/chat/interactions/InteractionCard.tsx:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/InteractionCard.tsx#L19)

### `PlanBodyProps`

Interface.

Props for [`PlanBody`](https://zidane.si/docs/reference/ui-chat-interactions.md#PlanBody).

```ts
interface PlanBodyProps
```

**Properties**

- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the plan. Defaults to the transcript's `Markdown` slot.
- `payload` (`PlanProposal`): The plan to show: its markdown and optional numbered steps.

Source: [ui/src/chat/interactions/PlanCard.tsx:145](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/PlanCard.tsx#L145)

### `PlanCardProps`

Interface.

Props for [`PlanCard`](https://zidane.si/docs/reference/ui-chat-interactions.md#PlanCard).

```ts
interface PlanCardProps
```

**Properties**

- `autoFocus?` (`boolean`): Focus Approve (the card just became the one to answer).
- `className?` (`string`): Extra classes on the root element.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the plan; defaults to the transcript's `Markdown` slot.
- `request` (`PlanRequest`): The `present_plan` request: the plan's title, markdown, and steps.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onAnswer` (`(response: PlanResponse) => Promise<void>`): Called with the decision (approve, revise, or reject) and an optional note. The card waits on the returned promise and shows a rejection's message.

Source: [ui/src/chat/interactions/PlanCard.tsx:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/PlanCard.tsx#L23)

### `QuestionFieldProps`

Interface.

Props for [`QuestionField`](https://zidane.si/docs/reference/ui-chat-interactions.md#QuestionField).

```ts
interface QuestionFieldProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `index` (`number`): Zero-based position of the question. Shown as a number before the prompt.
- `labels` (`{ addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addToChat: string; agent: string; agentDraftNote: string; agentProfiles: string; archive: string; archived: string; attachFile: string; attachmentEmpty: (name: string) => string; attachmentExportPdf: (name: string) => string; attachmentNotices: string; attachmentReadFailed: (name: string) => string; attachments: string; attachmentTitle: (name: string, detail: string) => string; attachmentTooLarge: (name: string, size: string, limit: string) => string; attachmentUnreadableImage: (name: string) => string; attachmentUnsupported: (name: string) => string; authCancel: string; authCard: string; authCopied: string; authCopyDetails: string; authEnterCode: (code: string) => string; authFailed: (message: string) => string; authFixed: string; authHeadline: (auth: AuthFailure, label: string) => string; authOpeningBrowser: string; authOpenPage: string; authPaste: string; authPasteSend: string; authSettings: string; authSettingsHint: string; authSignedIn: string; authSignedInRetrying: string; authSignInAgain: string; authSwitching: (account: string) => string; authTryAgain: string; authUseAccount: (account: string) => string; authWaiting: string; autoDenied: string; back: string; badgeCopied: string; badgeNoComposer: string; badgeOpenIn: (app: string) => string; badgeOpenInBrowserPane: string; badgePathUnavailable: string; blockRunAgain: string; blockRunAttach: string; blockRunAttachmentName: string; blockRunCopy: string; blockRunFailed: (reason: string) => string; blockRunHere: string; blockRunInTerminal: string; blockRunMenu: string; blockRunNeedsTerminal: string; blockRunning: string; blockRunOutput: string; blockRunRemove: string; blockRunStop: string; blockRunStopped: string; blockRunTimedOut: string; blockRunTruncated: string; cancel: string; chats: string; chipBranch: (name: string) => string; chipChat: (name: string) => string; chipCommand: (name: string) => string; chipCommit: (sha: string) => string; chipFactAliases: string; chipFactBranch: string; chipFactChanges: string; chipFactContext: string; chipFactDate: string; chipFactModel: string; chipFactPrompts: string; chipFactSize: string; chipFactTurns: string; chipFactUpdated: string; chipLoading: string; chipNotAmongChats: string; chipNotFound: (title: string) => string; chipRemoteFile: (path: string, host: string) => string; chipSessionError: string; chipSessionRunning: string; chipSkill: (name: string) => string; chipTokens: (count: string) => string; chipUntitledChat: string; chooseModel: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; commandDetail: string; commandSuggestions: string; completionSuggestions: string; composerBadges: string; composerLabel: string; composerPlaceholder: string; composerPlaceholderQueue: string; composerPlaceholderSteer: string; confirm: string; confirmNo: string; confirmYes: string; contextActiveSkills: string; contextAutoCompact: (pct: number) => string; contextCacheRead: string; contextCacheWrite: string; contextClickToCopy: (hasDescription: boolean) => string; contextCopied: string; contextDeferred: string; contextDetail: string; contextEstimated: string; contextFreshInput: string; contextLastTurn: string; contextNoBreakdown: string; contextOutput: string; contextRunCount: (runs: number) => string; contextSessionCost: string; contextSummary: (used: string, window: string, pct: number) => string; contextSummaryCost: (summary: string, cost: string) => string; contextWindow: string; continue: string; continueHint: string; continueRun: string; copied: string; copy: string; copyCode: string; copyDiagramSource: string; copyImage: string; copyImageBase64: string; copyImageDataUrl: string; current: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; delete: string; diagnosticsCheckedBy: (source: string) => string; diagnosticsChecking: string; diagnosticsNone: string; diagram: (type: string | null) => string; diagramError: (message: string, at: string) => string; diagramErrorAt: (line: number, column: number) => string; dismiss: string; dismissHint: string; dotAttached: string; dotAttention: string; dotCompleted: string; dotError: string; dotIdle: string; dotPending: string; dotRunning: string; earlierHistory: string; earlierLines: (count: number) => string; earlierMessages: (count: number) => string; editorConflict: string; editorConflictDetail: string; editorEmpty: string; editorOverwrite: string; editorReadFailed: (message: string) => string; editorReload: string; effortLevel: (level: string) => string; errorFailed: (region: string) => string; errorStack: string; errorTryAgain: string; estimateDue: string; estimateDueTitle: string; estimateOver: string; estimateOverTitle: string; estimatePausedTitle: (left: string) => string; estimateProblemTitle: (reason: string, message?: string) => string; estimateTitle: (left: string) => string; expandGroup: (label: string) => string; favorites: string; filePath: (path: string) => string; fileReadOnly: (path: string) => string; fileTree: string; fileUnsaved: string; fileUnsavedTitle: (path: string) => string; filterActivities: { '1d': string; '30d': string; '3d': string; '7d': string; all: string }; filterActivity: string; filterAgent: string; filterAllAgents: string; filterAllAgentsOption: string; filterAllProjects: string; filterAllProjectsOption: string; filterAny: string; filterNoAgents: string; filterNoProjects: string; filterOrigin: string; filterOrigins: { all: string; scheduled: string; unscheduled: string }; filterPicked: (count: number) => string; filterProject: string; filterSaveView: string; filterSessions: string; filterSort: string; filterSorts: { alphabetical: string; createdTime: string; recency: string }; filterSpaceDefault: string; filterStatus: string; filterStatuses: { active: string; all: string; archived: string }; filterView: string; filterViews: { agent: string; date: string; host: string; none: string; project: string; state: string }; findClose: string; findCloseHint: string; findInConversation: string; findInConversationClose: string; findInFile: string; findMatchCase: string; findNext: string; findNextHint: string; findNoResults: string; findPrevious: string; findPreviousHint: string; findReferences: string; fitDiagram: string; foldOutcomes: (ok: number, failed: number) => string; foldSteps: (count: number) => string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hostBadgeTitle: (host: string, status: string) => string; hostCollapse: (name: string) => string; hostExpand: (name: string) => string; hostOpenSettings: (host: string) => string; hostPicker: string; hostRunsOn: (name: string) => string; hostRunsOnSection: string; hostStatusError: (status: string, error: string) => string; hostStatuses: { 'auth-refused': string; connected: string; connecting: string; identity: string; local: string; offline: string; reconnecting: string; 'version-mismatch': string }; hostThisMachine: string; imageModelReferences: string; imageModelReferencesHint: string; imageModelsNone: string; imageModelsPill: string; imageModelTransparency: string; imageModelTransparencyHint: string; inboxEmpty: string; inboxInProgress: string; inboxNeedsYou: string; inboxPreviousSession: string; inboxRecent: string; inputCaption: string; interactionAnsweredBy: (who: string) => string; interactionApproved: string; interactionDismissed: string; interactionPlan: string; interactionQuestion: string; interactionRejected: string; interactionRevise: string; interactionsLabel: string; interactionWaitingAnswers: string; interactionWaitingDecision: string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mentionSuggestions: string; modalBack: string; modalFailed: string; modelAccountBlocked: (provider: string) => string; modelChain: string; modelChainNoModel: string; modelChainOrderHint: string; modelFallback: string; modelFallbackHint: string; modelFallbackPosition: (n: number) => string; modelFeatures: string; modelForNextChat: string; modelInUse: string; modelKinds: string; modelLegacy: string; modelLegacyHint: string; modelNotInCatalog: string; modelNotInCatalogHint: string; modelOptions: string; modelOptionsEmpty: string; modelOptionsHint: string; modelPrimary: string; modelPrimaryHint: string; modelReasoning: string; modelReasoningHint: string; modelRemoveFallback: (n: number) => string; modelRemoveFromChain: string; modelRemovePrimary: string; modelsChatTab: string; modelsCustomId: string; modelServing: (picked: string, serving: string) => string; modelServingFallback: string; modelsImageTab: string; modelsInUse: string; modelsJumpHint: (provider: string, digit: number | null) => string; modelsJumpToProvider: string; modelsLegacy: string; modelsLegacyHidden: (count: number) => string; modelsLoadFailed: (error: string) => string; modelsLoading: string; modelsNoMatch: (query: string) => string; modelsNoProviders: string; modelsSelected: (count: number) => string; modelsShowLegacy: string; modelsShowLegacyHint: string; modelsShownOf: (shown: number, total: number) => string; modelsTypeAnId: string; modelUnavailable: string; modelVerdictTitle: (approved: boolean, model: string, confidence: string | null) => string; modelVia: string; modelViaHint: (modelId: string, provider: string) => string; months: readonly string[]; moreActions: string; moreAttachments: (count: number) => string; newSession: string; newSessionIn: (label: string) => string; next: string; noAnswer: string; noMatches: (query: string) => string; noReferences: string; noSessions: string; noSuggestions: string; of: (index: number, count: number) => string; openFiles: string; openGroup: (label: string) => string; openImageFile: (path: string) => string; openInNewTab: string; openNamedSession: (title: string) => string; openSecrets: string; openSession: string; outputCaption: string; paletteBack: string; paletteBackHint: string; paletteChoose: string; paletteEmpty: string; paletteFilter: string; paletteLabel: string; paletteLoading: string; paletteNoMatch: (query: string) => string; paletteOpen: string; paletteRun: string; paletteScopeHint: string; paletteTurnOff: string; paletteTurnOn: string; pickModel: string; pickOneOrMore: string; planApprove: string; planReject: string; planRejectAndStop: string; planRejectNote: string; planRejectPlaceholder: string; planRevise: string; planReviseNote: string; planRevisePlaceholder: string; planSendRevision: string; previewFailed: (name: string) => string; previewTooLarge: (name: string, size: string) => string; previous: string; questionCount: (count: number) => string; queueHint: string; queueMessage: string; reasoningEffort: string; receiptAgent: string; receiptAgentSwitched: string; receiptCost: string; receiptDuration: string; receiptModel: string; receiptModelOthers: (others: number) => string; receiptSpeed: string; receiptTokens: (sent: string, received: string) => string; receiptTurns: (turns: number) => string; reload: string; removeAttachment: (name: string) => string; removeFavorite: string; rename: string; requiredHint: string; requiredMark: string; resetsAt: (time: string) => string; retry: string; retryHint: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; saveSecurely: string; screenBack: (screen: string) => string; screenBackKey: string; scriptCallsDone: (done: number) => string; scriptCallsFailed: (failed: number) => string; scriptCallsOf: (done: number, total: number) => string; scriptCallsRunning: (running: number) => string; scriptLineCalls: (calls: number) => string; scriptLiveOutput: string; scriptLoop: string; scriptLoopRound: (round: number) => string; scriptLoopRounds: (rounds: number) => string; scriptLoopRuns: (runs: number) => string; scriptOptionOutput: string; scriptOptions: string; scriptOptionTimeout: string; scriptOptionTokens: (tokens: number) => string; scriptPercent: (percent: number) => string; scriptProgress: string; scriptWaitLeft: (seconds: number) => string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; secretDeclined: (name: string) => string; secretNote: (ttl: SecretTtl) => string; secretReused: (name: string) => string; secretSaved: (name: string, left: SecretTimeLeft) => string; secretSent: (name: string) => string; secretTtlLabel: string; secretTtlName: (ttl: SecretTtl) => string; secretValueLabel: string; secretValuePlaceholder: string; selectTurnCopied: string; selectTurnCopy: string; selectTurnDetails: string; selectTurnExit: string; selectTurnFork: string; selectTurnForkFailed: string; selectTurnMove: string; selectTurnNothingToCopy: string; selectTurnSelecting: string; sendAnswers: (count: number) => string; sendHint: string; sendMessage: string; sessionActions: string; sessionEventLabel: (title: string, verb: string, needsAttention: boolean) => string; sessions: string; setModelOptions: string; shellCancelled: string; shellExit: (code: number) => string; shellKilled: string; showDiagram: string; showDiagramSource: string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; signInCopyCode: string; signInDone: (account?: string) => string; signInEnterCode: (host: string) => string; signInFailed: string; signInInBrowser: (service: string) => string; signInNotOpened: string; signInOpenPage: string; signInPaste: string; signInStarting: string; signInSubmit: string; skip: string; spawnResumes: (childId: string) => string; spawnTask: string; stateCompleted: string; stateError: string; stateIdle: string; stateRunning: string; steerHint: string; steerMessage: string; stepDone: string; stepFailed: string; stepOf: (index: number, count: number) => string; stepResuming: string; stepRunning: string; steps: string; stepWaiting: string; stopCommand: string; stopHint: string; stopped: string; stoppedByYou: string; stopRun: string; switchAgent: string; switchingAgent: string; switchModel: string; terminal: string; terminalExited: (code: number) => string; terminalLoadFailed: (message: string) => string; thinkingLive: string; thoughtFor: (seconds: number) => string; thoughts: string; thoughtTimes: (count: number) => string; today: string; toolAttachments: string; transcriptLoading: string; turnMenuCopy: string; turnMenuCopySelection: string; turnMenuCopySelectionFailed: string; turnMenuDelete: string; turnMenuEdit: string; turnMenuEditNeedsComposer: string; turnMenuFork: string; turnMenuRewind: string; turnMenuSent: (age: string) => string; turnMenuStopFirst: (label: string) => string; turnsCompacted: string; unarchive: string; unsupportedInteraction: (tool: string) => string; viewAttachment: (name: string) => string; waitingForSlot: (max: number) => string; workerContinues: string; workerModel: string; workerSystemPrompt: string; workerSystemReplaced: string; workerType: string; working: string; wrapLines: string; yesterday: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string }`): The chat labels used for the field's strings.
- `onChange` (`(value: AnswerValue) => void`): Called with the new answer when the user edits the field.
- `onOpenSecrets?` (`() => void`): Opens the Secrets panel from an answered secret. Absent: no button.
- `onSubmit?` (`() => void`): Enter in a secret's password field (the form saves).
- `question` (`Question`): The question to draw. Its `type` picks the control.
- `readOnly?` (`boolean`): The answered form (transcript): the same card, showing what was picked, nothing editable.
- `requestId` (`string`): Id of the request. Builds unique element ids for the field.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `value` (`AnswerValue | undefined`): The current answer, or `undefined` when none is given.

Source: [ui/src/chat/interactions/QuestionField.tsx:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionField.tsx#L28)

### `QuestionFormProps`

Interface.

Props for [`QuestionForm`](https://zidane.si/docs/reference/ui-chat-interactions.md#QuestionForm).

```ts
interface QuestionFormProps
```

**Properties**

- `autoFocus?` (`boolean`): Focus the first control (the card just became the one to answer).
- `className?` (`string`): Extra classes on the root element.
- `Markdown?` (`ComponentType<MarkdownSlotProps>`): Draws the intro; defaults to the transcript's `Markdown` slot.
- `request` (`QuestionRequest`): The `ask_user` request: its intro and questions.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onAnswer` (`(response: QuestionResponse) => Promise<void>`): Called with the answers when the user sends. The form waits on the promise and shows a rejection's message under the controls.
- `onDismiss?` (`() => Promise<void>`): Withdraw the question unanswered. Absent: no Dismiss button.

Source: [ui/src/chat/interactions/QuestionForm.tsx:40](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/QuestionForm.tsx#L40)

### `SecretInputProps`

Interface.

Props for [`SecretInput`](https://zidane.si/docs/reference/ui-chat-interactions.md#SecretInput).

```ts
interface SecretInputProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `describedBy?` (`string`): Ids of the elements that describe the field (the question's help).
- `id` (`string`): Id of the password field: a `<label htmlFor>` names it.
- `inputRef?` (`Ref<HTMLInputElement>`): Ref to the password field.
- `onChange` (`(value: string, ttl: SecretTtl) => void`): Called on every keystroke with the typed value and the picked TTL. Keep the value out of anything logged or saved.
- `onSubmit?` (`() => void`): Called on Enter in the password field.
- `required?` (`boolean`): Marks the field required for assistive tech.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `ttl` (`SecretTtl`): The TTL picked.

Source: [ui/src/chat/interactions/SecretInput.tsx:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/interactions/SecretInput.tsx#L15)
