made overflow be hidden on main

This commit is contained in:
Lucas Oliveira 2025-10-21 18:13:03 -03:00 committed by Mike Fortman
parent ba4bf9adc4
commit ae15ec8b36

View file

@ -4,8 +4,8 @@ import { motion } from "framer-motion";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { import {
type ChatConversation, type ChatConversation,
useGetConversationsQuery, useGetConversationsQuery,
} from "@/app/api/queries/useGetConversationsQuery"; } from "@/app/api/queries/useGetConversationsQuery";
import type { Settings } from "@/app/api/queries/useGetSettingsQuery"; import type { Settings } from "@/app/api/queries/useGetSettingsQuery";
import { OnboardingContent } from "@/app/new-onboarding/components/onboarding-content"; import { OnboardingContent } from "@/app/new-onboarding/components/onboarding-content";
@ -16,187 +16,187 @@ import { Navigation } from "@/components/navigation";
import { useAuth } from "@/contexts/auth-context"; import { useAuth } from "@/contexts/auth-context";
import { useChat } from "@/contexts/chat-context"; import { useChat } from "@/contexts/chat-context";
import { import {
ANIMATION_DURATION, ANIMATION_DURATION,
HEADER_HEIGHT, HEADER_HEIGHT,
ONBOARDING_STEP_KEY, ONBOARDING_STEP_KEY,
SIDEBAR_WIDTH, SIDEBAR_WIDTH,
TOTAL_ONBOARDING_STEPS, TOTAL_ONBOARDING_STEPS,
} from "@/lib/constants"; } from "@/lib/constants";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
export function ChatRenderer({ export function ChatRenderer({
settings, settings,
children, children,
}: { }: {
settings: Settings; settings: Settings;
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const pathname = usePathname(); const pathname = usePathname();
const { isAuthenticated, isNoAuthMode } = useAuth(); const { isAuthenticated, isNoAuthMode } = useAuth();
const { const {
endpoint, endpoint,
refreshTrigger, refreshTrigger,
refreshConversations, refreshConversations,
startNewConversation, startNewConversation,
} = useChat(); } = useChat();
// Initialize onboarding state based on local storage and settings // Initialize onboarding state based on local storage and settings
const [currentStep, setCurrentStep] = useState<number>(() => { const [currentStep, setCurrentStep] = useState<number>(() => {
if (typeof window === "undefined") return 0; if (typeof window === "undefined") return 0;
const savedStep = localStorage.getItem(ONBOARDING_STEP_KEY); const savedStep = localStorage.getItem(ONBOARDING_STEP_KEY);
return savedStep !== null ? parseInt(savedStep, 10) : 0; return savedStep !== null ? parseInt(savedStep, 10) : 0;
}); });
const [showLayout, setShowLayout] = useState<boolean>(() => { const [showLayout, setShowLayout] = useState<boolean>(() => {
if (typeof window === "undefined") return false; if (typeof window === "undefined") return false;
const savedStep = localStorage.getItem(ONBOARDING_STEP_KEY); const savedStep = localStorage.getItem(ONBOARDING_STEP_KEY);
// Show layout if settings.edited is true and if no onboarding step is saved // Show layout if settings.edited is true and if no onboarding step is saved
return !!settings?.edited && savedStep === null; return !!settings?.edited && savedStep === null;
}); });
// Only fetch conversations on chat page // Only fetch conversations on chat page
const isOnChatPage = pathname === "/" || pathname === "/chat"; const isOnChatPage = pathname === "/" || pathname === "/chat";
const { data: conversations = [], isLoading: isConversationsLoading } = const { data: conversations = [], isLoading: isConversationsLoading } =
useGetConversationsQuery(endpoint, refreshTrigger, { useGetConversationsQuery(endpoint, refreshTrigger, {
enabled: isOnChatPage && (isAuthenticated || isNoAuthMode), enabled: isOnChatPage && (isAuthenticated || isNoAuthMode),
}) as { data: ChatConversation[]; isLoading: boolean }; }) as { data: ChatConversation[]; isLoading: boolean };
const handleNewConversation = () => { const handleNewConversation = () => {
refreshConversations(); refreshConversations();
startNewConversation(); startNewConversation();
}; };
// Save current step to local storage whenever it changes // Save current step to local storage whenever it changes
useEffect(() => { useEffect(() => {
if (typeof window !== "undefined" && !showLayout) { if (typeof window !== "undefined" && !showLayout) {
localStorage.setItem(ONBOARDING_STEP_KEY, currentStep.toString()); localStorage.setItem(ONBOARDING_STEP_KEY, currentStep.toString());
} }
}, [currentStep, showLayout]); }, [currentStep, showLayout]);
const handleStepComplete = () => { const handleStepComplete = () => {
if (currentStep < TOTAL_ONBOARDING_STEPS - 1) { if (currentStep < TOTAL_ONBOARDING_STEPS - 1) {
setCurrentStep(currentStep + 1); setCurrentStep(currentStep + 1);
} else { } else {
// Onboarding is complete - remove from local storage and show layout // Onboarding is complete - remove from local storage and show layout
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
localStorage.removeItem(ONBOARDING_STEP_KEY); localStorage.removeItem(ONBOARDING_STEP_KEY);
} }
setShowLayout(true); setShowLayout(true);
} }
}; };
// List of paths with smaller max-width // List of paths with smaller max-width
const smallWidthPaths = ["/settings/connector/new"]; const smallWidthPaths = ["/settings/connector/new"];
const isSmallWidthPath = smallWidthPaths.includes(pathname); const isSmallWidthPath = smallWidthPaths.includes(pathname);
const x = showLayout ? "0px" : `calc(-${SIDEBAR_WIDTH / 2}px + 50vw)`; const x = showLayout ? "0px" : `calc(-${SIDEBAR_WIDTH / 2}px + 50vw)`;
const y = showLayout ? "0px" : `calc(-${HEADER_HEIGHT / 2}px + 50vh)`; const y = showLayout ? "0px" : `calc(-${HEADER_HEIGHT / 2}px + 50vh)`;
const translateY = showLayout ? "0px" : `-50vh`; const translateY = showLayout ? "0px" : `-50vh`;
const translateX = showLayout ? "0px" : `-50vw`; const translateX = showLayout ? "0px" : `-50vw`;
// For all other pages, render with Langflow-styled navigation and task menu // For all other pages, render with Langflow-styled navigation and task menu
return ( return (
<> <>
<AnimatedConditional <AnimatedConditional
className="[grid-area:header] bg-background border-b" className="[grid-area:header] bg-background border-b"
vertical vertical
slide slide
isOpen={showLayout} isOpen={showLayout}
delay={ANIMATION_DURATION / 2} delay={ANIMATION_DURATION / 2}
> >
<Header /> <Header />
</AnimatedConditional> </AnimatedConditional>
{/* Sidebar Navigation */} {/* Sidebar Navigation */}
<AnimatedConditional <AnimatedConditional
isOpen={showLayout} isOpen={showLayout}
slide slide
className={`border-r bg-background overflow-hidden [grid-area:nav] w-[${SIDEBAR_WIDTH}px]`} className={`border-r bg-background overflow-hidden [grid-area:nav] w-[${SIDEBAR_WIDTH}px]`}
> >
<Navigation <Navigation
conversations={conversations} conversations={conversations}
isConversationsLoading={isConversationsLoading} isConversationsLoading={isConversationsLoading}
onNewConversation={handleNewConversation} onNewConversation={handleNewConversation}
/> />
</AnimatedConditional> </AnimatedConditional>
{/* Main Content */} {/* Main Content */}
<main className="overflow-visible w-full flex items-center justify-center [grid-area:main]"> <main className="overflow-hidden w-full flex items-center justify-center [grid-area:main]">
<motion.div <motion.div
initial={{ initial={{
width: showLayout ? "100%" : "100vw", width: showLayout ? "100%" : "100vw",
height: showLayout ? "100%" : "100vh", height: showLayout ? "100%" : "100vh",
x: x, x: x,
y: y, y: y,
translateX: translateX, translateX: translateX,
translateY: translateY, translateY: translateY,
}} }}
animate={{ animate={{
width: showLayout ? "100%" : "850px", width: showLayout ? "100%" : "850px",
borderRadius: showLayout ? "0" : "16px", borderRadius: showLayout ? "0" : "16px",
border: showLayout ? "0" : "1px solid #27272A", border: showLayout ? "0" : "1px solid #27272A",
height: showLayout ? "100%" : "800px", height: showLayout ? "100%" : "800px",
x: x, x: x,
y: y, y: y,
translateX: translateX, translateX: translateX,
translateY: translateY, translateY: translateY,
}} }}
transition={{ transition={{
duration: ANIMATION_DURATION, duration: ANIMATION_DURATION,
ease: "easeOut", ease: "easeOut",
}} }}
className={cn( className={cn(
"flex h-full w-full max-w-full max-h-full items-center justify-center overflow-hidden", "flex h-full w-full max-w-full max-h-full items-center justify-center overflow-hidden",
!showLayout && "absolute", !showLayout && "absolute",
)} )}
> >
<div <div
className={cn( className={cn(
"h-full bg-background", "h-full bg-background w-full",
showLayout && "p-6 container", showLayout && !isOnChatPage && "p-6 container",
showLayout && isSmallWidthPath && "max-w-[850px] ml-0", showLayout && isSmallWidthPath && "max-w-[850px] ml-0",
!showLayout && !showLayout &&
"w-full bg-card rounded-lg shadow-2xl p-0 py-2 overflow-y-auto", "w-full bg-card rounded-lg shadow-2xl p-0 py-2 overflow-y-auto",
)} )}
> >
<motion.div <motion.div
initial={{ initial={{
opacity: showLayout ? 1 : 0, opacity: showLayout ? 1 : 0,
}} }}
animate={{ animate={{
opacity: "100%", opacity: "100%",
}} }}
transition={{ transition={{
duration: ANIMATION_DURATION, duration: ANIMATION_DURATION,
ease: "easeOut", ease: "easeOut",
delay: ANIMATION_DURATION, delay: ANIMATION_DURATION,
}} }}
className={cn("w-full h-full 0v")} className={cn("w-full h-full 0v")}
> >
<div className={cn("w-full h-full", !showLayout && "hidden")}> <div className={cn("w-full h-full", !showLayout && "hidden")}>
{children} {children}
</div> </div>
{!showLayout && ( {!showLayout && (
<OnboardingContent <OnboardingContent
handleStepComplete={handleStepComplete} handleStepComplete={handleStepComplete}
currentStep={currentStep} currentStep={currentStep}
/> />
)} )}
</motion.div> </motion.div>
</div> </div>
</motion.div> </motion.div>
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: showLayout ? 0 : 1, y: showLayout ? 20 : 0 }} animate={{ opacity: showLayout ? 0 : 1, y: showLayout ? 20 : 0 }}
transition={{ duration: ANIMATION_DURATION, ease: "easeOut" }} transition={{ duration: ANIMATION_DURATION, ease: "easeOut" }}
className={cn("absolute bottom-10 left-0 right-0")} className={cn("absolute bottom-10 left-0 right-0")}
> >
<ProgressBar <ProgressBar
currentStep={currentStep} currentStep={currentStep}
totalSteps={TOTAL_ONBOARDING_STEPS} totalSteps={TOTAL_ONBOARDING_STEPS}
/> />
</motion.div> </motion.div>
</main> </main>
</> </>
); );
} }