Changes
This commit is contained in:
+25
-5
@@ -1,4 +1,5 @@
|
|||||||
import { useState, useRef, useEffect } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { Send, Bot, User, Loader2, Trash2, AlertTriangle, Maximize2, Minimize2, ChevronDown, Settings } from 'lucide-react';
|
import { Send, Bot, User, Loader2, Trash2, AlertTriangle, Maximize2, Minimize2, ChevronDown, Settings } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -108,6 +109,18 @@ const AIChat = () => {
|
|||||||
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
|
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
|
||||||
const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();
|
const { enterFullscreen, exitFullscreen } = useBrowserFullscreen();
|
||||||
|
|
||||||
|
// Prevent page scroll while in fullscreen mode (portal overlays the viewport)
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof document === 'undefined') return;
|
||||||
|
if (!isFullscreen) return;
|
||||||
|
|
||||||
|
const prevOverflow = document.body.style.overflow;
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
return () => {
|
||||||
|
document.body.style.overflow = prevOverflow;
|
||||||
|
};
|
||||||
|
}, [isFullscreen]);
|
||||||
|
|
||||||
// Exit fullscreen on Escape key
|
// Exit fullscreen on Escape key
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleEscape = (e: KeyboardEvent) => {
|
const handleEscape = (e: KeyboardEvent) => {
|
||||||
@@ -382,16 +395,16 @@ const AIChat = () => {
|
|||||||
sendMessage();
|
sendMessage();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
const chatUi = (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className={`flex flex-col ${
|
className={
|
||||||
isFullscreen
|
isFullscreen
|
||||||
? 'fixed inset-0 z-50 bg-background p-2 sm:p-3 md:p-8 overflow-hidden w-screen h-screen'
|
? 'flex flex-col fixed inset-0 z-[100] bg-background p-2 sm:p-3 md:p-8 overflow-hidden w-screen h-screen'
|
||||||
: 'h-full'
|
: 'flex flex-col h-full'
|
||||||
}`}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between gap-2 mb-3 flex-shrink-0">
|
<div className="flex items-center justify-between gap-2 mb-3 flex-shrink-0">
|
||||||
<GlitchText
|
<GlitchText
|
||||||
@@ -698,6 +711,13 @@ const AIChat = () => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// IMPORTANT: MainLayout uses framer-motion transforms which create a containing block
|
||||||
|
// for `position: fixed` descendants, causing "fullscreen" to be clipped.
|
||||||
|
// Portaling to body guarantees true viewport fullscreen.
|
||||||
|
return isFullscreen && typeof document !== 'undefined'
|
||||||
|
? createPortal(chatUi, document.body)
|
||||||
|
: chatUi;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AIChat;
|
export default AIChat;
|
||||||
|
|||||||
Reference in New Issue
Block a user