# `single_step_choice_emoji`

## Use when / do not use when

Use when exactly one emoji-led option completes on selection. Do not use when emoji is merely decorative on a standard list or when multiple answers are allowed.

## Exact metadata contract

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

- Step contract version: `3`
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
- Type: `single_step_choice_emoji`
- Family: `choice`
- Description: Exactly one emoji-led option is selected.
- Action owner: `step`
- 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: `one`
- Presentation: `emoji`
- Completion: `selection`
- Allow empty config: `false`

#### 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: 'goalFeeling' } as const;

const manifestStep = {
  id: 'goal-feeling',
  name: 'goal-feeling',
  path: '/goal-feeling',
  filePath: 'src/steps/step-goal-feeling.tsx',
  componentKey: 'stepGoalFeeling',
  type: 'single_step_choice_emoji',
  choice,
  title: 'How do you want to feel?',
} as const satisfies FunnelManifestStep;

const componentMeta = {
  id: 'goal-feeling',
  name: 'goal-feeling',
  type: 'single_step_choice_emoji',
  choice,
  figmaNodeId: 'golden:single-step-choice-emoji',
  title: 'How do you want to feel?',
  description: 'Select exactly one emoji-led feeling.',
} as const satisfies FunnelStepMeta;

export const goldenFixture = {
  stepType: 'single_step_choice_emoji',
  manifestStep,
  componentMeta,
  options: [
    { id: 'focused', label: 'Focused', emoji: '🎯' },
    { id: 'calm', label: 'Calm', emoji: '🌿' },
  ],
  persistedAnswer: 'focused',
  helper: 'useStepChoices',
} as const;
```
<!-- funnelsgrove:generated:end contract-v3/step/single_step_choice_emoji -->

## Interaction and persisted answer shape

Declare `choice.answerKey`; every option includes an emoji and stable ID. Persist the selected ID as a scalar string.

## Automatic lifecycle events

`useStepChoices` coordinates persistence, controller completion, and manifest routing. Preview suppresses provider delivery.

## Required semantic conversions

None.

## Approved shared helpers

Use `useStepChoices` and the shared emoji-choice rendering pattern.

## MUST rules

- Provide meaningful emoji data for every option.
- Keep IDs stable when labels or emoji change.

## NEVER rules

- Never persist emoji or labels as the answer.
- Never bypass the choice helper.

## Golden template or fixture

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

## Validation command

Run `fgrove validate`.

## Manual QA and completion criteria

Confirm keyboard and pointer selection both save one stable ID, show the intended emoji, and advance once.
