javascript

Popover = hint

  • пятница, 28 февраля 2025 г. в 00:00:06
https://habr.com/ru/articles/886334/

Эта статья — перевод оригинальной статьи «Popover = hint»

Также я веду телеграм канал «Frontend по‑флотски», где рассказываю про интересные вещи из мира разработки интерфейсов.

Вступление

Chrome 133 развивает существующую функцию всплывающих подсказок, представляя новый режим: popover="hint". Этот режим, управляемый браузером, позволяет использовать новый контекст наложения, упрощающий создание всплывающих подсказок и подобных эфемерных плавающих элементов. Он снижает трудозатраты разработчиков, сохраняя гибкость дизайна.

Введение и история

API Popover, представленный в Chrome 114, позволяет создавать доступные плавающие пользовательские интерфейсы, такие как меню и всплывающие подсказки. По умолчанию popover="auto" управляет функциями отключения лёгкого закрытия и управления фокусом, не требуя дополнительных сценариев, как описано в разделе Знакомство с API Popover. При открытии поповера с popover="auto" все остальные безпредковые поповеры с popover="auto" будут закрыты, что обеспечивает эргономичность API, который делает наиболее разумные вещи.

Поповеры, закрывающие другие поповеры

<div id="p1" popover>First Popover</div>
<button popovertarget="p1">Open popover 1</button>
<div id="p2" popover>Second Popover</div>
<button popovertarget="p2">Open popover 2</button>

В этом примере открытие popover 2 приведет к закрытию popover 1, поскольку popover="auto" позволяет одновременно открывать только один такой popover.

Хотя такое поведение хорошо работает для меню и диалогов, оно может создавать проблемы, когда необходимо сосуществование нескольких типов плавающего пользовательского интерфейса. Например, меню и всплывающая подсказка, использующие popover="auto", могут конфликтовать, когда открытие всплывающей подсказки приводит к закрытию меню. Такая ситуация может показаться необычной, но она часто встречается в современных пользовательских интерфейсах в стиле приложений. Например, меню в шапке github.com используют всплывающие окна и для меню, и для всплывающих подсказок, позволяя при определенных условиях видеть их одновременно:

Одним из способов решения этой проблемы является использование popover="manual" для элементов всплывающих подсказок, что позволяет полностью контролировать всплывающие подсказки с помощью скриптов. Однако для этого необходимо переделать поведение стека, лёгкого закрытия и управление фокусом - именно те задачи, для решения которых был создан Popover API. Это подтолкнуло нас к поиску путей расширения API для обеспечения недостающей функциональности.

В ходе исследований, проведенных разработчиками, мы выявили два распространенных контекста наложения:

  • Постоянный пользовательский интерфейс: Например, меню и диалоговые окна.

  • Эфемерный пользовательский интерфейс: Например, наведенные карточки и всплывающие подсказки.

Чтобы учесть оба варианта, popover="hint" вводит второй стек, отличный от popover="auto", гарантируя, что меню останется открытым даже при появлении всплывающих подсказок. Вместо того чтобы вводить несколько контекстов наложения для разных типов пользовательского интерфейса, что, по сути, означало бы повторное изобретение z-index, этот подход упрощает ситуацию, определяя всего две широкие категории: постоянный пользовательский интерфейс (auto) и эфемерный пользовательский интерфейс (hint). Это позволяет найти баланс между гибкостью и предотвращением повторного возникновения тех же проблем, с которыми вы сталкивались до использования popover.

Поведение нового значения

И popover="auto", и popover="hint" поддерживают легкое закрытие, то есть они автоматически закрываются, когда пользователь щелкает за их пределами или нажимает Esc на клавиатуре. В этом отношении оба стиля идентичны.

Когда речь идет о принудительном скрытии других всплывающих окон, popover="auto" закрывает все другие всплывающие окна авто и подсказки при открытии, гарантируя, что только одно такое окно будет активно одновременно (единственным исключением здесь являются вложенные всплывающие окна, о которых речь пойдет ниже). popover="hint", с другой стороны, принудительно скрывает только другие всплывающие окна подсказки, позволяя меню и всплывающим окнам оставаться открытыми и сосуществовать.

