ui fixes yo

This commit is contained in:
Arkaprabha Chakraborty
2025-11-01 02:41:23 +05:30
parent 8e4dfe5c87
commit 0ad067efb2
3 changed files with 83 additions and 67 deletions

View File

@@ -236,56 +236,70 @@ const Room = () => {
return () => window.removeEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile);
}, []); }, []);
// Mobile swipe gesture handling // Mobile swipe gesture handling & Escape key to close panels
useEffect(() => { useEffect(() => {
if (!isMobile) return; // Swipe gesture (mobile only)
if (isMobile) {
let touchStartX = 0;
let touchStartY = 0;
let touchStartTime = 0;
let touchStartX = 0; const handleTouchStart = (e: TouchEvent) => {
let touchStartY = 0; const touch = e.touches[0];
let touchStartTime = 0; touchStartX = touch.clientX;
touchStartY = touch.clientY;
touchStartTime = Date.now();
};
const handleTouchStart = (e: TouchEvent) => { const handleTouchEnd = (e: TouchEvent) => {
const touch = e.touches[0]; const touch = e.changedTouches[0];
touchStartX = touch.clientX; const touchEndX = touch.clientX;
touchStartY = touch.clientY; const touchEndY = touch.clientY;
touchStartTime = Date.now(); const touchEndTime = Date.now();
};
const handleTouchEnd = (e: TouchEvent) => { const deltaX = touchEndX - touchStartX;
const touch = e.changedTouches[0]; const deltaY = touchEndY - touchStartY;
const touchEndX = touch.clientX; const deltaTime = touchEndTime - touchStartTime;
const touchEndY = touch.clientY;
const touchEndTime = Date.now();
const deltaX = touchEndX - touchStartX; // Only consider it a swipe if:
const deltaY = touchEndY - touchStartY; // 1. The gesture is fast enough (less than 500ms)
const deltaTime = touchEndTime - touchStartTime; // 2. The horizontal distance is significant (at least 100px)
// 3. The vertical distance is less than horizontal (to avoid conflicting with scrolling)
// Only consider it a swipe if: if (
// 1. The gesture is fast enough (less than 500ms) deltaTime < 500 &&
// 2. The horizontal distance is significant (at least 100px) Math.abs(deltaX) > 100 &&
// 3. The vertical distance is less than horizontal (to avoid conflicting with scrolling) Math.abs(deltaX) > Math.abs(deltaY)
if ( ) {
deltaTime < 500 && if (deltaX < 0 && leftPanelForced) {
Math.abs(deltaX) > 100 && // Swipe left - close left panel
Math.abs(deltaX) > Math.abs(deltaY) setLeftPanelForced(false);
) { } else if (deltaX > 0 && rightPanelForced) {
if (deltaX < 0 && leftPanelForced) { // Swipe right - close right panel
// Swipe left - close left panel setRightPanelForced(false);
setLeftPanelForced(false); }
} else if (deltaX > 0 && rightPanelForced) {
// Swipe right - close right panel
setRightPanelForced(false);
} }
};
document.addEventListener('touchstart', handleTouchStart, { passive: true });
document.addEventListener('touchend', handleTouchEnd, { passive: true });
// Clean up swipe listeners
return () => {
document.removeEventListener('touchstart', handleTouchStart);
document.removeEventListener('touchend', handleTouchEnd);
};
}
// Escape key closes panels (all devices)
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
if (leftPanelForced) setLeftPanelForced(false);
if (rightPanelForced) setRightPanelForced(false);
} }
}; };
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('touchstart', handleTouchStart, { passive: true });
document.addEventListener('touchend', handleTouchEnd, { passive: true });
return () => { return () => {
document.removeEventListener('touchstart', handleTouchStart); document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('touchend', handleTouchEnd);
}; };
}, [isMobile, leftPanelForced, rightPanelForced]); }, [isMobile, leftPanelForced, rightPanelForced]);
@@ -324,19 +338,19 @@ const Room = () => {
// Calculate panel visibility based on window width // Calculate panel visibility based on window width
// Minimum width needed: 320px (left) + 640px (main content) + 320px (right) = 1280px // Minimum width needed: 320px (left) + 640px (main content) + 320px (right) = 1280px
const shouldShowPanels = windowWidth >= 1280; const showSidePanels = windowWidth >= 1280;
// Auto-hide forced panels when screen size increases (do this before calculating visibility) // Auto-hide forced panels when screen size increases (do this before calculating visibility)
useEffect(() => { useEffect(() => {
if (shouldShowPanels) { if (showSidePanels) {
setLeftPanelForced(false); setLeftPanelForced(false);
setRightPanelForced(false); setRightPanelForced(false);
} }
}, [shouldShowPanels]); }, [showSidePanels]);
// Calculate final panel visibility - when shouldShowPanels is true, always show panels regardless of forced state // Calculate final panel visibility - when shouldShowPanels is true, always show panels regardless of forced state
const showLeftPanel = shouldShowPanels || (!shouldShowPanels && leftPanelForced); const showLeftPanel = showSidePanels || (!showSidePanels && leftPanelForced);
const showRightPanel = shouldShowPanels || (!shouldShowPanels && rightPanelForced); const showRightPanel = showSidePanels || (!showSidePanels && rightPanelForced);
// Initialize theme from cookie // Initialize theme from cookie
useEffect(() => { useEffect(() => {
@@ -809,7 +823,7 @@ const Room = () => {
share share
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-popover-foreground bg-popover text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-popover-foreground bg-popover text-xs border-foreground">
copy link to this page copy link to this page
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
@@ -823,7 +837,7 @@ const Room = () => {
purge purge
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-popover-foreground bg-popover text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-popover-foreground bg-popover text-xs border-foreground">
permanently delete this room and all its contents permanently delete this room and all its contents
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
@@ -837,7 +851,7 @@ const Room = () => {
exit exit
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-popover-foreground bg-popover text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-popover-foreground bg-popover text-xs border-foreground">
return to home return to home
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
@@ -855,7 +869,7 @@ const Room = () => {
upload upload
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground">
upload files upload files
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
@@ -873,13 +887,13 @@ const Room = () => {
theme theme
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground">
{getThemeById(currentThemeId)?.name || "Switch theme"} {getThemeById(currentThemeId)?.name || "Switch theme"}
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
{/* Mobile Panel Controls */} {/* Panel Controls for mobile and when panels are hidden due to width */}
{isMobile && ( {(isMobile || !showSidePanels) && (
<> <>
<HoverCard> <HoverCard>
<HoverCardTrigger> <HoverCardTrigger>
@@ -890,7 +904,7 @@ const Room = () => {
media media
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground z-[999]">
toggle users & media panel toggle users & media panel
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
@@ -903,7 +917,7 @@ const Room = () => {
notes notes
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground z-50"> <HoverCardContent className="py-1 px-2 w-auto text-xs border-foreground">
toggle comments panel toggle comments panel
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
@@ -983,7 +997,7 @@ const Room = () => {
)} )}
{/* Overlay for mobile when panels are forced open */} {/* Overlay for mobile when panels are forced open */}
{!shouldShowPanels && (leftPanelForced || rightPanelForced) && ( {!showSidePanels && (leftPanelForced || rightPanelForced) && (
<div <div
className="fixed inset-0 bg-black/20 z-30" className="fixed inset-0 bg-black/20 z-30"
onClick={() => { onClick={() => {

View File

@@ -149,7 +149,7 @@ export const CodeEditor = forwardRef<CodeEditorRef, CodeEditorProps>(({
}, [themeConfig, editorReady]); }, [themeConfig, editorReady]);
return ( return (
<div className={`border border-border overflow-hidden ${className}`}> <div className={`border border-border overflow-hidden ${className}`}>
<Editor <Editor
height="100%" height="100%"
language={language} language={language}

View File

@@ -13,16 +13,18 @@ const HoverCardContent = React.forwardRef<
React.ElementRef<typeof HoverCardPrimitive.Content>, React.ElementRef<typeof HoverCardPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content> React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<HoverCardPrimitive.Content <HoverCardPrimitive.Portal>
ref={ref} <HoverCardPrimitive.Content
align={align} ref={ref}
sideOffset={sideOffset} align={align}
className={cn( sideOffset={sideOffset}
"z-50 w-64 border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className={cn(
className "z-50 w-64 border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
)} className
{...props} )}
/> {...props}
/>
</HoverCardPrimitive.Portal>
)) ))
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName HoverCardContent.displayName = HoverCardPrimitive.Content.displayName