Управление видимостью

Floating UI — это библиотека для создания плавающих элементов интерфейса, таких как тултипы, всплывающие меню, поповеры и модальные окна, с гибким управлением положением и видимостью. Управление видимостью является ключевым аспектом при работе с динамическими интерфейсами, позволяя контролировать, когда элемент появляется и исчезает, а также как он взаимодействует с окружающими элементами.

Основные подходы к видимости

В Floating UI управление видимостью делится на несколько уровней:

  1. Состояние видимости (visible/hidden) Контроль состояния отображения осуществляется через стандартные свойства DOM: display, visibility, opacity. Обычно рекомендуется использовать комбинацию opacity и pointer-events, чтобы плавно анимировать появление элементов без нарушения интерактивности.

    const tooltip = document.querySelector('#tooltip');
    tooltip.style.opacity = '1'; // показать
    tooltip.style.pointerEvents = 'auto';
    
    tooltip.style.opacity = '0'; // скрыть
    tooltip.style.pointerEvents = 'none';
  2. Управление через состояние в JavaScript Часто состояние видимости хранится в переменной или реактивной структуре, например, в React или Vue. Это позволяет синхронизировать визуальное отображение с внутренней логикой приложения.

    const [isOpen, setIsOpen] = useState(false);
    
    return (
      <div>
        <button onCl ick={() => setIsOpen(!isOpen)}>Toggle</button>
        {isOpen && <FloatingElement>Содержимое</FloatingElement>}
      </div>
    );
  3. Использование Floating UI hooks и middleware Floating UI предоставляет хуки, такие как useFloating, для управления положением и видимостью. Middleware, например hide, позволяет автоматически скрывать элемент при выходе за пределы видимой области или пересечении с другим элементом.

    import { useFloating, offset, flip, shift, hide } from '@floating-ui/react-dom';
    
    const { x, y, reference, floating, strategy } = useFloating({
      middleware: [offset(10), flip(), shift(), hide()]
    });

События, управляющие видимостью

Для динамических интерфейсов критически важно корректно обрабатывать события пользователя:

  • hover — для тултипов и подсказок.
  • click — для раскрывающихся меню и поповеров.
  • focus/blur — для элементов формы и интерактивных полей.
  • scroll/resize — для автоматического скрытия элементов, вышедших за пределы видимости.
reference.addEventListener('mouseenter', () => {
  floating.style.opacity = '1';
});

reference.addEventListener('mouseleave', () => {
  floating.style.opacity = '0';
});

Анимация появления и скрытия

Плавные анимации создают ощущение живости интерфейса. Floating UI не навязывает конкретный способ анимации, поэтому рекомендуется использовать CSS-переходы или анимации с requestAnimationFrame.

.floating {
  transition: opacity 0.2s ease, transform 0.2s ease;
  transform: translateY(-5px);
  opacity: 0;
}

.floating.show {
  transform: translateY(0);
  opacity: 1;
}
floating.classList.add('show'); // показать
floating.classList.remove('show'); // скрыть

Автоматическое скрытие и условия видимости

Middleware hide позволяет автоматически управлять видимостью на основе позиции относительно viewport или reference-элемента. Можно комбинировать с кастомной логикой для сложных интерфейсов:

import { autoUpdate } from '@floating-ui/dom';

autoUpdate(reference, floating, () => {
  const rect = floating.getBoundingClientRect();
  if (rect.bottom < 0 || rect.top > window.innerHeight) {
    floating.style.opacity = '0';
  } else {
    floating.style.opacity = '1';
  }
});

Сочетание управления видимостью и позиции

Появление элемента часто связано с его позиционированием. Floating UI позволяет синхронизировать эти два аспекта через хуки и middleware:

  • offset — задает расстояние между reference и плавающим элементом.
  • flip — автоматически меняет сторону при недостатке места.
  • shift — корректирует положение при столкновении с границами контейнера.

Пример комбинированного использования:

const { x, y, reference, floating } = useFloating({
  placement: 'bottom',
  middleware: [offset(10), flip(), shift(), hide()]
});

return (
  <>
    <button ref={reference}>Hover me</button>
    <div ref={floating} style={{ position: 'absolute', top: y ?? 0, left: x ?? 0 }}>
      Плавающий элемент
    </div>
  </>
);

Советы по производительности

  • Не ререндерить плавающий элемент при каждом движении мыши; использовать throttling или requestAnimationFrame.
  • Минимизировать использование тяжелых middleware, если элемент часто появляется и исчезает.
  • Хранить состояние видимости вне рендера основного компонента, если требуется быстрый отклик.

Заключение по принципам

Управление видимостью в Floating UI строится на сочетании:

  • реактивного состояния,
  • событий пользовательского ввода,
  • middleware для автоматизации скрытия и корректировки позиции,
  • плавной анимации через CSS или JS.

Такой подход обеспечивает гибкое, отзывчивое и предсказуемое поведение интерфейсов, делая взаимодействие пользователя с элементами более естественным и удобным.