Больше всего они различаются по вложенности. popover="auto" поддерживает вложенность, позволяя дочернему поповеру оставаться открытым внутри другого родительского поповера. popover="hint" имеет особое поведение по вложенности, в котором участвуют отдельные "стопки". Когда поповер с подсказкой находится внутри автопоповера, он присоединяется к автостеку, чтобы сохранить контекстную группировку, то есть он будет оставаться открытым до тех пор, пока другие автоповеры или поповеры с подсказкой не заставят его принудительно скрыться. Это обеспечивает интуитивное поведение, при котором всплывающие подсказки не мешают другим меню или всплывающим окнам.

Наконец, для самых разных случаев использования всегда есть popover="manual", который не содержит ни одного из этих поведений, позволяя вам определить точную функциональность и поведение, которые вам нужны.

popover="auto"

popover="hint"

popover="manual"

Лёгкое закрытие

Да

Да

Нет

Принудительно скрывает

Несвязанные auto и hint

Несвязанные hint

Ничего

Вложенность

Да

Особая (описано ранее)

N/A - нет лёгкого закрытия

Триггер наведения

Распространенным UX-шаблоном являются всплывающие подсказки и ховеркарты, которые срабатывают при наведении курсора. Наведение курсора мыши на интересующий элемент в течение определенного времени приводит к показу наведенной карточки. В настоящее время такое поведение необходимо реализовать с помощью JavaScript, например, добавив слушателей для событий mouseenter и mouseleave. Однако в разработке находится еще один API, который должен сделать триггер ховера декларативным: API Interest Invokers.

Работа над этим API еще не завершена, но общая идея состоит в том, чтобы добавить атрибут interesttarget ко многим типам элементов, который наделяет их поведением, вызывающим наведение курсора:

<a interesttarget="my-hovercard" href="...">
  Hover to show the hovercard
</a>
<span popover="hint" id="my-hovercard">
  This is the hovercard
</span> 

При использовании предыдущего HTML наведение курсора на ссылку <a> автоматически покажет всплывающее окно my-hovercard. Если переместить указатель на этот элемент, всплывающее окно будет скрыто. И все это без JavaScript!

Примеры

<button>An interesting button</button>
<div popover="hint">More info about the button</div>
[popover] {
  margin: 0;
  inset: auto;
  position-area: bottom right;
}
const button = document.querySelector('button');
const popover = document.querySelector('[popover]');

button.onmouseenter = () => {
  setTimeout(() => {
    popover.showPopover({source: button});
  }, 500);
}

button.onmouseleave = () => {
  setTimeout(() => {
    popover.hidePopover();
  }, 500);
}
Ссылка на демо

В этом примере используется popover="hint" для создания базовой всплывающей подсказки, которая предоставляет дополнительную информацию о кнопке при наведении на нее мыши. Активация наведения обеспечивается обработчиками событий mouseenter и mouseleave с простыми задержками в 0,5 секунды. Обратите внимание, что есть несколько деталей, которые не обрабатываются в этом примере:

  1. Наведение на сам всплывающий элемент не предотвращает закрытие всплывающего элемента при наведении на него. Поэтому, например, невозможно скопировать или вставить текст из всплывающего окна.

  2. Никакого "debouncing" нет: достаточно навестись на кнопку на небольшую долю секунды, чтобы сработало всплывающее окно, даже если кнопка будет быстро отведена до истечения времени задержки. В этом случае всплывающая подсказка "мерцает", быстро открываясь и закрываясь.

  3. Пример вообще недоступен: любой пользователь, не использующий мышь, не может получить доступ к содержимому всплывающей подсказки.

Эти недостатки можно исправить с помощью дополнительного JavaScript. Например, необходимо добавить обработчики событий focus (или, возможно, keydown и keyup) для поддержки активации всплывающей подсказки с помощью клавиатуры. Объяснение того, что нужно правильно обработать, чтобы всплывающая подсказка была доступной, можно найти в этой замечательной записи в блоге Сары Хигли. Все эти вопросы (и многие другие) будут автоматически решаться декларативно с помощью API Interest Invokers.