Библиотека Tippy.js предоставляет гибкие способы задания содержимого всплывающих подсказок. Основные варианты:
Базовый пример с текстом:
tippy('#button', {
content: 'Простая подсказка'
});
Для отображения форматированного содержимого используется HTML. По
умолчанию HTML отключён из соображений безопасности, поэтому необходимо
явно разрешить его через опцию allowHTML.
tippy('#button', {
content: '<strong>Жирный текст</strong> и <em>курсив</em>',
allowHTML: true
});
Особенности:
Вместо строки можно передать уже существующий элемент:
const template = document.querySelector('#tooltip-template');
tippy('#button', {
content: template
});
Поведение:
Чтобы избежать этого, используется клонирование:
tippy('#button', {
content: template.cloneNode(true)
});
Функция позволяет генерировать содержимое на лету:
tippy('#button', {
content(reference) {
return `ID элемента: ${reference.id}`;
}
});
Аргумент reference — это элемент, к которому привязан
тултип.
tippy('.item', {
content(reference) {
return reference.getAttribute('data-info');
}
});
Tippy.js по умолчанию умеет брать содержимое из атрибута
data-tippy-content:
<button data-tippy-content="Подсказка">Наведи</button>
tippy('button');
Можно использовать другой атрибут:
tippy('button', {
content(reference) {
return reference.getAttribute('data-custom');
}
});
Для загрузки данных с сервера используется асинхронный подход:
tippy('#button', {
content: 'Загрузка...',
onShow(instance) {
fetch('/api/data')
.then(response => response.text())
.then(data => {
instance.setContent(data);
});
}
});
Ключевые моменты:
setContentМетод setContent позволяет менять текст тултипа
динамически:
const instance = tippy('#button', {
content: 'Старое значение'
});
instance.setContent('Новое значение');
Если используется делегирование:
tippy('#container', {
target: '.child',
content: 'Общее содержимое'
});
Обновление происходит через экземпляр:
instance.setContent('Обновлено');
Часто применяется скрытый HTML-шаблон:
<div id="tpl" style="display: none;">
<div class="tooltip-content">
<h4>Заголовок</h4>
<p>Описание</p>
</div>
</div>
tippy('#button', {
content: document.querySelector('#tpl').innerHTML,
allowHTML: true
});
Внутри тултипа могут находиться кнопки, формы и другие элементы:
tippy('#button', {
content: `
<button oncl ick="alert('Нажато')">Кнопка</button>
`,
allowHTML: true,
interactive: true
});
Опция interactive: true необходима, чтобы тултип не
закрывался при взаимодействии.
При использовании HTML важно учитывать:
import DOMPurify from 'dompurify';
tippy('#button', {
content: DOMPurify.sanitize(userInput),
allowHTML: true
});
Для оптимизации можно откладывать генерацию:
tippy('#button', {
content: '...',
onShow(instance) {
if (!instance._loaded) {
instance.setContent('Данные загружены');
instance._loaded = true;
}
}
});
tippy('.buttons', {
content(reference) {
return `Кнопка: ${reference.textContent}`;
}
});
Каждый элемент получает собственное содержимое.
Можно сочетать разные техники:
tippy('.item', {
allowHTML: true,
content(reference) {
const title = reference.getAttribute('data-title');
const desc = reference.getAttribute('data-desc');
return `
<strong>${title}</strong>
<div>${desc}</div>
`;
}
});
Через render API можно полностью контролировать DOM:
tippy('#button', {
render(instance) {
const popper = document.createElement('div');
popper.className = 'custom-tooltip';
const content = document.createElement('div');
content.className = 'content';
content.textContent = instance.props.content;
popper.appendChild(content);
return {
popper,
onUpdate(prevProps, nextProps) {
content.textContent = nextProps.content;
}
};
}
});
Событие onUpdate позволяет реагировать на изменения:
tippy('#button', {
content: 'Начало',
onUpdate(instance) {
console.log('Содержимое обновлено:', instance.props.content);
}
});
При необходимости можно преобразовывать Markdown:
import marked from 'marked';
tippy('#button', {
allowHTML: true,
content: marked('# Заголовок\n\nТекст')
});
onShow, а не пересоздавать тултипtippy('.user', {
allowHTML: true,
interactive: true,
content(reference) {
const name = reference.dataset.name;
const email = reference.dataset.email;
return `
<div class="user-card">
<strong>${name}</strong>
<div>${email}</div>
<button class="send">Написать</button>
</div>
`;
},
onShow(instance) {
const btn = instance.popper.querySelector('.send');
btn.addEventListener('click', () => {
alert('Сообщение отправлено');
});
}
});
Такой подход демонстрирует создание полноценных интерактивных карточек внутри тултипов с динамическими данными.