feat: Presentation page redesign

This commit is contained in:
shiva raj badu 2026-02-23 00:32:47 +05:45
parent 9e54c6bb9e
commit 7abb446d32
No known key found for this signature in database
8 changed files with 191 additions and 357 deletions

View file

@ -31,7 +31,7 @@ export const PresentationCard = ({
// useFontLoader(presentation.fonts || []);
const handlePreview = (e: React.MouseEvent) => {
e.preventDefault();
router.push(`/presentation?id=${id}&type=${presentation.type}`);
router.push(`/presentation?id=${id}&type=standard`);
};
const handleDelete = async (e: React.MouseEvent) => {

View file

@ -4,10 +4,9 @@ import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { clearPresentationData } from "@/store/slices/presentationGeneration";
import { PresentationGenerationApi } from "../../services/api/presentation-generation";
import { Template, LoadingState, TABS } from "../types/index";
import { MixpanelEvent, trackEvent } from "@/utils/mixpanel";
import { TemplateLayoutsWithSettings } from "@/app/presentation-templates";
import { LoadingState, TABS } from "../types/index";
import { getCustomTemplateDetails } from "@/app/hooks/useCustomTemplates";
import { TemplateLayoutsWithSettings } from "@/app/presentation-templates/utils";
const DEFAULT_LOADING_STATE: LoadingState = {
message: "",
@ -129,7 +128,7 @@ export const usePresentationGeneration = (
layout = {
name: selectedTemplate.id,
ordered: false,
slides: selectedTemplate.layouts.map((layoutItem) => ({
slides: selectedTemplate.layouts.map((layoutItem: any) => ({
id: layoutItem.layoutId,
name: layoutItem.layoutName,
description: layoutItem.layoutDescription,

View file

@ -6,6 +6,8 @@ import {
Loader2,
Redo2,
Undo2,
RotateCcw,
ArrowRightFromLine,
} from "lucide-react";
import React, { useState } from "react";
@ -37,17 +39,20 @@ import { usePresentationUndoRedo } from "../hooks/PresentationUndoRedo";
import ToolTip from "@/components/ToolTip";
import { clearPresentationData } from "@/store/slices/presentationGeneration";
import { clearHistory } from "@/store/slices/undoRedoSlice";
import { Separator } from "@/components/ui/separator";
const Header = ({
const PresentationHeader = ({
presentation_id,
isPresentationSaving,
currentSlide,
}: {
presentation_id: string;
isPresentationSaving: boolean;
currentSlide?: number;
}) => {
const [open, setOpen] = useState(false);
const [showLoader, setShowLoader] = useState(false);
const router = useRouter();
const [isExporting, setIsExporting] = useState(false);
const pathname = usePathname();
const dispatch = useDispatch();
@ -68,8 +73,7 @@ const Header = ({
if (isStreaming) return;
try {
setOpen(false);
setShowLoader(true);
setIsExporting(true);
// Save the presentation data before exporting
trackEvent(MixpanelEvent.Header_UpdatePresentationContent_API_Call);
await PresentationGenerationApi.updatePresentationContent(presentationData);
@ -88,13 +92,12 @@ const Header = ({
}
} catch (error) {
console.error("Export failed:", error);
setShowLoader(false);
toast.error("Having trouble exporting!", {
description:
"We are having trouble exporting your presentation. Please try again.",
});
} finally {
setShowLoader(false);
setIsExporting(false);
}
};
@ -102,8 +105,7 @@ const Header = ({
if (isStreaming) return;
try {
setOpen(false);
setShowLoader(true);
setIsExporting(true);
// Save the presentation data before exporting
trackEvent(MixpanelEvent.Header_UpdatePresentationContent_API_Call);
await PresentationGenerationApi.updatePresentationContent(presentationData);
@ -132,7 +134,7 @@ const Header = ({
"We are having trouble exporting your presentation. Please try again.",
});
} finally {
setShowLoader(false);
setIsExporting(false);
}
};
const handleReGenerate = () => {
@ -182,117 +184,79 @@ const Header = ({
</div>
);
const MenuItems = ({ mobile }: { mobile: boolean }) => (
<div className="flex flex-col lg:flex-row items-center gap-4">
{/* undo redo */}
<button onClick={handleReGenerate} disabled={isStreaming || !presentationData} className="text-white disabled:opacity-50" >
Re-Generate
</button>
<div className="flex items-center gap-2 ">
<ToolTip content="Undo">
<button disabled={!canUndo} className="text-white disabled:opacity-50" onClick={() => {
onUndo();
}}>
<Undo2 className="w-6 h-6 " />
</button>
</ToolTip>
<ToolTip content="Redo">
<button disabled={!canRedo} className="text-white disabled:opacity-50" onClick={() => {
onRedo();
}}>
<Redo2 className="w-6 h-6 " />
</button>
</ToolTip>
</div>
{/* Present Button */}
<Button
onClick={() => {
const to = `?id=${presentation_id}&mode=present&slide=${currentSlide || 0}`;
trackEvent(MixpanelEvent.Navigation, { from: pathname, to });
router.push(to);
}}
variant="ghost"
className="border border-white font-bold text-white rounded-[32px] transition-all duration-300 group"
>
<Play className="w-4 h-4 mr-1 stroke-white group-hover:stroke-black" />
Present
</Button>
{/* Desktop Export Button with Popover */}
<div style={{
zIndex: 100
}} className="hidden lg:block relative ">
<Popover open={open} onOpenChange={setOpen} >
<PopoverTrigger asChild>
<Button className={`border py-5 text-[#5146E5] font-bold rounded-[32px] transition-all duration-500 hover:border hover:bg-[#5146E5] hover:text-white w-full ${mobile ? "" : "bg-white"}`}>
<SquareArrowOutUpRight className="w-4 h-4 mr-1" />
Export
</Button>
</PopoverTrigger>
<PopoverContent align="end" className="w-[250px] space-y-2 py-3 px-2 ">
<ExportOptions mobile={false} />
</PopoverContent>
</Popover>
</div>
{/* Mobile Export Section */}
<div className="lg:hidden flex flex-col w-full">
<ExportOptions mobile={true} />
</div>
</div>
);
return (
<>
<OverlayLoader
show={showLoader}
text="Exporting presentation..."
showProgress={true}
duration={40}
/>
<div
<div className="py-7 sticky top-0 bg-white z-50 mb-[17px] pr-[25px] flex justify-between items-center">
<h2 className="text-[28px] text-[#101323] w-[600px] truncate">{presentationData?.title || "Presentation"}</h2>
<div className="flex items-center gap-2.5">
className="bg-[#5146E5] w-full shadow-lg sticky top-0 ">
{isPresentationSaving && <div className="flex items-center gap-2">
<Loader2 className="w-3.5 h-3.5 animate-spin" />
</div>}
<Announcement />
<Wrapper className="flex items-center justify-between py-1">
<Link href="/dashboard" className="min-w-[162px]">
<img
className="h-16"
src="/logo-white.png"
alt="Presentation logo"
/>
</Link>
<div className="flex items-center gap-2 bg-[#F6F6F9] px-3.5 h-[38px] border border-[#EDECEC] rounded-[80px]">
{/* Desktop Menu */}
<div className="hidden lg:flex items-center gap-4 2xl:gap-6">
{isStreaming && (
<Loader2 className="animate-spin text-white font-bold w-6 h-6" />
)}
<ToolTip content="Regenerate Presentation">
<button onClick={handleReGenerate} className="group">
<RotateCcw className="w-3.5 h-3.5 text-[#101323] group-hover:text-[#5141e5] duration-300" />
</button>
</ToolTip>
<Separator orientation="vertical" className="h-4" />
<ToolTip content="Undo">
<button disabled={!canUndo} className=" disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer group" onClick={() => {
onUndo();
}}>
<Undo2 className="w-3.5 h-3.5 text-[#101323] group-hover:text-[#5141e5] duration-300" />
<MenuItems mobile={false} />
<HeaderNav />
</button>
</ToolTip>
<Separator orientation="vertical" className="h-4" />
<ToolTip content="Redo">
<button disabled={!canRedo} className=" disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer group" onClick={() => {
onRedo();
}}>
<Redo2 className="w-3.5 h-3.5 text-[#101323] group-hover:text-[#5141e5] duration-300" />
</button>
</ToolTip>
<Separator orientation="vertical" className="h-4 w-[2px]" />
<ToolTip content="Present">
<button
onClick={() => {
const to = `?id=${presentation_id}&mode=present&slide=${currentSlide || 0}`;
trackEvent(MixpanelEvent.Navigation, { from: pathname, to });
router.push(to);
}}
disabled={!presentationData?.slides || presentationData?.slides.length === 0} className="cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed group">
<Play className="w-3.5 h-3.5 text-[#101323] group-hover:text-[#5141e5] duration-300" />
</button>
</ToolTip>
</div>
{/* Mobile Menu */}
<div className="lg:hidden flex items-center gap-4">
<HeaderNav />
</div>
</Wrapper>
<Popover open={open} onOpenChange={setOpen} >
<PopoverTrigger asChild>
<button className="flex items-center gap-[7px] px-[18px] py-[11px] rounded-[53px] text-sm font-semibold text-[#101323]"
style={{
background: "linear-gradient(270deg, #D5CAFC 2.4%, #E3D2EB 27.88%, #F4DCD3 69.23%, #FDE4C2 100%)",
}}
disabled={isExporting}
>
{isExporting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : "Export"} <ArrowRightFromLine />
</button>
</PopoverTrigger>
<PopoverContent align="end" className="w-[250px] space-y-2 py-3 px-2 ">
<ExportOptions mobile={false} />
</PopoverContent>
</Popover>
</div>
</div>
</>
);
};
export default Header;
export default PresentationHeader;

View file

@ -1,17 +1,15 @@
"use client";
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { RootState } from "@/store/store";
import { Skeleton } from "@/components/ui/skeleton";
import PresentationMode from "../../components/PresentationMode";
import SidePanel from "./SidePanel";
import SlideContent from "./SlideContent";
import Header from "./Header";
import { Button } from "@/components/ui/button";
import { usePathname } from "next/navigation";
import { trackEvent, MixpanelEvent } from "@/utils/mixpanel";
import { AlertCircle, Loader2 } from "lucide-react";
import Help from "./Help";
import {
usePresentationStreaming,
usePresentationData,
@ -21,8 +19,9 @@ import {
import { PresentationPageProps } from "../types";
import LoadingState from "./LoadingState";
import { useFontLoader } from "../../hooks/useFontLoader";
import { usePresentationUndoRedo } from "../hooks/PresentationUndoRedo";
import PresentationHeader from "./PresentationHeader";
const PresentationPage: React.FC<PresentationPageProps> = ({
presentation_id,
}) => {
@ -32,7 +31,6 @@ const PresentationPage: React.FC<PresentationPageProps> = ({
const [selectedSlide, setSelectedSlide] = useState(0);
const [isFullscreen, setIsFullscreen] = useState(false);
const [error, setError] = useState(false);
const [isMobilePanelOpen, setIsMobilePanelOpen] = useState(false);
const { presentationData, isStreaming } = useSelector(
@ -123,63 +121,64 @@ const PresentationPage: React.FC<PresentationPageProps> = ({
}
return (
<div className="h-screen flex overflow-hidden flex-col">
<div className="fixed right-6 top-[5.2rem] z-50">
{isSaving && <Loader2 className="w-6 h-6 animate-spin text-blue-500" />}
</div>
<Header presentation_id={presentation_id} currentSlide={selectedSlide} />
<Help />
<div className="h-screen overflow-hidden ">
<div
style={{
background: "#c8c7c9",
background: "#ffffff",
}}
className="flex flex-1 relative pt-6"
className="flex gap-6 relative "
>
<SidePanel
selectedSlide={selectedSlide}
onSlideClick={handleSlideClick}
loading={loading}
isMobilePanelOpen={isMobilePanelOpen}
setIsMobilePanelOpen={setIsMobilePanelOpen}
/>
<div className="w-[200px]">
<SidePanel
selectedSlide={selectedSlide}
onSlideClick={handleSlideClick}
loading={loading}
<div className="flex-1 h-[calc(100vh-100px)] overflow-y-auto">
/>
</div>
<div className=" w-full h-[calc(100vh-20px)] overflow-y-auto">
<PresentationHeader presentation_id={presentation_id} isPresentationSaving={isSaving} currentSlide={selectedSlide} />
<div
id="presentation-slides-wrapper"
className="mx-auto flex flex-col items-center overflow-hidden justify-center p-2 sm:p-6 pt-0"
style={{
background: "rgba(255, 255, 255, 0.10)",
boxShadow: "0 0 20.01px 0 rgba(122, 90, 248, 0.16) inset",
}}
className="p-6 rounded-[20px] flex flex-col items-center overflow-hidden justify-center border border-[#EDECEC] "
>
{!presentationData ||
loading ||
!presentationData?.slides ||
presentationData?.slides.length === 0 ? (
<div className="relative w-full h-[calc(100vh-120px)] mx-auto">
<div className="">
{Array.from({ length: 2 }).map((_, index) => (
<Skeleton
key={index}
className="aspect-video bg-gray-400 my-4 w-full mx-auto max-w-[1280px]"
/>
))}
<div className="w-full max-w-[1280px] h-full">
{!presentationData ||
loading ||
!presentationData?.slides ||
presentationData?.slides.length === 0 ? (
<div className="relative w-full h-[calc(100vh-120px)] mx-auto">
<div className="">
{Array.from({ length: 2 }).map((_, index) => (
<Skeleton
key={index}
className="aspect-video bg-gray-400 my-4 w-full mx-auto "
/>
))}
</div>
{stream && <LoadingState />}
</div>
{stream && <LoadingState />}
</div>
) : (
<>
{presentationData &&
presentationData.slides &&
presentationData.slides.length > 0 &&
presentationData.slides.map((slide: any, index: number) => (
<SlideContent
key={`${slide.type}-${index}-${slide.index}`}
slide={slide}
index={index}
presentationId={presentation_id}
/>
))}
</>
)}
) : (
<>
{presentationData &&
presentationData.slides &&
presentationData.slides.length > 0 &&
presentationData.slides.map((slide: any, index: number) => (
<SlideContent
key={`${slide.type}-${index}-${slide.index}`}
slide={slide}
index={index}
presentationId={presentation_id}
/>
))}
</>
)}
</div>
</div>
</div>
</div>

View file

@ -1,8 +1,6 @@
"use client";
import React, { useState, useEffect } from "react";
import { LayoutList, ListTree, PanelRightOpen, X } from "lucide-react";
import ToolTip from "@/components/ToolTip";
import { Button } from "@/components/ui/button";
import React, { } from "react";
import { Plus } from "lucide-react";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "@/store/store";
import {
@ -21,26 +19,25 @@ import {
} from "@dnd-kit/sortable";
import { setPresentationData } from "@/store/slices/presentationGeneration";
import { SortableSlide } from "./SortableSlide";
import { SortableListItem } from "./SortableListItem";
import SlideScale from "../../components/PresentationRender";
import { Separator } from "@/components/ui/separator";
import { useRouter } from "next/navigation";
interface SidePanelProps {
selectedSlide: number;
onSlideClick: (index: number) => void;
isMobilePanelOpen: boolean;
setIsMobilePanelOpen: (value: boolean) => void;
loading: boolean;
}
const SidePanel = ({
selectedSlide,
onSlideClick,
isMobilePanelOpen,
setIsMobilePanelOpen,
loading,
}: SidePanelProps) => {
const [isOpen, setIsOpen] = useState(true);
const [active, setActive] = useState<"list" | "grid">("grid");
const router = useRouter();
const { presentationData, isStreaming } = useSelector(
(state: RootState) => state.presentationGeneration
@ -50,11 +47,7 @@ const SidePanel = ({
useEffect(() => {
if (window.innerWidth < 768) {
setIsOpen(isMobilePanelOpen);
}
}, [isMobilePanelOpen]);
const sensors = useSensors(
useSensor(PointerSensor, {
@ -67,12 +60,7 @@ const SidePanel = ({
})
);
const handleClose = () => {
setIsOpen(false);
if (window.innerWidth < 768) {
setIsMobilePanelOpen(false);
}
};
const handleDragEnd = (event: any) => {
const { active, over } = event;
@ -119,196 +107,80 @@ const SidePanel = ({
}
return (
<>
{/* Desktop Toggle Button - Always visible when panel is closed */}
{!isOpen && (
<div className="hidden xl:block fixed left-4 top-1/2 -translate-y-1/2 z-50">
<ToolTip content="Open Panel">
<Button
onClick={() => setIsOpen(true)}
className="bg-white hover:bg-gray-50 shadow-lg"
>
<PanelRightOpen className="text-black" size={20} />
</Button>
</ToolTip>
</div>
)}
<div className="bg-[#F6F6F9] pt-8 px-4 w-[200px]">
{/* Mobile Toggle Button */}
{!isMobilePanelOpen && (
<div className="xl:hidden fixed left-4 bottom-4 z-50">
<ToolTip content="Show Panel">
<Button
onClick={() => setIsMobilePanelOpen(true)}
className="bg-[#5146E5] text-white p-3 rounded-full shadow-lg"
>
<PanelRightOpen className="text-white" size={20} />
</Button>
</ToolTip>
</div>
)}
<img onClick={() => {
router.push("/dashboard");
}} src="/logo-with-bg.png" alt="" className="w-10 h-10 cursor-pointer object-contain" />
<Separator orientation="horizontal" className="my-6 " />
<div
className={`
fixed xl:relative h-full z-50 xl:z-auto
transition-all duration-300 ease-in-out
${isOpen ? "ml-0" : "-ml-[300px]"}
${isMobilePanelOpen
? "translate-x-0"
: "-translate-x-full xl:translate-x-0"
}
`}
>
<div
className="min-w-[300px] bg-white max-w-[300px] h-[calc(100vh-120px)] rounded-[20px] hide-scrollbar overflow-hidden slide-theme shadow-xl"
className="w-full h-[calc(100vh-120px)] hide-scrollbar overflow-hidden slide-theme "
>
<div
className="sticky top-0 z-40 px-6 py-4"
>
<div className="flex items-center justify-between gap-4">
<div className="flex items-center justify-start gap-4">
<ToolTip content="Image Preview">
<Button
className={`${active === "grid"
? "bg-[#5141e5] hover:bg-[#4638c7]"
: "bg-white hover:bg-white"
}`}
onClick={() => {
if (!isStreaming) {
setActive("grid")
}
}}
>
<LayoutList
className={`${active === "grid" ? "text-white" : "text-black"
}`}
size={20}
/>
</Button>
</ToolTip>
<ToolTip content="List Preview">
<Button
className={`${active === "list"
? "bg-[#5141e5] hover:bg-[#4638c7]"
: "bg-white hover:bg-white"
}`}
onClick={() => {
if (!isStreaming) {
setActive("list")
}
}}
>
<ListTree
className={`${active === "list" ? "text-white" : "text-black"
}`}
size={20}
/>
</Button>
</ToolTip>
</div>
<X
onClick={handleClose}
className="text-[#6c7081] cursor-pointer hover:text-gray-600"
size={20}
/>
</div>
</div>
<p className="text-xl font-normal pb-3.5 text-[#000000]">Slides</p>
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
>
{/* List Preview */}
{active === "list" && (
<div className="p-4 overflow-y-auto hide-scrollbar h-[calc(100%-100px)]">
{isStreaming ? (
presentationData &&
presentationData?.slides.map((slide: any, index: number) => (
<div
key={`${index}-${slide.type}-${slide.id}`}
className={`p-3 cursor-pointer rounded-lg slide-box`}
>
<span className="font-medium slide-title">
Slide {index + 1}
</span>
<p className="text-sm slide-description">
{slide.content.title}
</p>
</div>
))
) : (
<SortableContext
items={
presentationData?.slides.map((slide: any) => slide.id!) || []
}
strategy={verticalListSortingStrategy}
<div className=" overflow-y-auto hide-scrollbar h-[calc(100%-140px)] space-y-3.5">
{isStreaming ? (
presentationData &&
presentationData?.slides.map((slide: any, index: number) => (
<div
key={`${slide.id}-${index}`}
onClick={() => onSlideClick(index)}
className={` cursor-pointer ring-2 rounded-[12px] transition-all duration-200 ${selectedSlide === index ? ' ring-[#5141e5]' : 'ring-gray-200'
}`}
>
<div className="space-y-2" id={`slide-${selectedSlide}`}>
{presentationData &&
presentationData?.slides.map((slide: any, index: number) => (
<SortableListItem
key={`${slide.id}-${index}`}
slide={slide}
index={index}
selectedSlide={selectedSlide}
onSlideClick={onSlideClick}
/>
))}
</div>
</SortableContext>
)}
</div>
)}
{/* Grid Preview */}
{active === "grid" && (
<div className="p-4 overflow-y-auto hide-scrollbar h-[calc(100%-100px)] space-y-4">
{isStreaming ? (
presentationData &&
presentationData?.slides.map((slide: any, index: number) => (
<div
key={`${slide.id}-${index}`}
onClick={() => onSlideClick(index)}
className={` cursor-pointer ring-2 p-1 rounded-md transition-all duration-200 ${selectedSlide === index ? ' ring-[#5141e5]' : 'ring-gray-200'
}`}
>
<div className=" bg-white pointer-events-none relative overflow-hidden aspect-video">
<div className="absolute bg-gray-100/5 z-50 top-0 left-0 w-full h-full" />
<div className="transform scale-[0.2] flex justify-center items-center origin-top-left w-[500%] h-[500%]">
<SlideScale slide={slide} />
</div>
<div className=" bg-white pointer-events-none relative overflow-hidden aspect-video">
<div className="absolute bg-gray-100/5 z-50 top-0 left-0 w-full h-full" />
<div className="transform scale-[0.2] flex justify-center items-center origin-top-left w-[500%] h-[500%]">
<SlideScale slide={slide} />
</div>
</div>
))
) : (
<SortableContext
items={
presentationData?.slides.map((slide: any) => slide.id || `${slide.index}`) || []
}
strategy={verticalListSortingStrategy}
>
{presentationData &&
presentationData?.slides.map((slide: any, index: number) => (
<SortableSlide
key={`${slide.id}-${index}`}
slide={slide}
index={index}
selectedSlide={selectedSlide}
onSlideClick={onSlideClick}
</div>
))
) : (
<SortableContext
items={
presentationData?.slides.map((slide: any) => slide.id || `${slide.index}`) || []
}
strategy={verticalListSortingStrategy}
>
{presentationData &&
presentationData?.slides.map((slide: any, index: number) => (
<SortableSlide
key={`${slide.id}-${index}`}
slide={slide}
index={index}
selectedSlide={selectedSlide}
onSlideClick={onSlideClick}
/>
))}
</SortableContext>
)}
</div>
/>
))}
</SortableContext>
)}
</div>
)}
</DndContext>
<button className=" pt-6 gap-2 flex flex-col py-2 duration-300 items-center justify-center rounded-lg cursor-pointer mx-auto">
<Plus className="w-3.5 h-3.5" />
<span className="text-[11px] font-normal text-[#000000]">Add Slide</span>
</button>
</div>
</div>
</>
</div>
);
};

View file

@ -132,7 +132,7 @@ const SlideContent = ({ slide, index, presentationId }: SlideContentProps) => {
<>
<div
id={`slide-${slide.index}`}
className=" w-full max-w-[1280px] main-slide flex items-center max-md:mb-4 justify-center relative"
className=" w-full main-slide flex items-center max-md:mb-4 justify-center relative"
>
{isStreaming && (
<Loader2 className="w-8 h-8 absolute right-2 top-2 z-30 text-blue-800 animate-spin" />

View file

@ -10,7 +10,7 @@ interface SortableSlideProps {
selectedSlide: number;
onSlideClick: (index: any) => void;
}
const SCALE = 0.2;
const SCALE = 0.125;
export function SortableSlide({ slide, index, selectedSlide, onSlideClick }: SortableSlideProps) {
const searchParams = useSearchParams();
@ -55,7 +55,7 @@ export function SortableSlide({ slide, index, selectedSlide, onSlideClick }: Sor
{...attributes}
{...listeners}
onClick={handleClick}
className={` cursor-pointer border-[3px] relative p-1 shadow-lg rounded-md transition-all duration-200 ${selectedSlide === index ? ' border-[#5141e5]' : 'border-gray-300'
className={` cursor-pointer border relative p-1 rounded-[12px] transition-all duration-200 ${selectedSlide === index ? ' border-[#5141e5]' : 'border-[#EDEEEF]'
}`}
>

View file

@ -211,7 +211,7 @@ const UploadPage = () => {
onConfigChange={handleConfigChange}
/>
</div> */}
<div className=" w-full mx-auto px-2 md:px-0 max-w-[720px] ">
<div className=" w-full mx-auto px-2 md:px-0 max-w-[780px] ">
<div
className='fixed z-0 md:-bottom-[36%] -bottom-[40%] left-0 w-full h-full'