Skip to content

Commit 3b5a590

Browse files
Update Modal.tsx (#84)
* Update Modal.tsx Make modal moveable so we can see the serial console if blocked. * Update Modal.tsx Moved modal initial position up higher and added a bit of transparency so you can kind of see that the cli is beyond in case you need to move the modal.
1 parent 680524e commit 3b5a590

File tree

1 file changed

+77
-9
lines changed

1 file changed

+77
-9
lines changed

src/components/Modal/Modal.tsx

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { faRectangleXmark } from "@fortawesome/free-solid-svg-icons";
22
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3-
import React, { useEffect } from "react";
3+
import React, { useEffect, useState, MouseEvent } from "react";
44
import { IModal } from "@/types";
55

66
const Modal = ({
@@ -12,37 +12,105 @@ const Modal = ({
1212
className,
1313
...props
1414
}: IModal) => {
15+
const [position, setPosition] = useState({ x: 0, y: 0 });
16+
const [isDragging, setIsDragging] = useState(false);
17+
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
18+
1519
useEffect(() => {
1620
if (isModalOpen) {
1721
document.body.style.overflow = "hidden";
1822
} else {
1923
document.body.style.overflow = "unset";
24+
setPosition({ x: 0, y: 0 });
2025
}
2126
}, [isModalOpen]);
27+
28+
const handleMouseDown = (e: MouseEvent) => {
29+
if (e.button !== 0) return;
30+
e.preventDefault();
31+
setIsDragging(true);
32+
setDragStart({
33+
x: e.clientX - position.x,
34+
y: e.clientY - position.y,
35+
});
36+
};
37+
38+
const handleMouseMove = (e: MouseEvent) => {
39+
if (!isDragging) return;
40+
e.preventDefault();
41+
requestAnimationFrame(() => {
42+
const newX = e.clientX - dragStart.x;
43+
const newY = e.clientY - dragStart.y;
44+
setPosition({ x: newX, y: newY });
45+
});
46+
};
47+
48+
const stopDragging = () => {
49+
setIsDragging(false);
50+
};
51+
52+
useEffect(() => {
53+
if (!isDragging) return;
54+
55+
const handleMouseUp = (e: MouseEvent) => {
56+
e.preventDefault();
57+
stopDragging();
58+
};
59+
60+
window.addEventListener("mousemove", handleMouseMove as any);
61+
window.addEventListener("mouseup", handleMouseUp as any);
62+
window.addEventListener("mouseleave", stopDragging);
63+
window.addEventListener("blur", stopDragging);
64+
window.addEventListener("keydown", stopDragging);
65+
66+
return () => {
67+
window.removeEventListener("mousemove", handleMouseMove as any);
68+
window.removeEventListener("mouseup", handleMouseUp as any);
69+
window.removeEventListener("mouseleave", stopDragging);
70+
window.removeEventListener("blur", stopDragging);
71+
window.removeEventListener("keydown", stopDragging);
72+
};
73+
}, [isDragging, dragStart.x, dragStart.y, position.x, position.y]);
74+
2275
return (
2376
<>
2477
{isModalOpen && (
25-
<div className="fixed inset-0 z-40 flex items-center justify-center">
78+
<div className="fixed inset-0 z-40 flex items-start justify-center pt-[5vh]">
2679
<div className="fixed inset-0 bg-black opacity-50"></div>
2780
<div
28-
className={`z-50 overflow-auto rounded-lg border border-gray-900 bg-gray-500 shadow-xl ${className}`}
81+
style={{
82+
transform: `translate(${position.x}px, ${position.y}px)`,
83+
cursor: isDragging ? "grabbing" : "grab",
84+
userSelect: "none",
85+
}}
86+
className={`z-50 mx-auto overflow-auto rounded-lg border border-gray-900 bg-gray-500/70 shadow-xl ${className}`}
2987
{...props}
3088
>
3189
{title && (
32-
<div className="flex gap-4 border-b border-gray-500 p-4">
33-
<button onClick={closeModal} className="pr-3">
90+
<div
91+
className="flex gap-4 border-b border-gray-500 p-4 cursor-grab select-none bg-gray-500"
92+
onMouseDown={handleMouseDown}
93+
onDragStart={(e) => e.preventDefault()}
94+
>
95+
<button
96+
onClick={closeModal}
97+
className="pr-3 bg-gray-500 hover:bg-gray-600"
98+
>
3499
<FontAwesomeIcon
35100
icon={faRectangleXmark}
36101
className="text-2xl text-white"
37102
/>
38103
</button>
39-
40-
<p>{title}</p>
104+
<p className="text-white">{title}</p>
41105
</div>
42106
)}
43-
<div className={`h-full w-full ${title && "p-4"}`}>{children}</div>
107+
<div className={`h-full w-full bg-gray-500/70 ${title && "p-4"}`}>
108+
{children}
109+
</div>
44110
{footer && (
45-
<div className="border-t border-gray-500 p-4">{footer}</div>
111+
<div className="border-t border-gray-500 p-4 bg-gray-500">
112+
{footer}
113+
</div>
46114
)}
47115
</div>
48116
</div>

0 commit comments

Comments
 (0)