diff --git a/client/src/components/DraggableContainer.tsx b/client/src/components/DraggableContainer.tsx
index 23b2b34..f50da2d 100644
--- a/client/src/components/DraggableContainer.tsx
+++ b/client/src/components/DraggableContainer.tsx
@@ -1,4 +1,5 @@
import { useEffect, useRef, useState } from "react";
+import { flushSync } from "react-dom";
import type { ReactNode } from "react";
import clsx from "clsx";
@@ -282,11 +283,19 @@ export default function DraggableContainer({
setDragStartAlignment(getAlignmentClassesFromPosition(position));
}
- // Если контейнер был по центру с transform, убираем transform и используем абсолютную позицию
- if (position.transform) {
- setPosition({
- top: rect.top,
- left: rect.left,
+ // Конвертируем позицию в left/top перед началом драга
+ // Это нужно чтобы избежать скачка при переходе с right/bottom на left/top
+ // Используем flushSync для синхронного обновления DOM
+ if (
+ position.transform ||
+ position.right !== undefined ||
+ position.bottom !== undefined
+ ) {
+ flushSync(() => {
+ setPosition({
+ top: rect.top,
+ left: rect.left,
+ });
});
}
@@ -496,7 +505,7 @@ export default function DraggableContainer({
className={clsx(
"pointer-events-auto",
// draggable && "touch-none",
- !isDragging && "transition-all duration-500 ease-out",
+ !isDragging && enableSnapping && "transition-all duration-500 ease-out",
draggable &&
!dragHandleRef &&
(isDragging ? "cursor-grabbing" : "cursor-grab"),
diff --git a/client/src/components/ui/PopoverWrapper.tsx b/client/src/components/ui/PopoverWrapper.tsx
index 02503e6..b0da57a 100644
--- a/client/src/components/ui/PopoverWrapper.tsx
+++ b/client/src/components/ui/PopoverWrapper.tsx
@@ -1,4 +1,5 @@
import { useEffect, useState } from "react";
+import { createPortal } from "react-dom";
import { AnimatePresence, motion } from "motion/react";
import clsx from "clsx";
@@ -19,6 +20,7 @@ function PopoverWrapper({
}: PopoverProps) {
const [openUpwards, setOpenUpwards] = useState(false);
const [menuHeight, setMenuHeight] = useState(0);
+ const [, forceUpdate] = useState(0);
useEffect(() => {
if (
@@ -33,6 +35,26 @@ function PopoverWrapper({
}
}, [parentElRef, isOpened, menuHeight, position]);
+ // Обновляем позицию при изменении положения родительского элемента
+ useEffect(() => {
+ if (!isOpened) return;
+
+ let animationFrameId: number;
+
+ const updatePosition = () => {
+ forceUpdate((prev) => prev + 1);
+ animationFrameId = requestAnimationFrame(updatePosition);
+ };
+
+ animationFrameId = requestAnimationFrame(updatePosition);
+
+ return () => {
+ if (animationFrameId) {
+ cancelAnimationFrame(animationFrameId);
+ }
+ };
+ }, [isOpened]);
+
const getPositionStyles = () => {
if (!parentElRef.current) return {};
@@ -66,7 +88,7 @@ function PopoverWrapper({
};
};
- return (
+ return createPortal(