ModalPage
Компонент реализующий модальное окно. Позволяет показать дополнительный контент, удерживая пользователя в текущем контексте страницы/приложения.
Область применения
- Формы для редактирования.
- Детали профиля пользователя.
- Разделы настроек, которые должны удерживать пользователя в текущем контексте приложения.
Анатомия
ModalPage состоит из композиции нескольких компонентов.
Опциональные компоненты, передающиеся пользователем:
- ModalPageHeader – передаётся через параметр
header; ModalPageFooter– передаётся через параметрfooter.
Обязательные компоненты, задающиеся библиотекой:
ModalOutlet– обёртка с фиксированной позицией для перекрытия других элементов в DOM;ModalOverlay– интерактивный задний фон;ModalPageInternal– инкапсулирует в себе всю логику поведения;ModalPageContent– оборачивает переданныйchildrenв CustomScrollView.
Поведение
Параметр open задает состояние показа/скрытия ModalPage. По умолчанию компонент скрыт.
При состоянии open={false} компонент размонтируется из DOM. Чтобы отключить это поведение, необходимо задать параметр
keepMounted.
Смена состояния сопровождается анимацией содержимого ModalPage, а также ModalOverlay. За сменой состояния можно следить
через события:
onOpenonOpenedonClose– передаёт в аргумент причину закрытия (см. описание в таблице с API)onClosed
Отличие onOpened/onClosed от onOpen/onClose в том, что они вызываются после завершения анимации.
Далее поведение зависит от разрешения экрана.
Настольный режим
При разрешении >= 768px компонент ModalPage имеет вид диалогового окна.
При open={true}:
- параметр
sizeбудет ограничивать максимальную ширину окна; - навигация через
TabиShift+Tabбудет зациклена на содержимомModalPage.
По умолчанию, пользователь может закрыть диалоговое окно с помощью:
- нажатия на кнопку закрытия, что вызовет событие
onCloseс аргументомclick-close-button; - нажатия на
ModalOverlay, что вызовет событиеonCloseс аргументомclick-overlay; - нажатия на
Esc, что вызовет событиеonCloseс аргументомescape-key.
Мобильный режим
При разрешении <= 767px компонент ModalPage имеет вид панели, выдвигающейся снизу вверх (далее bottom sheet).
При open={true} навигация через Tab и Shift + Tab будет зациклена на содержимом ModalPage (допустимо, т.к. к устройству
может быть подключена клавиатура).
По умолчанию, пользователь может закрыть bottom sheet с помощью:
- нажатия на
ModalOverlay, что вызовет событиеonCloseс аргументомclick-overlay; - нажатия на
Esc, что вызовет событиеonCloseс аргументомescape-key(допустимо, т.к. к устройству может быть подключена клавиатура); - определенного взаимодействие через тач или указатель мыши, что вызовет событие
onCloseс аргументомswipe-down(см. Взаимодействие через тач или указатель мыши)
Взаимодействие через тач или указатель мыши
Для bottom sheet можно задавать на какой процент высоты экрана изначально должна открываться панель – этот процент задаётся
через параметр settlingHeight. Минимальное значение 25, а максимальное 100. По умолчанию используется 50.
От settlingHeight зависит дальнейшее поведение bottom sheet:
- при
settlingHeight <= 90у bottom sheet появляется возможность через перетаскивание раскрывать высоту до100и схлопывать обратно до переданногоsettlingHeight; - при
settlingHeight > 90значение приводится к100и, соответственно, bottom sheet всегда раскрывается на100.
Если необходимо, чтобы высота bottom sheet зависела от его контента, то стоит использовать параметр dynamicContentHeight,
вместо settlingHeight.
В обеих случаях перетаскивание bottom sheet изменяет прозрачность ModalOverlay – при перетаскивание вниз фон становится
светлее. При settlingHeight процент прозрачности высчитывается относительно переданного значения в settlingHeight.
Пользователь через перетаскивание может вызвать закрытие bottom sheet по следующим условиям:
-
onClose('swipe-down')вызовется сразу же, если bottom sheet достиг высоты0, независимо закончил ли пользователь взаимодействие с ним или нет; -
onClose('swipe-down')вызовется, если после окончания взаимодействия с bottom sheet его высота будет:- при
settlingHeight: меньше половины переданного значения вsettlingHeight(пример, еслиsettlingHeight={50}, то условием закрытие будетheight < 50 / 2); - при
dynamicContentHeight: меньше половины контента;
- при
-
onClose('swipe-down')вызовется при сильном смахивании вниз;- при
settlingHeight: добавляется условии, что bottom sheet должен находится на высоте равной переданному вsettlingHeight;
- при
При следующих условиях возможность перетаскивания замораживается, чтобы не блокировать пользователя:
- при условии
disableContentPanningGesture={false}, есть взаимодействие с контентомModalPageContentприscrollTop !== 0; - есть взаимодействие с горизонтальным скроллом;
- есть взаимодействие с текстовым полем;
- есть взаимодействие с выделенным текстом;
- есть взаимодействие с элементом вызвавшим
event.stopPropagation()наonTouchStartилиonMouseDown. - есть взаимодействие с элементом с data-атрибутом
data-vkui-block-sheet-behavior(в частности, используется приdisableContentPanningGesture={true});
Доступность (a11y)
ModalPage является модальным окном (role="dialog"), а значит у него обязательно должно быть имя — его краткое название. Благодаря этому пользователи вспомогательных технологий знают, что это за элемент и какое у него содержимое.
Задать имя можно с помощью следующих способов:
- используя свойство
title; - используя свойство
aria-label; - используя свойство
aria-labelledby; - используя внутри компонент ModalPageHeader. Этот компонент сам свяжется с
ModalPageчерез контекст c помощьюaria-labelledby.
FAQ
Как поменять максимальную ширину контента?
Используйте параметр size.
Как задать фиксированную высоту контента?
Используйте параметр height. Высоту можно задать как числом (height={300}) так и в процентах (height={'80%'}).
Как правильно применять параметр autoFocus?
К сожалению, из-за особенностей React, autoFocus ломает CSS анимацию.
Чтобы исправить проблему, следует отказаться от autoFocus и выставлять фокус вручную при событии onOpened.
Свойства и методы
| Свойство | Описание |
|---|---|
disableCloseAnimation | booleanОтключает анимацию закрытия модалки. По умолчанию: - |
disableContentPanningGesture | booleanОтключает раскрытие и закрытие панели в мобильном виде. По умолчанию: - |
disableFocusTrap | booleanПозволяет отключить захват фокуса. Нужно использовать, когда поверх одной модалки открывается другая, чтобы два По умолчанию: - |
disableModalOverlay | booleanОтключает отображение и взаимодействие с фоном модалки. По умолчанию: - |
disableOpenAnimation | booleanОтключает анимацию открытия модалки. По умолчанию: - |
dynamicContentHeight | booleanЕсли высота контента в модальной странице может поменяться, нужно установить это свойство. По умолчанию: - |
footer | ReactNodeПодвал модальной страницы, По умолчанию: - |
getModalContentRef | Ref<HTMLDivElement>Возвращает DOM-элемент содержимого модального окна. По умолчанию: - |
getRootRef | Ref<HTMLDivElement>По умолчанию: - |
header | ReactNodeШапка модальной страницы, По умолчанию: - |
height | string | numberЗадаёт модальному окну фиксированную высоту. Можно передать числовое значение в пикселях, а можно строкой, в том числе и в процентах “50%”. В мобильной версии ‘settlingHeight’ будет считаться относительно заданного height. По умолчанию: - |
hideCloseButton | booleanСкрывает кнопку закрытия (актуально для iOS, так как можно отрисовать кнопку закрытия внутри модалки). По умолчанию: - |
id | stringПо умолчанию: - |
keepMounted | booleanСохранять ли компонент в DOM при По умолчанию: false |
modalContentTestId | string
По умолчанию: - |
modalDismissButtonLabel | stringТекст для скринридера. По умолчанию: - |
modalDismissButtonTestId | string
По умолчанию: - |
modalOverlayTestId | string
По умолчанию: - |
nav | stringУникальный идентификатор навигационного элемента (вместо id) По умолчанию: - |
noFocusToDialog | booleanОтключает фокус на интерактивный элемент после открытия модалки. По умолчанию: - |
onClose | ((reason: ModalPageCloseReason, event?: UIEvent<HTMLElement, UIEvent>) => void) | undefinedБудет вызвано при начале закрытия модалки. По умолчанию: - |
onClosed | VoidFunctionБудет вызвано при окончательном закрытии модалки. По умолчанию: - |
onOpen | VoidFunctionБудет вызвано при начале открытия модалки. По умолчанию: - |
onOpened | VoidFunctionБудет вызвано при окончательном открытии модалки. По умолчанию: - |
open | booleanСостояние видимости. По умолчанию: false |
outsideButtons | ReactNodeУправляющие элементы под кнопкой закрытия. Доступно только в По умолчанию: - |
preventClose | booleanПозволяет отключить возможность закрытия модальной страницы (смахивание, клавиша ⚠️ ВНИМАНИЕ: использование этой опции негативно сказывается на пользовательском опыте. По умолчанию: - |
restoreFocus | boolean | (() => boolean | HTMLElement)По умолчанию: true |
settlingHeight | numberПроцент, на который изначально будет открыта модальная страница. Игнорируется при включении По умолчанию: 50 |
size | LiteralUnion<"s" | "auto" | "m" | "l" | "max-content" | "min-content" | "fit-content", string | number>Задаёт контенту максимальную ширину на десктопе. По умолчанию: s |
style | Omit<CSSProperties, "height" | "maxHeight" | "maxWidth">Дополнительные стили. По умолчанию: - |