StepperModal — многоступенчатая модалка
Расположение
src/components/ui/StepperModal.vue
Назначение
Переиспользуемый wizard-компонент для пошаговых форм. Оборачивает Modal.vue, добавляя навигацию по шагам с индикатором прогресса.
Props
| Prop | Тип | По умолчанию | Описание |
|---|---|---|---|
steps | Array<{ key: string, title: string }> | обязателен | Описание шагов. key используется для именованных слотов |
modelValue | Boolean | false | Видимость модалки (v-model) |
id | String | — | ID для Bootstrap modal |
title | String | — | Заголовок модалки. Если не указан — берётся title текущего шага |
submitText | String | 'Создать' | Текст кнопки на последнем шаге |
nextText | String | 'Далее' | Текст кнопки перехода на следующий шаг |
backText | String | 'Назад' | Текст кнопки возврата |
stacking, breakpoint, forceDesktop | — | — | Проброс в Modal |
disabledNext | Boolean | — | Блокировка кнопки «Далее» |
disabledSubmit | Boolean | — | Блокировка кнопки «Создать» |
showLoader | Boolean | — | Лоадер на кнопке «Создать» |
Events
| Event | Payload | Описание |
|---|---|---|
update:modelValue | Boolean | Закрытие/открытие |
submit | — | Нажатие финальной кнопки |
step-change | Number (индекс) | Переход на другой шаг |
Именованные слоты
Для каждого шага используется слот #step-{key}:
<StepperModal :steps="[{ key: 'info', title: 'Информация' }, { key: 'confirm', title: 'Подтверждение' }]">
<template #step-info>
<!-- содержимое первого шага -->
</template>
<template #step-confirm>
<!-- содержимое второго шага -->
</template>
</StepperModal>Динамические шаги
Массив steps может быть computed — компонент автоматически адаптируется при изменении набора шагов. Если текущий индекс выходит за границы нового массива, он корректируется.
Мобильное позиционирование кнопок
На мобилке кнопки «Назад / Далее / Создать» прижаты к низу видимой области модалки через mt-auto + динамический min-height.
Как работает: при открытии модалки, после завершения анимации ion-modal (~400ms), JS измеряет getBoundingClientRect().top контейнера и visualViewport.height, вычитает высоту sibling-элементов (пустой buttons wrapper из Modal.vue) и устанавливает точный min-height через inline style.
Ранее использовался хардкод calc(100svh - 80px), который ломался на разных устройствах из-за safe-area, отступов stacking-режима ion-modal и т.д.
expose
Компонент экспортирует currentStepIndex, goNext, goBack, goToFirstStepWithErrors для программной навигации.
Использование в проекте
CreateUpdatePortfolioModal.vue— создание портфеля (editMode использует обычную Modal).- Обычный портфель: 4 шага (тип → параметры → учёт валюты → уведомления)
- Составной портфель: 3 шага (тип → параметры → уведомления)
Связь с currency_mode
Поле currency_mode портфеля (выбирается на шаге «Учёт валюты» при создании) влияет на CreateOperationModal.vue:
currency_mode.code === 'strict'("Обязательный учет") → опция «Нет» скрыта изconversion_target_type, дефолт — «Валюта»currency_mode.code === 'facultative'("Валюта не важна") илиnull→ поведение по умолчанию (дефолт — «Нет»)