Floating UI — это библиотека для позиционирования всплывающих элементов относительно других элементов в веб-приложениях. Одной из ключевых особенностей является возможность интеграции с реактивными фреймворками (React, Vue, Solid и др.), что позволяет динамически обновлять позицию элементов при изменении состояния приложения. Центральным механизмом здесь являются refs — ссылки на DOM-узлы, используемые для вычисления позиции.
Refs в Floating UI служат для привязки элемент-всплывающее окно и элемент-опорный объект. Библиотека требует два обязательных ref:
Пример с React:
import { useFloating } from '@floating-ui/react-dom';
function Tooltip() {
const { x, y, reference, floating, strategy } = useFloating();
return (
<>
<button ref={reference}>Наведи на меня</button>
<div ref={floating} style={{ position: strategy, top: y ?? 0, left: x ?? 0 }}>
Всплывающая подсказка
</div>
</>
);
}
В этом примере reference и floating — это
функции, которые автоматически присваивают DOM-элементы внутренним
переменным Floating UI. Обратите внимание, что
x и y могут быть undefined до
момента первого расчета, поэтому важно использовать безопасные
fallback-значения.
Floating UI предоставляет реактивное API, которое позволяет отслеживать изменения размера или положения элементов и пересчитывать позицию. Основные подходы:
import { autoUpdate } from '@floating-ui/dom';
const cleanup = autoUpdate(referenceElement, floatingElement, updatePosition);
function updatePosition() {
computePosition(referenceElement, floatingElement, { placement: 'bottom' })
.then(({ x, y }) => {
Object.assign(floatingElement.style, {
left: `${x}px`,
top: `${y}px`,
});
});
}
x и y в React/Vue позволяет автоматически
пересчитывать стили при обновлении позиции.Для реактивных фреймворков refs интегрируются через ref
или createSignal. В Vue это выглядит так:
import { useFloating } from '@floating-ui/vue';
export default {
setup() {
const reference = ref(null);
const floating = ref(null);
const { x, y, strategy } = useFloating(reference, floating);
return { reference, floating, x, y, strategy };
},
};
В Solid подход аналогичен, но используется реактивная система сигналов:
import { createSignal } from 'solid-js';
import { useFloating } from '@floating-ui/solid';
const [reference, setReference] = createSignal(null);
const [floating, setFloating] = createSignal(null);
const { x, y, strategy } = useFloating(reference, floating);
reference или
floating не инициализированы, вычисления не выполняются.
Нужно проверять, что DOM-элементы существуют.autoUpdate для поддержания точной позиции.В реальных приложениях часто всплывающие элементы создаются динамически. Floating UI поддерживает позднее присваивание ref, что позволяет:
const reference = null;
const floating = null;
useEffect(() => {
if (reference && floating) {
computePosition(reference, floating, { placement: 'top' }).then(updateStyles);
}
}, [reference, floating]);
Такой подход гарантирует корректную позицию даже для элементов, которые рендерятся после загрузки страницы.
Refs и реактивность в Floating UI образуют ядро динамического
позиционирования. Правильная настройка reference и
floating, совместно с автообновлением позиции через
autoUpdate или реактивные состояния, обеспечивает
стабильную работу всплывающих элементов независимо от изменений DOM,
размеров окна и внутренних стейтов приложения. Этот подход универсален и
одинаково эффективен как в React, так и в Vue или Solid, обеспечивая
гибкое управление позиционированием в сложных интерфейсах.