# Questionnaire Page (`questionnaire-01`) - SignalOS page block

> Questionnaire page: pipeline questions with single-choice answers, free-text custom answers, an additional-context field, and answered-count progress, with empty, confirmed and submitting states.

- **Version:** 0.1.4
- **Kind:** block (group: semantics-details) · **Category:** pages
- **Install:** `npx shadcn@latest add @signalos/questionnaire-01`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/page-header, @signalos/textarea, @signalos/badge, @signalos/checkbox, @signalos/command, @signalos/dialog, @signalos/input, @signalos/label, @signalos/popover, @signalos/progress, @signalos/select, @signalos/skeleton, @signalos/tooltip
- **npm dependencies:** lucide-react@^0.468.0, @xyflow/react@^12.0.0
- **Files installed:** `src/components/blocks/questionnaire-01/Questionnaire.tsx`, `src/components/blocks/questionnaire-01/Questionnaire.types.ts`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
// after: npx shadcn@latest add @signalos/questionnaire-01
// mount the pulled page in a route, e.g. src/app/semantics-details/page.tsx
import { Questionnaire } from "@/components/blocks/questionnaire-01/Questionnaire"

export default function Page() {
  return <Questionnaire />
}
```

## Props

### `QuestionnaireOption`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `value` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |

### `QuestionnaireQuestion`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `question` | `string` | yes | - |  |
| `context` | `string \| null \| undefined` | no | - |  |
| `category` | `string \| null \| undefined` | no | - |  |
| `options` | `QuestionnaireOption[]` | yes | - |  |
| `selected_answer` | `string \| null \| undefined` | no | - |  |
| `custom_answer` | `string \| null \| undefined` | no | - |  |

### `QuestionnaireData`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `questions` | `QuestionnaireQuestion[]` | yes | - |  |

### `QuestionnaireAnswer`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `category` | `string \| undefined` | no | - |  |
| `question` | `string \| undefined` | no | - |  |
| `selected_option` | `string \| undefined` | no | - |  |
| `selected_option_label` | `string \| undefined` | no | - |  |
| `custom_answer` | `string \| undefined` | no | - |  |

### `QuestionnaireFdeInput`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `answers` | `QuestionnaireAnswer[]` | yes | - |  |
| `additional_context` | `string \| undefined` | no | - |  |

### `SubmitQuestionnairePayload`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `"retry" \| "submit"` | yes | - |  |
| `answers` | `QuestionnaireAnswer[] \| undefined` | no | - |  |
| `additional_context` | `string \| undefined` | no | - |  |

### `QuestionnaireViewProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `questions` | `QuestionnaireQuestion[]` | yes | - |  |
| `selectedAnswers` | `Record<string, string>` | yes | - |  |
| `customAnswers` | `Record<string, string>` | yes | - |  |
| `additionalContext` | `string` | yes | - |  |
| `answeredCount` | `number` | yes | - |  |
| `isConfirmed` | `boolean \| undefined` | no | - |  |
| `isSubmitting` | `boolean \| undefined` | no | - |  |
| `isNavigating` | `boolean \| undefined` | no | - |  |
| `onSelectOption` | `(qid: string, value: string) => void` | yes | - |  |
| `onSelectCustom` | `(qid: string) => void` | yes | - |  |
| `onCustomTextChange` | `(qid: string, text: string) => void` | yes | - |  |
| `onAdditionalContextChange` | `(context: string) => void` | yes | - |  |
| `onSubmit` | `(action: "retry" \| "submit") => void` | yes | - |  |
| `headerActions` | `ReactNode` | no | - |  |
| `confirmedBanner` | `ReactNode` | no | - |  |
| `className` | `string \| undefined` | no | - |  |
| `data-testid` | `string \| undefined` | no | - |  |

## Changelog

## 0.1.4

- Replace the copied placeholder description with one that actually describes this block; the registry description is what the agent skill shows as "pick it when".

## 0.1.3

- `Questionnaire`: replace `PageHeaderLeft` used as a title with `PageHeaderTitle` for correct semantic markup.
- `Questionnaire`: add `data-testid="questionnaire-question"` to each question container `div`.
- `Questionnaire`: add hidden `questionnaire-retry-button` alongside the submit button for consistency with other stage blocks.
- `Questionnaire`: wrap submit and retry buttons in a `gap-2` flex row.
- `Questionnaire.types.ts`: allow `null` for `context`, `category`, `selected_answer`, and `custom_answer` fields on `QuestionnaireQuestion`.

## 0.1.2

- Content updates.

# semantics-details-01
## 0.1.1
## 0.4.0

- Register all 54 component files in `registry-item.json` so consumers receive the full component tree on install.

## 0.3.0

- Remove legacy `components/semantics/` folder; all components now live in per-stage directories (`glossary/`, `relationships/`, `cross-source/`, `metrics/`, `signal-rules/`, `equilibrium/`, `content-profile/`).
- Register all migrated component files in `registry-item.json` so consumers receive the full component tree.

## 0.2.0

- Lift navigation out of card sub-components: `ReviewQueueCard`, `SharedStageCard`, and `CompletedStageCard` no longer call `useRouter` — they now accept an `onNavigate: (path: string) => void` prop and call it instead.
- Add `onNavigate` to `ReviewQueueViewProps`; `ReviewQueueView` threads it through `QueueSection` to each card.
- Replace `@/types` imports in card components and `StepProgress` with relative imports from `../../pipeline.types` (removes the forbidden app-level alias from shipped files).
- Remove `StageActionDialog` import from `SharedStageCard` (pointed to `@/components/features/…`, a forbidden app-side path).

## 0.1.0

- Initial block: review queue view with per-source and shared stage sections, tab navigation, and questionnaire view.
