# `multi_select_choice`

## Use when / do not use when

Use when zero or more options can be selected before an explicit Continue action. Do not use for single-selection or implicit selection-to-advance behavior.

## Exact metadata contract

<!-- funnelsgrove:generated:start contract-v3/step/multi_select_choice -->
### Generated contract facts — do not edit

- Step contract version: `3`
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
- Type: `multi_select_choice`
- Family: `choice`
- Description: Multiple options are selected before explicit completion.
- Action owner: `either`
- Analytics role: _none_
- Terminal: `false`
- Required kind: _none_
- Allowed kinds: _None_
- Allowed semantic events: _None_
- Forbidden capabilities: `email-capture`, `checkout`, `subscription-management`, `subscription-handoff`, `hardcoded-navigation`, `provider-direct-analytics`, `browser-registration-completed`

#### Choice contract

- Cardinality: `many`
- Presentation: `standard`
- Completion: `explicit`
- Allow empty config: `true`

#### Automatic lifecycle events

`first_step_clicked`, `first_step_viewed`, `funnel_started`, `step_completed`, `step_exited`, `step_started`

#### Approved capability owners

- `choice-write` must be owned by `useStepChoices`.

#### Reserved identities

_No reserved identity for this type._

#### Golden fixture source

```ts
import type { FunnelManifestStep, FunnelStepMeta } from '@funnelsgrove/runtime';

const choice = { answerKey: 'priorities', allowEmpty: true } as const;

const manifestStep = {
  id: 'priorities',
  name: 'priorities',
  path: '/priorities',
  filePath: 'src/steps/step-priorities.tsx',
  componentKey: 'stepPriorities',
  type: 'multi_select_choice',
  choice,
  title: 'Choose your priorities',
} as const satisfies FunnelManifestStep;

const componentMeta = {
  id: 'priorities',
  name: 'priorities',
  type: 'multi_select_choice',
  choice,
  figmaNodeId: 'golden:multi-select-choice',
  title: 'Choose your priorities',
  description: 'Select any priorities that apply.',
} as const satisfies FunnelStepMeta;

export const goldenFixture = {
  stepType: 'multi_select_choice',
  manifestStep,
  componentMeta,
  options: [
    { id: 'sleep', label: 'Better sleep' },
    { id: 'focus', label: 'More focus' },
  ],
  persistedAnswer: ['sleep', 'focus'],
  emptyAnswer: [],
  helper: 'useStepChoices',
} as const;
```
<!-- funnelsgrove:generated:end contract-v3/step/multi_select_choice -->

## Interaction and persisted answer shape

Declare `choice.answerKey` and the intended `allowEmpty` value. Persist an array of stable option IDs; an allowed empty selection is `[]`.

## Automatic lifecycle events

`useStepChoices` coordinates array persistence and explicit completion. Preview suppresses provider delivery.

## Required semantic conversions

None.

## Approved shared helpers

Use `useStepChoices` for toggles, saving, completion, and routing.

## MUST rules

- Preserve stable IDs and exact array shape.
- Make Continue state match `allowEmpty`.

## NEVER rules

- Never store comma-separated text, labels, or option objects.
- Never auto-advance on the first selection.

## Golden template or fixture

See the [embedded canonical fixture](#golden-fixture-source) generated from `multi_select_choice.fixture.ts`.

## Validation command

Run `fgrove validate`.

## Manual QA and completion criteria

Test select, deselect, reload, and empty-state behavior; confirm one ID array persists and explicit Continue completes once.
