Modal
Модальне вікно зі стеком шарів, пасткою фокуса й блокуванням прокрутки.
Знизу до sm вікно — bottom sheet, вище — центрований діалог. Це не декор:
центроване вікно на телефоні з піднятою клавіатурою просто не вміщається.
Приклад
Вкладені оверлеї
Усі оверлеї бібліотеки ділять один стек шарів. Відкрийте другий рівень і натисніть Escape — закриється лише верхній.
API
Props
| Назва | Тип | Типово | Опис |
|---|---|---|---|
title | string | "" | Заголовок. Ігнорується, якщо задано слот `header`. |
size | lgsmmdxlfull | "lg" | Ширина панелі. |
panelClass | string | "" | Додаткові класи панелі — коли готових розмірів не вистачає. |
modalId | string | — | Стабільний id шару в стеку оверлеїв. Задавати не обов'язково: без нього генерується автоматично. |
initialFocus | string | — | CSS-селектор усередині панелі, якому віддати фокус при відкритті. Типово фокус отримує сама панель, а НЕ перший інпут: на мобільних автофокус в інпуті одразу піднімає клавіатуру і з'їдає пів екрана. |
ariaLabel | string | — | Доступне ім'я діалогу, коли слот `header` не є заголовком. Без нього aria-labelledby вказує на контейнер слота, і якщо там лежить поле вводу — ім'я вікна обчислюється з його ЗНАЧЕННЯ. Діалог пошуку оголошувався як «Діалог: тек» на слові «текст». |
modelValue | boolean | false | Відкрито. Використовуйте через `v-model`. |
closable | boolean | true | Показувати хрестик і дозволяти закриття через Escape. |
closeOnBackdrop | boolean | true | Клік по затемненому фону закриває вікно. Типово `true` — на відміну від UiDrawer, де типово `false`. Модалка зазвичай інформаційна, і випадкове закриття нічого не коштує; drawer майже завжди містить форму, де це втрата введеного. |
persistent | boolean | false | Ні Escape, ні клік по фону не закривають — лише явна дія. |
noPadding | boolean | false | Прибрати внутрішні відступи вмісту. |
Події
| Назва | Payload | Опис |
|---|---|---|
update:modelValue | [value: boolean] | Зміна стану відкриття. Використовуйте через `v-model`. |
close | [] | { "Вікно закрито — будь-яким способом": "хрестиком, Escape або кліком по фону." } |
Слоти
| Назва | Опис |
|---|---|
default | Вміст вікна. |
header | Замінює заголовок цілком. Тоді `title` не використовується. |
footer | Кнопки дій. Футер не рендериться, якщо слот порожній. |
Коли використовувати
Для короткої взаємодії, яка має перервати основний потік: підтвердження, компактна форма, перегляд деталі.
Якщо форма велика або користувач має звірятися зі сторінкою під нею —
беріть UiDrawer.
Коли НЕ використовувати
Не кладіть у модалку багатокрокові майстри. Заблокована прокрутка фону плюс обмежена висота панелі роблять довгий вміст незручним саме там, де його найбільше.
Не ставте :closable="false", доки у вікні немає власного шляху виходу.
Цей прапорець вимикає всі способи закриття одразу: і хрестик, і Escape,
і клік по фону. Разом із пасткою фокуса, яка робить решту сторінки inert,
вікно стає глухим кутом — вийти можна хіба перезавантаженням вкладки. Саме
так свого часу поводився пошук по цій документації. Якщо закриття справді
має бути лише явним, лишіть у вікні власну кнопку, яка змінює v-model.
Доступність
Панель має role="dialog", aria-modal="true" і назву — з title через
aria-labelledby або з aria-label, якщо заголовок замінено слотом.
Коли слот header містить не заголовок, а керування — поле пошуку,
перемикач — назву треба задати props ariaLabel явно. Інакше
aria-labelledby вказує на контейнер слота, і назву вікна браузер
обчислює зі значення поля: діалог оголошувався як «Діалог: тек», щойно
користувач набирав «текст».
Фокус утримується всередині панелі, а при закритті повертається на елемент,
з якого вікно відкрили. Решта прямих дітей <body> на час відкриття
позначаються inert і aria-hidden.
Типово фокус отримує сама панель, а не перший інпут: на мобільних
автофокус в інпуті одразу піднімає клавіатуру і з'їдає пів екрана. Якщо
потрібно інакше — задайте initialFocus.
Портування
Компонент не працює сам по собі: йому потрібні чотири композабли зі списку
залежностей вище. Разом вони становлять overlay-ядро, спільне для UiModal,
UiDrawer і UiConfirmDialog — копіюйте їх один раз на проєкт.