Анимации открытия и закрытия

Chakra UI предоставляет удобные инструменты для создания анимаций открытия и закрытия компонентов, основанные на встроенном хукe useDisclosure и компонентах с поддержкой motion. Основной подход заключается в управлении состоянием видимости и плавном переходе между состояниями enter и exit с помощью свойства motion или оберток типа Collapse и ScaleFade.

useDisclosure для управления состоянием

Хук useDisclosure является базовым инструментом для контроля открытия и закрытия элементов. Он возвращает объект со следующими свойствами:

  • isOpen — булево значение, определяющее видимость компонента.
  • onOpen — функция для открытия.
  • onClose — функция для закрытия.
  • onToggle — функция для переключения состояния.

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

import { useDisclosure, Button, Box } from "@chakra-ui/react";

function Example() {
  const { isOpen, onToggle } = useDisclosure();

  return (
    <>
      <Button onCl ick={onToggle}>Toggle Box</Button>
      {isOpen && <Box p={5} bg="teal.200">Контент открыт</Box>}
    </>
  );
}

В этом примере компонент Box появляется и исчезает мгновенно. Для плавного эффекта используются компоненты анимации Chakra UI.


Компонент Collapse

Collapse позволяет анимировать высоту элемента при открытии и закрытии. Он особенно удобен для аккордеонов, меню и скрываемых блоков.

Ключевые свойства:

  • in — определяет, открыт ли компонент (true/false).
  • animateOpacity — если true, анимирует прозрачность вместе с высотой.
  • startingHeight — начальная высота до открытия.
  • endingHeight — высота после завершения анимации (по умолчанию auto).

Пример:

import { Collapse, Button, Box, useDisclosure } from "@chakra-ui/react";

function CollapseExample() {
  const { isOpen, onToggle } = useDisclosure();

  return (
    <>
      <Button onCl ick={onToggle}>Показать/Скрыть</Button>
      <Collapse in={isOpen} animateOpacity>
        <Box
          p="40px"
          mt="4"
          bg="teal.100"
          rounded="md"
          shadow="md"
        >
          Контент с анимацией высоты
        </Box>
      </Collapse>
    </>
  );
}

При нажатии кнопки высота блока плавно изменяется, создавая эффект раскрытия.


Компонент ScaleFade

ScaleFade сочетает масштабирование и изменение прозрачности. Подходит для модальных окон, всплывающих подсказок и других элементов, требующих плавного появления.

Основные свойства:

  • initialScale — масштаб при начальном состоянии.
  • in — состояние видимости.
  • unmountOnExit — удаляет компонент из DOM после закрытия, если true.

Пример:

import { ScaleFade, Button, Box, useDisclosure } from "@chakra-ui/react";

function ScaleFadeExample() {
  const { isOpen, onToggle } = useDisclosure();

  return (
    <>
      <Button onCl ick={onToggle}>Показать/Скрыть</Button>
      <ScaleFade initialScale={0.9} in={isOpen}>
        <Box
          p="40px"
          mt="4"
          bg="pink.100"
          rounded="md"
          shadow="md"
        >
          Плавное появление с масштабированием
        </Box>
      </ScaleFade>
    </>
  );
}

Компонент Fade

Fade обеспечивает простое плавное появление и исчезновение через прозрачность, без изменения размеров. Используется для ненавязчивых всплывающих эффектов.

Пример:

import { Fade, Button, Box, useDisclosure } from "@chakra-ui/react";

function FadeExample() {
  const { isOpen, onToggle } = useDisclosure();

  return (
    <>
      <Button onCl ick={onToggle}>Toggle Fade</Button>
      <Fade in={isOpen}>
        <Box
          p="40px"
          mt="4"
          bg="blue.100"
          rounded="md"
          shadow="md"
        >
          Плавное появление через прозрачность
        </Box>
      </Fade>
    </>
  );
}

Комбинирование анимаций

Для более сложных эффектов можно комбинировать компоненты анимации. Например, обернуть Collapse в Fade или ScaleFade, создавая одновременное изменение высоты и прозрачности.

Пример комбинированного эффекта:

import { Collapse, Fade, Button, Box, useDisclosure } from "@chakra-ui/react";

function CombinedExample() {
  const { isOpen, onToggle } = useDisclosure();

  return (
    <>
      <Button onCl ick={onToggle}>Toggle Combined</Button>
      <Fade in={isOpen}>
        <Collapse in={isOpen} animateOpacity>
          <Box
            p="40px"
            mt="4"
            bg="green.100"
            rounded="md"
            shadow="md"
          >
            Комбинированная анимация высоты и прозрачности
          </Box>
        </Collapse>
      </Fade>
    </>
  );
}

Анимация с Motion через Framer Motion

Chakra UI интегрируется с framer-motion, что позволяет создавать кастомные анимации. Для этого используется компонент motion:

import { motion } from "framer-motion";
import { Box, Button, useDisclosure } from "@chakra-ui/react";

const MotionBox = motion(Box);

function MotionExample() {
  const { isOpen, onToggle } = useDisclosure();

  return (
    <>
      <Button onCl ick={onToggle}>Toggle Motion</Button>
      <MotionBox
        p="40px"
        mt="4"
        bg="purple.100"
        rounded="md"
        shadow="md"
        initial={{ opacity: 0, y: -20 }}
        animate={{ opacity: isOpen ? 1 : 0, y: isOpen ? 0 : -20 }}
        transition={{ duration: 0.5 }}
      >
        Анимация через framer-motion
      </MotionBox>
    </>
  );
}

MotionBox позволяет полностью управлять свойствами анимации: прозрачностью, позицией, масштабом и временем перехода.


Важные рекомендации

  • Для элементов, которые полностью скрываются, рекомендуется использовать unmountOnExit, чтобы избежать рендеринга скрытых компонентов.
  • Свойство animateOpacity помогает добиться более мягкого визуального эффекта при изменении размеров блока.
  • Комбинирование анимаций делает интерфейс динамичным, но следует избегать слишком сложных последовательностей, чтобы не перегружать пользователя.
  • Интеграция с framer-motion позволяет создавать уникальные переходы, которых нет в стандартных компонентах Chakra UI, обеспечивая полный контроль над движением.

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