Задержки открытия и закрытия

В Radix UI взаимодействие с компонентами, такими как DropdownMenu, Popover, Tooltip и HoverCard, часто требует тонкой настройки поведения при наведении или клике. Одним из ключевых аспектов UX является задержка открытия и закрытия компонентов, чтобы избежать резких или случайных действий пользователя.


Основные свойства для управления задержками

Radix UI предоставляет встроенные пропсы для управления задержками:

  • delayDuration — задает время задержки перед открытием компонента.
  • closeDelay — устанавливает время задержки перед закрытием компонента (доступно не для всех компонентов, часто используется через onOpenChange с таймером).
  • disableOutsidePointerEvents — иногда используется совместно с задержками, чтобы блокировать клики вне компонента до его закрытия.

Пример на Popover:

import * as Popover from '@radix-ui/react-popover';

<Popover.Root>
  <Popover.Trigger>Открыть попап</Popover.Trigger>
  <Popover.Content
    sideOffset={5}
    align="start"
    onOpenAutoFo cus={(event) => event.preventDefault()}
    delayDuration={300} // Задержка перед открытием 300мс
  >
    Контент попапа с задержкой открытия
  </Popover.Content>
</Popover.Root>

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


Задержка закрытия через управление состоянием

Radix UI не всегда предоставляет отдельный проп closeDelay, поэтому закрытие с задержкой реализуется через управление состоянием компонента:

import { useState, useEffect } from 'react';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';

function DelayedDropdown() {
  const [open, setOpen] = useState(false);
  const [delayedClose, setDelayedClose] = useState(null);

  const handleOpenChange = (isOpen) => {
    if (!isOpen) {
      const timer = setTimeout(() => setOpen(false), 500); // Задержка закрытия 500мс
      setDelayedClose(timer);
    } else {
      clearTimeout(delayedClose);
      setOpen(true);
    }
  };

  return (
    <DropdownMenu.Root open={open} onOpenCha nge={handleOpenChange}>
      <DropdownMenu.Trigger>Меню</DropdownMenu.Trigger>
      <DropdownMenu.Content>
        <DropdownMenu.Item>Элемент 1</DropdownMenu.Item>
        <DropdownMenu.Item>Элемент 2</DropdownMenu.Item>
      </DropdownMenu.Content>
    </DropdownMenu.Root>
  );
}

Пояснение:

  • При закрытии устанавливается таймер, чтобы компонент не исчез мгновенно.
  • Если пользователь снова открыл компонент, таймер очищается.
  • Это обеспечивает плавное поведение и предотвращает «мерцание» элементов.

Особенности HoverCard и Tooltip

Для компонентов, реагирующих на наведение курсора, задержки особенно важны:

import * as HoverCard from '@radix-ui/react-hover-card';

<HoverCard.Root openDelay={400} closeDelay={200}>
  <HoverCard.Trigger>Наведи курсор</HoverCard.Trigger>
  <HoverCard.Content>
    Информация с задержкой открытия 400мс и закрытия 200мс
  </HoverCard.Content>
</HoverCard.Root>

Ключевые моменты:

  • openDelay — задержка перед открытием при наведении.
  • closeDelay — задержка перед закрытием после ухода курсора.
  • Значения задаются в миллисекундах, позволяя тонко подстраивать UX.

Совместное использование анимаций и задержек

Часто задержки сочетаются с анимациями появления и исчезновения:

import { keyframes, styled } from '@stitches/react';

const fadeIn = keyframes({
  from: { opacity: 0 },
  to: { opacity: 1 }
});

const fadeOut = keyframes({
  from: { opacity: 1 },
  to: { opacity: 0 }
});

const AnimatedContent = styled(HoverCard.Content, {
  animation: `${fadeIn} 0.3s`,
  '&[data-state="closed"]': {
    animation: `${fadeOut} 0.3s`
  }
});

Особенности интеграции:

  • Компоненты Radix UI используют атрибут data-state для управления состояниями.
  • Анимации должны учитывать задержку открытия/закрытия, чтобы эффект выглядел естественно и плавно.

Практические рекомендации

  1. Согласованность задержек: для всех интерактивных компонентов на странице лучше использовать одинаковые значения открытие/закрытие.
  2. Минимизация случайных открытий: особенно актуально для HoverCard и Tooltip.
  3. Комбинация с анимациями: задержка должна быть равна или больше длительности анимации открытия, чтобы не возникало «разрывов».
  4. Контроль через состояние: для сложных сценариев, таких как меню с вложенными элементами, рекомендуется полностью управлять открытием через useState и таймеры.

Задержки открытия и закрытия в Radix UI обеспечивают плавность, предсказуемость и улучшенный пользовательский опыт, особенно для компонентов с наведением или вложенной навигацией. Их гибкая настройка через пропсы и управление состоянием позволяет реализовать как простые, так и сложные сценарии поведения интерфейса.