Floating UI предоставляет мощную архитектуру для управления позиционированием всплывающих элементов, таких как тултипы, поповеры и dropdown-меню. Ключевым аспектом является использование middleware — функций, которые изменяют или корректируют поведение позиции floating-элемента. Возможность комбинирования нескольких middleware позволяет создавать гибкие и предсказуемые интерфейсы.
Каждое middleware в Floating UI получает объект
state с текущими координатами (x,
y), размерами элементов (rects), а также
контекстом позиционирования. Middleware могут:
offset),flip),autoUpdate),shift).Каждое middleware возвращает объект с изменёнными координатами и, при необходимости, дополнительными данными.
Middleware выполняются последовательно в порядке объявления. Выходные данные одного middleware становятся входными для следующего. Это позволяет строить цепочки, например:
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
computePosition(reference, floating, {
middleware: [
offset(10),
flip(),
shift({ padding: 5 })
],
});
В этом примере происходит:
Порядок middleware критичен. Например, flip должен идти
после offset, чтобы корректно учитывать смещение при выборе
альтернативной позиции.
Floating UI поддерживает создание собственных middleware. Структура middleware обычно выглядит так:
function customMiddleware(options) {
return {
name: 'customMiddleware',
fn(state) {
const { x, y } = state;
// Пример: корректировка координат
return { x: x + (options.dx || 0), y: y + (options.dy || 0) };
}
};
}
computePosition(reference, floating, {
middleware: [
offset(5),
customMiddleware({ dx: 10, dy: -5 }),
flip()
],
});
Ключевой момент: middleware должны возвращать новый объект координат, иначе последующие middleware не будут корректно работать.
offset + shift offset изменяет
позицию элемента относительно reference, а shift
корректирует координаты, если элемент выходит за пределы видимой
области. Это позволяет реализовать динамические смещения с учётом
ограничений экрана.
flip + shift flip выбирает
оптимальную сторону для отображения floating-элемента. Если выбранная
сторона всё ещё выходит за пределы viewport, shift
корректирует позицию, чтобы элемент оставался видимым.
arrow + offset Middleware arrow
управляет положением стрелки относительно reference. В комбинации с
offset можно точно позиционировать стрелку независимо от
смещения всего floating-элемента.
autoUpdate с middleware цепочкой Функция
autoUpdate следит за изменением размеров и позиции
reference или floating-элемента, вызывая пересчёт цепочки middleware
автоматически. Это обеспечивает постоянное корректное позиционирование
при изменении окна или контента.
Некоторые middleware могут добавлять данные в
state.middlewareData, которые могут использоваться
последующими middleware. Например:
import { computePosition, shift, arrow } from '@floating-ui/dom';
computePosition(reference, floating, {
middleware: [
shift({ padding: 5 }),
arrow({ element: arrowElement, padding: 10 })
]
});
Здесь arrow использует информацию о сдвиге, созданную
shift, чтобы корректно разместить стрелку относительно
floating-элемента.
flip и shift.computePosition(reference, floating, {
middleware: [
offset({ mainAxis: 10, crossAxis: 5 }),
flip({ fallbackPlacements: ['top', 'bottom', 'right'] }),
shift({ padding: 8 }),
arrow({ element: arrowEl, padding: 5 }),
customMiddleware({ dx: 2, dy: -2 })
],
});
Такой подход обеспечивает:
Комбинирование middleware позволяет гибко управлять поведением floating-элементов, учитывая ограничения экрана, пользовательские смещения и точное позиционирование стрелок. Такой подход обеспечивает предсказуемое поведение UI-компонентов при любых сценариях взаимодействия.