diff --git a/components/chat/ChatItem.tsx b/components/chat/ChatItem.tsx index 5803779..20f8b97 100644 --- a/components/chat/ChatItem.tsx +++ b/components/chat/ChatItem.tsx @@ -83,6 +83,7 @@ export function ChatItem({ ? `/api/dm/messages/${message.id}` : `/api/messages/${message.id}`; + /** Closes the profile popover when clicking outside or pressing the Escape key. */ useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( @@ -93,14 +94,24 @@ export function ChatItem({ } }; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + setIsProfileOpen(false); + } + }; + if (isProfileOpen) { document.addEventListener("mousedown", handleClickOutside); + document.addEventListener("keydown", handleKeyDown); } + return () => { document.removeEventListener("mousedown", handleClickOutside); + document.removeEventListener("keydown", handleKeyDown); }; }, [isProfileOpen]); + /** Determines the friendship status between the current user and the message author. */ const getFriendshipStatus = () => { if ( !user?.id || diff --git a/components/ui/UserProfilePopover.tsx b/components/ui/UserProfilePopover.tsx index 829ed65..e7ebb77 100644 --- a/components/ui/UserProfilePopover.tsx +++ b/components/ui/UserProfilePopover.tsx @@ -40,25 +40,30 @@ export function UserProfilePopover({ const [justSent, setJustSent] = useState(false); const isSelf = user.id === currentUserId; - const isAlreadyFriend = friendshipStatus === "ACCEPTED"; const isPending = friendshipStatus === "PENDING" || justSent; const isButtonDisabled = isLoading || isAlreadyFriend || isPending; + /** Precise positioning with Y- and X-axis corrections. */ useLayoutEffect(() => { if (!triggerRef.current || !popoverRef.current) return; const triggerRect = triggerRef.current.getBoundingClientRect(); const popoverRect = popoverRef.current.getBoundingClientRect(); const viewportHeight = window.innerHeight; + const viewportWidth = window.innerWidth; let top = triggerRect.bottom + 8; - const left = triggerRect.left; + let left = triggerRect.left; if (top + popoverRect.height > viewportHeight - 16) { top = triggerRect.top - popoverRect.height - 8; } + if (left + popoverRect.width > viewportWidth - 16) { + left = viewportWidth - popoverRect.width - 16; + } + setCoords({ top, left }); setIsVisible(true); }, [triggerRef]); @@ -89,7 +94,7 @@ export function UserProfilePopover({ }} className="z-50 w-64 bg-background border border-surface/80 rounded-2xl p-4 shadow-2xl transition-opacity duration-75 pointer-events-auto" > -
+