Модальное окно
<sf-modal> показывает одну ограниченную задачу поверх страницы:
подтверждение, короткую форму, подробности. Компонент управляет верхним
слоем, клавиатурной границей, блокировкой страницы и возвратом фокуса;
приложение отвечает за смысл действий и данные внутри. Самостоятельный
долгий процесс лучше открыть отдельной страницей.
Пример
Выберите, когда присылать уведомления по проекту.
Применение
Открытие и закрытие
Открывающее действие связывается с окном атрибутом data-sf-modal-open со
значением modal-id окна. Кнопки внутри закрывают конкретный экземпляр
через data-sf-modal-close. Содержимое окна передают слоты header,
content и footer; заголовок по умолчанию задаёт title.
По умолчанию окно закрывается по Escape, нажатию на затемнение и кнопке
закрытия. unclose отключает эти пути для обязательного решения; в таком
окне всегда оставляйте понятные действия. При нескольких открытых окнах
Escape, Tab и блокировкой страницы владеет только верхнее.
Положение
center, inline-start, inline-end, top и bottom меняют положение, но
не поведение окна. Положения inline-start и inline-end — модальная
боковая панель; панели, рядом с которыми страница остаётся доступной, делает
Drawer. Логические направления
учитывают письмо справа налево; физические left и right — их синонимы
для совместимости.
Физическая левая сторона не меняется в RTL.
Физическая правая сторона не меняется в RTL.
В LTR это левая сторона, в RTL — правая.
В LTR это правая сторона, в RTL — левая.
Короткая задача у верхней границы.
Короткая задача у нижней границы.
Затемнение и полноэкранный режим
overlay-preset="default" даёт стабильное затемнение. Вариант focus
добавляет размытие фона, не заменяя затемнение. fullscreen берите только
для ограниченной задачи, которой действительно нужна вся область просмотра.
Стабильное затемнение без blur.
Затемнение сохраняется, а фон дополнительно размывается.
Используйте для ограниченной задачи, которой действительно нужна вся область.
Окно в потоке страницы
display="inline" оставляет поверхность в обычном потоке. Она не выносится
в отдельный слой, не блокирует страницу, не захватывает и не возвращает
фокус.
Окно в потоке показывается сразу, атрибут open для этого не нужен.
close() убирает его со страницы, а open() возвращает на место; toggle()
переключает эти два состояния. Так же окно закрывает и его собственная кнопка
закрытия, если она показана. Пример ниже написан без open.
Сворачивание и восстановление
hide="true" добавляет действие сворачивания. Свёрнутое окно остаётся
открытым экземпляром, но перестаёт быть видимым интерактивным слоем. Для
восстановления нужна внешняя кнопка с data-sf-modal-show, потому что
содержимое свёрнутого окна недоступно.
Свёрнутое окно остаётся экземпляром, но перестаёт быть активным слоем.
Источник содержимого
Обычный mode="inline" берёт содержимое из слотов. mode="ajax" принимает
в src адрес или селектор узла на странице; mode="iframe" создаёт
отдельный документ. Для селектора сетевой запрос не нужен.
Разметка внутри <sf-modal> без атрибута slot тоже становится содержимым
окна: она идёт после того, что передано в слот content, — так же, как у
sf-drawer: <sf-modal modal-id="about" title="О проекте"><p>…</p></sf-modal>
показывает абзац в окне.
Для удалённых источников приложение определяет разрешения, CSP, обработку
ошибки и доверие к содержимому. Встроенный документ — одна остановка Tab;
окно не читает чужой документ и сохраняет свою кнопку закрытия.
Слоты показываются копиями
При подключении <sf-modal> забирает элементы со slot и содержимое без
слота из своей разметки и показывает их копии. Обычное окно рисует копии в отдельном контейнере
[data-sf-modal-portal] в конце body, окно в потоке — внутри самого
элемента. Повторная отрисовка может заменить копии новыми. Поэтому ссылка на
элемент слота, полученная до отрисовки, указывает на узел вне документа, а
обработчик addEventListener на нём не сработает.
Обрабатывайте события внутри окна делегированием: слушайте submit или
click на document и проверяйте event.target. Если нужен сам элемент,
найдите его после await modal.whenRendered().
Проверка полей в окне строится так же: focusout и submit слушают на
document, а поле берут из события. SF.Input.setState меняет состояние
той копии поля, которую показывает окно. После close() из обработчика
фокус возвращается на элемент, который открыл окно.
Пример: проверка формы в окне
Настройка поверхности
show-header, show-close, show-footer, close-on-esc,
close-on-overlay, overlay, position, fullscreen, width и height
меняют независимые части окна. Для внешнего оформления используйте
root-class, overlay-class, surface-class, panel-class, header-class,
body-class, content-class и footer-class. Значения геометрии задавайте
токенами Framework, а не абсолютными размерами. Поверхность берёт радиус
крупных блоков --sf-radius-default; кнопки закрытия и сворачивания —
компактные кнопки-иконки со своим радиусом.
Окно внутри блока
Обычно окно выводится в конце body и закрывает всё окно браузера. Если
<sf-modal> находится внутри элемента с атрибутом data-sf-overlay-container,
затемнение и поверхность окна выводятся внутри этого элемента и закрывают
только его: элемент получает contain: layout, а прокрутка страницы не
блокируется. Так область редактора или пример документации держат своё окно;
примеры с формой, источником содержимого и проверкой формы на этой странице
устроены так. Тот же атрибут держит внутри блока и
Drawer.
<div data-sf-overlay-container class="h-e6">
<sf-modal modal-id="preview" title="Пример">…</sf-modal>
</div>
Высоту блока задаёт страница: окно стоит по его границам.
Методы и события
open(), close(), toggle(), hide(), show(), setSrc() и
reloadContent() управляют тем же экземпляром. События modal:before-open,
modal:before-close, modal:before-hide и modal:before-show можно
отменить; соответствующее modal:after-* приходит только после принятого и
завершённого перехода.
События modal:* всплывают до document, как у sf-drawer; окно-источник
указано в event.detail.modal. Помощники onBeforeOpen(), onAfterOpen()
и остальные, а также обработчики, переданные в SF.create, получают только
события своего окна. Обычный слушатель на внешнем окне услышит и вложенное,
поэтому проверяйте event.detail.modal. Второй аргумент помощника —
параметры addEventListener: modal.onAfterClose(handler, {once: true})
сработает на ближайшее закрытие этого окна и снимется.
const modal = await SF.createAsync('modal', {
modalId: 'confirm-delete',
title: 'Удалить проект?',
html: '<p slot="content">Проект и его файлы удаляются без возможности восстановления.</p>',
onAfterClose: () => refreshList(),
});
document.body.append(modal);
await modal.whenRendered();
modal.open();
Доступность
- Окну нужно доступное имя: видимый
titleилиaria-label. Без них окно называется общим словом на языке страницы — «Окно», по-английски «Dialog». - Открытое окно —
dialogсaria-modal="true". Фокус переходит на саму панель окна, а не на первое поле;TabиShift+Tabне выходят за его границы, остальная страница недоступна. После закрытия — кнопкой,Escapeили методомclose()— фокус возвращается на элемент, который открыл окно. Первое поле формы в окне человек получает первым нажатиемTab. Escapeзакрывает верхнее окно, если не заданuncloseилиclose-on-esc="false". Пока внутри открыта всплывающая панель (sf-popover),Escapeзакрывает сначала её. В окне сuncloseоставьте видимые действия, которыми задачу можно завершить.- Кнопки закрытия и сворачивания на русской странице называются «Закрыть» и «Свернуть».
- Окно в потоке (
display="inline") — областьregionбез удержания фокуса. - Кнопке, которая открывает окно через
data-sf-modal-open, Framework ARIA не ставит: ниaria-haspopup, ниaria-expanded, ниaria-controls. Нужное пишите на кнопке сами, напримерaria-haspopup="dialog".
Справочник API
Раздел собран из манифеста компонента выпуска ui-106d5901f8c3 и обновляется вместе с выпуском. Чтобы исправить описание, исправьте манифест.
Каждому атрибуту соответствует свойство элемента с тем же именем в camelCase: search-placeholder — searchPlaceholder. Свойство атрибута template называется templateName.
| Тег | <sf-modal> |
| Назначение | Диалоговое окно поверх страницы в общем стеке модальных окон: по центру или у боковой, верхней или нижней границы, со слотами заголовка, содержимого и подвала, ловушкой фокуса, блокировкой прокрутки и возвратом фокуса. Окно также можно свернуть, загрузить его содержимое через Ajax или в iframe либо отрисовать встроенным в поток страницы. |
| Контракт | smart.modal, версия 1.1.0 |
| Поставка | выпуск Framework ui-106d5901f8c3 |
| Жизненный цикл | экспериментальный: API может меняться между выпусками |
| Готовность | описан: манифест и сценарий есть, продуктовой приёмки нет |
| Заготовка до прихода кода | нет: атрибут data-sf-skeleton не пишется; своего скелетона при загрузке данных нет (Заготовка до прихода кода) |
Атрибуты
template—string, по умолчаниюdefault.modal-id—string, по умолчанию пусто.title—string, по умолчанию пусто. Пусто — текст на языке страницы (по-английски «Dialog»).aria-label—string, по умолчанию пусто.text—string, по умолчанию пусто.open—boolean, по умолчаниюfalse.autoload—boolean, по умолчаниюfalse.unclose—boolean, по умолчаниюfalse.hide—boolean, по умолчаниюfalse.hide-modifier—string, по умолчанию пусто.minimized—boolean, по умолчаниюfalse.overlay—boolean, по умолчаниюtrue.show-header—boolean, по умолчаниюtrue.show-close—boolean, по умолчаниюtrue.show-footer—boolean, по умолчаниюtrue.close-on-esc—boolean, по умолчаниюtrue.close-on-overlay—boolean, по умолчаниюtrue.preserve-scroll-gap—boolean, по умолчаниюtrue.position—string, по умолчаниюcenter, значения:center,left,right,inline-start,inline-end,top,bottom.mode—string, по умолчаниюinline, значения:inline,ajax,iframe.display—string, по умолчаниюmodal, значения:modal,inline.src—string, по умолчанию пусто.root-class—string, по умолчанию пусто.preload—boolean, по умолчаниюtrue.fullscreen—boolean, по умолчаниюfalse.width—string, по умолчанию пусто.height—string, по умолчанию пусто.blur—string, по умолчанию пусто.blur-type—string, по умолчаниюmedium, значения:none,small,medium,large.overlay-preset—string, по умолчаниюdefault, значения:default,focus.overlay-class—string, по умолчанию пусто.close-class—string, по умолчанию пусто.surface-class—string, по умолчанию пусто.surface-padding—string, по умолчанию пусто.panel-class—string, по умолчанию пусто.header-class—string, по умолчанию пусто.body-class—string, по умолчанию пусто.content-class—string, по умолчанию пусто.footer-class—string, по умолчанию пусто.
Методы
getSlotHtml(name: string)— возвращаетstring. Возвращает HTML захваченного содержимого для именованного слота с перенесёнными данными времени выполнения и идентификаторами событий.open(options?: object|boolean)— возвращаетobject. Открывает окно или выводит его на передний план, если оно уже открыто. Отправляет modal:before-open (отменяемое), затем modal:after-open после проецирования; загружает удалённое содержимое, если задан src. options.animate (или логическое значение) управляет анимацией открытия. Возвращает элемент.close()— возвращаетobject. Закрывает окно после modal:before-close (отменяемое), выполняет анимацию закрытия, возвращает фокус и отправляет modal:after-close. Возвращает элемент.hide()— возвращаетobject. Сворачивает открытое накладываемое окно после modal:before-hide (отменяемое) и отправляет modal:after-hide. Во встроенном режиме ничего не делает. Возвращает элемент.show()— возвращаетobject. Восстанавливает свёрнутое окно после modal:before-show (отменяемое) и отправляет modal:after-show. Возвращает элемент.toggle()— возвращаетobject. Вызывает close(), если открыто, иначе open(). Возвращает элемент.setSrc(src: string)— возвращаетobject. Устанавливает атрибут src, прерывает и сбрасывает текущее удалённое содержимое и загружает новый источник, если загрузка сейчас разрешена. Возвращает элемент.getModalRoot()— возвращаетobject|null. Возвращает отрисованный элемент .sf-modal или null до отрисовки.onKeyDown(event: KeyboardEvent)— возвращаетnull. Обработчик keydown документа, который модальное окно привязывает само: Escape закрывает верхнее открытое окно, если это разрешает close-on-esc, Tab удерживается внутри него. Не предназначен для вызова хостом.resetRemoteContent()— возвращаетnull. Очищает загруженный удалённый HTML, ошибку и состояние загрузки и прерывает выполняющийся запрос.clearPortal()— возвращаетnull. Снимает отрисовку и удаляет корень портала, в который проецировалось окно, если он есть.onBeforeOpen(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:before-open, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onAfterOpen(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:after-open, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onBeforeClose(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:before-close, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onAfterClose(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:after-close, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onBeforeHide(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:before-hide, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onAfterHide(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:after-hide, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onBeforeShow(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:before-show, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onAfterShow(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:after-show, который срабатывает только на собственные события этого модального окна. Возвращает элемент.onModalReady(handler: function, options?: object|boolean)— возвращаетobject. Сразу вызывает обработчик с событием modal:ready, если модальное окно уже отрисовано, иначе добавляет обработчик его собственного modal:ready. Возвращает элемент.onModalUpdate(handler: function, options?: object|boolean)— возвращаетobject. Добавляет на хост-элементе обработчик modal:update, который срабатывает только на собственные события этого модального окна. Возвращает элемент.reloadContent()— возвращаетobject. Сбрасывает удалённое содержимое и снова загружает src, даже если окно закрыто и preload выключен. Возвращает элемент.
События
Все события приходят на сам элемент и всплывают. Общие события базового элемента перечислены в главе Жизненный цикл → Этапы.
modal:after-close—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. После закрытия окна. Всплывает.modal:after-hide—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. После сворачивания окна. Всплывает.modal:after-open—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. После открытия окна. Всплывает.modal:after-show—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. После того как свёрнутое окно снова показано. Всплывает.modal:before-close—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. Перед закрытием окна; отменяемое — preventDefault() оставляет окно как есть. Всплывает.modal:before-hide—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. Перед сворачиванием окна; отменяемое — preventDefault() оставляет окно как есть. Всплывает.modal:before-open—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. Перед открытием окна; отменяемое — preventDefault() оставляет окно как есть. Всплывает.modal:before-show—detail:{ component?: any, modal?: any, modalId?: string, root?: any, phase?: string }. Перед тем как свёрнутое окно снова показано; отменяемое — preventDefault() оставляет окно как есть. Всплывает.modal:ready—detail:{ component?: any, modal?: any, modalId?: string, root?: any }. Окно отрисовано впервые. Всплывает и с composed: true; detail.modal — sf-modal, отправивший событие.modal:update—detail:{ component?: any, modal?: any, modalId?: string, root?: any }. Окно отрисовано повторно после первой отрисовки. Всплывает и с composed: true; detail.modal — sf-modal, отправивший событие.sf-after-render—detail:{ component?: any, tagName?: string, template?: string, changedAttributes?: array }. Базовое событие жизненного цикла после каждой отрисовки. Всплывает и с composed: true.sf-before-render—detail:{ component?: any, tagName?: string, template?: string, changedAttributes?: array }. Базовое событие жизненного цикла перед каждой отрисовкой. Всплывает и с composed: true.modal:before-content-upload—detail:{ component?: any, modal?: any, modalId?: string, src?: string, remote?: object }. Начинается Ajax-запрос содержимого (mode=ajax). Всплывает и с composed: true.modal:after-content-upload—detail:{ component?: any, modal?: any, modalId?: string, src?: string, remote?: object }. Удалённое содержимое загружено, с success или error в detail.remote; прерванный запрос его не отправляет. Также отправляется при загрузке iframe. Всплывает и с composed: true.
Доступность
- Роль: диалог (
dialog). - Доступное имя: обязательно.
- Клавиши:
Tab,Shift+Tab,Escape. - Фокус: При открытии фокус переходит на панель верхнего окна; Tab и Shift+Tab удерживаются внутри неё, а Escape закрывает её, если это разрешает close-on-esc. При закрытии фокус возвращается элементу, который открыл окно. Заголовок по умолчанию задаёт доступное имя диалога через aria-labelledby; для пользовательского заголовка или окна без заголовка укажите aria-label. display=inline сохраняет обычную навигацию по документу. С display=inline окно является областью (region) на странице, а не диалогом.
Минимальная разметка
<sf-modal></sf-modal>
Источник
simai/ui@106d5901f8c3b4f23131ce0e7ede5dbd8abfe4f4:distr/smart/modalsimai/ui@106d5901f8c3b4f23131ce0e7ede5dbd8abfe4f4:distr/rule/rule.json#name=cl-modal