# Step

## Usage

Individual step within a Stepper. Renders a progress-bar segment, an indicator, and a label with optional description. Progress (completed/active/not-started) is derived from the parent Stepper's activeStep and this step's step index.

`step` is the zero-based index and decides the progress, so it is never set directly. The default slot puts content under the description, outside the clickable label row, so a form inside keeps its own targets. `end` adds trailing content to the label row, and `icon` replaces the built-in indicator artwork.

```vue
<script setup lang="ts">
import { Step, Stepper } from '@astryx-vue/core/Stepper'
import { ref } from 'vue'

const active = ref(1)
</script>

<template>
  <Stepper :active-step="active" @step-click="active = $event">
    <Step label="Cart" :step="0" />
    <Step label="Shipping" :step="1" />
    <Step label="Payment" :step="2" />
  </Stepper>
</template>
```

## Examples

Common configurations, variations, and states.

### Content Slot

Children passed to a Step render below its description, indented to line up with the label rather than the indicator, and stay outside the clickable label area so buttons inside remain their own targets. In a full flow you gate the slot on the step being active. That is what turns a vertical stepper into an expanding one.

```vue
<script setup lang="ts">
import { Button } from '@astryx-vue/core/Button'
import { Step, Stepper } from '@astryx-vue/core/Stepper'
import { TextInput } from '@astryx-vue/core/TextInput'
import { ref } from 'vue'

const street = ref('')
const city = ref('')
</script>

<template>
  <div style="width: 400px; max-width: 100%">
    <Stepper :active-step="0" orientation="vertical">
      <Step
        description="Used for invoices and tax calculation"
        label="Billing address"
        :step="0"
      >
        <div class="step-content-demo">
          <TextInput v-model="street" label="Street" placeholder="1 Hacker Way" />
          <TextInput v-model="city" label="City" placeholder="Menlo Park" />
          <div>
            <Button label="Save address" variant="primary" />
          </div>
        </div>
      </Step>
    </Stepper>
  </div>
</template>

<style scoped>
.step-content-demo {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>
```

### Indicator

Everything the indicator prop accepts: the auto default, an always-number badge, a custom node, and none, each on its own completed Step so the prop is the only difference between them. Every variant occupies the same 16px box, so a step swapping its number for a check as it completes never shifts the label beside it. The last cell shows that a custom node can be live rather than static: a Spinner on a step that is in progress, shaded inherit so it picks up the step's own tint like any other glyph.

```vue
<script setup lang="ts">
import { Icon } from '@astryx-vue/core/Icon'
import { Spinner } from '@astryx-vue/core/Spinner'
import { Step, Stepper } from '@astryx-vue/core/Stepper'
import { Text } from '@astryx-vue/core/Text'
</script>

<template>
  <div class="step-cells">
    <div class="step-cells__cell">
      <Text type="label">
        auto (default)
      </Text>
      <Stepper :active-step="1" orientation="vertical">
        <Step label="Verify email" :step="0" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        number
      </Text>
      <Stepper :active-step="1" orientation="vertical">
        <Step indicator="number" label="Verify email" :step="0" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        Custom node
      </Text>
      <Stepper :active-step="1" orientation="vertical">
        <Step label="Verify email" :step="0">
          <template #icon>
            <Icon icon="check" size="sm" />
          </template>
        </Step>
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        none
      </Text>
      <Stepper :active-step="1" orientation="vertical">
        <Step indicator="none" label="Verify email" :step="0" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        Spinner (in progress)
      </Text>
      <Stepper :active-step="0" orientation="vertical">
        <Step label="Verify email" :step="0">
          <template #icon>
            <Spinner size="sm" />
          </template>
        </Step>
      </Stepper>
    </div>
  </div>
</template>

<style scoped>
.step-cells {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.step-cells__cell {
  width: 190px;
}
</style>
```

### States

Every state a single Step can land in, each shown as one Step in its own Stepper. Completed, current, and upcoming are derived by comparing the step index against the parent activeStep, so they are never set directly; isDisabled and status are the two a step declares itself. Status is a separate axis from progress, which is why a completed step can still carry a warning.

```vue
<script setup lang="ts">
import { Step, Stepper } from '@astryx-vue/core/Stepper'
import { Text } from '@astryx-vue/core/Text'
</script>

<template>
  <div class="step-cells">
    <div class="step-cells__cell">
      <Text type="label">
        Completed
      </Text>
      <Stepper :active-step="1" orientation="vertical">
        <Step label="Verify email" :step="0" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        Current
      </Text>
      <Stepper :active-step="0" orientation="vertical">
        <Step label="Verify email" :step="0" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        Upcoming
      </Text>
      <Stepper :active-step="0" orientation="vertical">
        <Step label="Add a payment method" :step="1" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        Disabled
      </Text>
      <Stepper :active-step="0" orientation="vertical">
        <Step is-disabled label="Add a payment method" :step="1" />
      </Stepper>
    </div>
    <div class="step-cells__cell">
      <Text type="label">
        Completed, with a status
      </Text>
      <Stepper :active-step="1" orientation="vertical">
        <Step label="Verify email" :step="0" status="warning" />
      </Stepper>
    </div>
  </div>
</template>

<style scoped>
.step-cells {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
}

.step-cells__cell {
  width: 220px;
}
</style>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `step` | `number` | — | Zero-based index of this step. Compared with the stepper's `activeStep` to derive the progress. Required. |
| `label` | `string` | — | Step name. Required. |
| `description` | `string` | — | Supporting line under the label. |
| `status` | `'accent' \| 'success' \| 'warning' \| 'error'` | — | Recolors the indicator only. The connector stays on the progress color. |
| `isDisabled` | `boolean` | `false` | Whether the step can be skipped over. Its label is dimmed, and the stepper's controls step past it. |
| `isOptional` | `boolean` | `false` | Appends an Optional marker after the label. |
| `indicator` | `'auto' \| 'number' \| 'none'` | `'auto'` | `auto` shows a check when done, a ring while in progress, and a number after that. `number` always shows the step number. `none` leaves the indicator empty. |
| `density` | `'compact' \| 'balanced' \| 'spacious'` | The stepper's density | Space around this step. |

## Slots

- `default`: content under the description. In a vertical separated step it sits outside the clickable label row.
- `icon`: replaces the built-in indicator artwork. A `Spinner` makes it live.
- `end`: trailing content on the label row, such as a duration.
