# tooltip ## Требования - [Floating UI](https://floating-ui.com) ## Подключение и настройка ### HTML ```html ``` ### JS #### Минимальные настройки ```js import { createTooltip } from '@advdominion/tooltip'; createTooltip(document.querySelector('button'), 'Подсказка'); ``` #### Все настройки со значениями по умолчанию ```js import { createTooltip } from '@advdominion/tooltip'; createTooltip(document.querySelector('button'), 'Подсказка', { animation: [ [{ opacity: 0 }, { opacity: 1 }], [{ opacity: 1 }, { opacity: 0 }], ], appendTo: document.body, arrow: { active: true, centered: false, padding: undefined }, delay: [0, 0], duration: [0, 0], easing: ['linear', 'linear'], flipPadding: 0, hideOnClick: true, interactive: true, offset: [0, 8], placement: 'top', shiftPadding: [8, 0], theme: 'light', trigger: 'mouseenter click', virtualReference: undefined, zIndex: '', // Callback-функции, по умолчанию не заданы onCreate(instance) {}, onMount(instance) {}, onShow(instance) {}, onShown(instance) {}, onHide(instance) {}, onHidden(instance) {}, }); ``` Любую настройку можно задать через data-атрибут: имя опции в kebab-case с префиксом `data-tooltip-`. Значение парсится как JSON, а если разобрать не удалось — используется как строка. ```html ``` #### animation Две последовательности keyframes для `Element.animate`: первая проигрывается при появлении, вторая — при скрытии. ```js createTooltip(document.querySelector('button'), 'Подсказка', { animation: [ [ { opacity: 0, transform: 'translateY(-5px)' }, { opacity: 1, transform: 'translateY(0)' }, ], [ { opacity: 1, transform: 'translateY(0)' }, { opacity: 0, transform: 'translateY(-5px)' }, ], ], }); ``` #### appendTo Элемент, в который вставляется подсказка перед показом. По умолчанию `document.body`. Значение `'parent'` вставляет подсказку в родителя опорного элемента — это нужно, когда её обрезает или перекрывает контейнер. #### arrow Настройка отображения и позиционирования стрелки. Поддерживает булево значение (`true`/`false`) для обратной совместимости либо объект: - `active` (`true`) — показывать ли стрелку. Эквивалент `arrow: true`/`arrow: false`. - `centered` (`false`) — фиксировать стрелку по центру всплывающей подсказки, вместо того чтобы следовать за центром элемента, который её вызывает. Полезно, когда подсказка прижата к краю области видимости и стрелка смещается при прокрутке. - `padding` (`undefined`) — отступ стрелки от краёв всплывающей подсказки. По умолчанию рассчитывается автоматически исходя из размера стрелки, чтобы её повёрнутые под 45° углы не выходили за границы подсказки. ```js createTooltip(document.querySelector('button'), 'Подсказка', { arrow: { active: true, centered: true }, }); ``` #### delay Задержка перед появлением и перед скрытием в миллисекундах: `[появление, скрытие]`. Методы `show({ immediately: true })` и `hide({ immediately: true })` отключают задержку и анимацию. #### duration Длительность анимации появления и скрытия в миллисекундах: `[появление, скрытие]`. #### easing Функция плавности анимации появления и скрытия: `[появление, скрытие]`. Принимает значения CSS, например `ease-out` или `cubic-bezier(0.4, 0, 0.2, 1)`. #### flipPadding Минимальный зазор между подсказкой и краем области видимости, при котором подсказка переворачивается на противоположную сторону. По умолчанию `0`: переворот происходит, только если подсказка не помещается целиком. Переворот наступает, когда подсказка, её зазор `offset` и `flipPadding` вместе не помещаются с выбранной стороны. Например, при `flipPadding: 60` подсказка над элементом перевернётся вниз, если сверху останется меньше 60 px свободного места. Значение передаётся в middleware `flip` из Floating UI: число либо объект со сторонами `top`, `right`, `bottom`, `left`. ```js createTooltip(document.querySelector('button'), 'Подсказка', { flipPadding: 60, }); ``` Так же настраивается через data-атрибут: ```html ``` #### hideOnClick - `true` (по умолчанию) — всплывающая подсказка скрывается при клике по любому элементу на странице (**кроме** самой всплывающей подсказки). - `'all'` — всплывающая подсказка скрывается при клике по любому элементу на странице (**включая** саму всплывающую подсказку). - `'toggle'` — всплывающая подсказка скрывается только при клике по элементу, который её вызывает. Настройка работает только с `trigger`, включающим `click` или `manual`. #### interactive `true` (по умолчанию) — курсор можно перевести с элемента на подсказку и взаимодействовать с её содержимым. Невидимая зона перекрывает зазор `offset` между элементом и подсказкой, чтобы подсказка не скрылась по пути курсора. `false` — подсказка скрывается сразу, как только курсор уходит с элемента. #### offset Зазор между элементом и подсказкой: `[поперёк основной оси, вдоль основной оси]`. Для `top` и `bottom` первое значение сдвигает подсказку по горизонтали, второе задаёт зазор по вертикали. По умолчанию `[0, 8]` — 8 px между элементом и подсказкой. #### placement Сторона размещения: `top`, `right`, `bottom`, `left`. Выравнивание задаётся суффиксом `-start` или `-end`, например `bottom-start`. Если места с выбранной стороны не хватает, подсказка переворачивается (см. `flipPadding`). #### shiftPadding Отступ от края области видимости, на который подсказка сдвигается вдоль оси, чтобы полностью поместиться на экране: `[по горизонтали, по вертикали]`. Для `top` и `bottom` работает по горизонтали, для `left` и `right` — по вертикали. По умолчанию `[8, 0]`. Пример с отступом 12 px от краёв экрана на мобильных: ```js createTooltip(document.querySelector('button'), 'Подсказка', { shiftPadding: [12, 0], }); ``` #### theme Тема оформления. Значение подставляется в класс `tooltip_theme_` — стили для каждой темы задаёт потребитель. По умолчанию `light`. #### trigger События, по которым показывается и скрывается подсказка: строка со списком через пробел. По умолчанию `mouseenter click`. - `mouseenter` — по наведению курсора (только мышь); - `click` — по клику; - `focus` — по получению фокуса; - `blur` — скрытие по потере фокуса; - `manual` — без обработчиков: показ и скрытие только через `show()` и `hide()`. ```js createTooltip(document.querySelector('button'), 'Подсказка', { trigger: 'click', }); ``` #### virtualReference Настройка используется для кастомного позиционирования, ожидает объект с методом `getBoundingClientRect`. Например, позиционирование всплывающей подсказки относительно виртуального элемента размером 100×50, который располагается в левой верхней точке экрана: ```js createTooltip(document.querySelector('button'), 'Подсказка', { virtualReference: { getBoundingClientRect() { return { x: 0, y: 0, top: 0, left: 0, bottom: 50, right: 100, width: 100, height: 50, }; }, }, }); ``` #### zIndex Значение для свойства `z-index` подсказки. По умолчанию пустая строка — `z-index` не задаётся, работает значение из CSS. #### Колбэки Каждый колбэк получает экземпляр подсказки (`instance` — то же, что `$el._tooltip`). - `onCreate` — после создания экземпляра, до первого показа. Здесь уже доступны `show()` и `hide()`. - `onMount` — при первом показе, после создания DOM подсказки и до её вставки в документ. Удобно для инициализации вложенных компонентов. - `onShow` — после вставки в документ, перед анимацией появления. - `onShown` — после анимации появления. - `onHide` — перед анимацией скрытия. - `onHidden` — после анимации скрытия, когда подсказка уже удалена из документа. ### Свойства #### $tooltip DOM-элемент всплывающей подсказки (имеет свойство `_reference` для доступа к элементу, на котором был вызван `createTooltip`) #### options Текущие настройки #### isVisible Видимость всплывающей подсказки - `true`/`false` ### Методы #### show ```js document.querySelector('button')._tooltip.show(); ``` #### hide ```js document.querySelector('button')._tooltip.hide(); ``` #### setContent ```js document.querySelector('button')._tooltip.setContent('Новая подсказка'); ``` #### updateOptions ```js document.querySelector('button')._tooltip.updateOptions({ placement: 'bottom' }); ``` #### destroy ```js document.querySelector('button')._tooltip.destroy(); ``` ### Стили ```scss $b: '.tooltip'; #{$b} { left: 0; max-width: calc(100vw - 32px); position: absolute; top: 0; width: max-content; will-change: transform; z-index: 200; @media (min-width: 900px) { max-width: 300px; } &__root { } &__arrow { #{$b}_theme_light & { background-color: white; height: 8px; width: 8px; } } &__container { #{$b}_theme_light & { background-color: white; box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2); } } } ```