Для работы с Popper.js в проекте на Svelte необходимо установить библиотеку через npm:
npm install @popperjs/core
После установки импортирование происходит стандартным образом:
import { createPopper } from '@popperjs/core';
Popper.js создаёт «попперы» — элементы, позиционирующиеся относительно других элементов (reference elements). В Svelte этот процесс удобно инкапсулировать в action.
В Svelte actions позволяют добавлять функциональность к DOM-элементам. Action для Popper.js можно оформить так:
// popper.js
import { createPopper } from '@popperjs/core';
export function popper(node, options) {
let popperInstance;
function init(reference) {
if (popperInstance) {
popperInstance.destroy();
}
popperInstance = createPopper(reference, node, options);
}
return {
upd ate(newOptions) {
if (popperInstance) {
popperInstance.setOptions(newOptions);
}
},
destroy() {
if (popperInstance) {
popperInstance.destroy();
}
},
init
};
}
Пояснение ключевых моментов:
node — это DOM-элемент, к которому применяется action,
обычно сам popper.options — конфигурация Popper.js, включает
placement, modifiers и прочее.init позволяет привязать popper к reference
элементу динамически.update обеспечивает возможность обновления параметров
после инициализации.destroy корректно удаляет Popper.js при размонтировании
компонента.<script>
import { popper } from './popper.js';
import { onMount } from 'svelte';
let referenceButton;
let tooltip;
let popperAction;
onMount(() => {
popperAction.init(referenceButton);
});
</script>
<button bind:this={referenceButton}>Наведи на меня</button>
<div
bind:this={tooltip}
use:popper={{ placement: 'top', modifiers: [{ name: 'offset', options: { offset: [0, 8] } }] }}
style="background: #333; color: #fff; padding: 4px 8px; border-radius: 4px;"
>
Подсказка
</div>
Особенности:
bind:this позволяет получить прямую ссылку на
DOM-элемент.use:popper.placement или modifiers
action автоматически обновит Popper.js.Popper.js поддерживает гибкую систему modifiers, позволяющую изменять поведение и позиционирование:
use:popper={{
placement: 'right',
modifiers: [
{
name: 'offset',
options: { offset: [10, 20] } // сдвиг по X и Y
},
{
name: 'flip',
options: { fallbackPlacements: ['top', 'bottom'] } // альтернативные позиции при переполнении
},
{
name: 'preventOverflow',
options: { padding: 8 } // защита от выхода за границы окна
}
]
}}
Ключевые модификаторы:
offset — смещение относительно reference элемента.flip — автоматический выбор подходящего положения при
нехватке места.preventOverflow — предотвращает выход поппера за
видимую область.В Svelte popper можно обновлять при изменении размеров или состояния компонента:
$: if (someCondition) {
popperAction.update({
placement: 'bottom',
modifiers: [{ name: 'offset', options: { offset: [0, 12] } }]
});
}
$: реактивная метка Svelte, позволяющая обновлять
Popper.js при изменении переменной.update корректно применяет новые параметры без
пересоздания поппера.Popper.js нужно корректно удалять при размонтировании компонента.
Action Svelte автоматически вызывает destroy:
<div use:popper={{ placement: 'left' }}>
Контент
</div>
При удалении DOM-узла Popper.js завершает работу, освобождая ресурсы.
Svelte предоставляет встроенные transition и animation для элементов. Попперы совместимы с ними:
<div
use:popper={{ placement: 'top' }}
transition:fade={{ duration: 200 }}
>
Подсказка
</div>
fade не мешает корректной позиции
Popper.js.placement
для плавных эффектов.Action позволяет создавать несколько popper-элементов с разными reference:
{#each items as item}
<button bind:this={item.ref}>{item.label}</button>
<div
bind:this={item.popper}
use:popper={{ placement: 'bottom' }}
>
{item.tooltip}
</div>
{/each}
createPopper.popperAction для
управления отдельными экземплярами.Svelte store можно использовать для управления видимостью и положением поппера:
<script>
import { writable } from 'svelte/store';
let showTooltip = writable(false);
</script>
<button on:mouseenter={() => showTooltip.se t(true)}
on:mouseleave={() => showTooltip.set(false)}>
Наведи на меня
</button>
{#if $showTooltip}
<div use:popper={{ placement: 'top' }}>Подсказка</div>
{/if}
Эти методы обеспечивают полную интеграцию Popper.js с Svelte, сохраняя реактивность, поддержку динамических изменений и правильное управление жизненным циклом компонентов.