Untitled
unknown
plain_text
2 months ago
11 kB
4
Indexable
// components/ScrollToolbar.tsx "use client" import React, { useState, useRef } from "react" import { motion, useScroll, useMotionValueEvent } from "framer-motion" import { Slider } from "@/components/ui/slider" import { Button } from "@/components/ui/button" import { Image, Moon, Sun, List, X, ChevronUp, ZoomIn, ZoomOut, UserRound, Mail, Instagram } from "lucide-react" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" interface ToolbarProps { gridSize: number; setGridSize: (value: number) => void; sections: { title: string; description?: string; }[]; inView?: boolean; clientConfig: any; } export const ScrollToolbar = ({ gridSize, setGridSize, sections, inView = false, clientConfig }: ToolbarProps) => { const [variant, setVariant] = useState("hidden") const { scrollY } = useScroll() const scrollToSection = (sectionTitle: string) => { const element = document.getElementById(`section-${sectionTitle}`) if (element) { element.scrollIntoView({ behavior: "smooth" }) } } const scrollToTop = () => { window.scrollTo({ top: 0, behavior: "smooth" }) } useMotionValueEvent(scrollY, "change", (latest) => { if (inView) return setVariant("absolute") if (latest > 300) setVariant("visible") else setVariant("hidden") }) return ( <motion.div variants={{ hidden: { position: 'fixed', bottom: "-100px", left: 0, right: 0 }, visible: { position: 'fixed', bottom: '20px', left: 0, right: 0 }, absolute: { position: 'absolute', bottom: '20px', left: 0, right: 0 } }} animate={variant} transition={{ duration: 0.3, ease: "easeInOut" }} className="z-40 flex w-full justify-center pointer-events-none" > <div className="rounded-full bg-zinc-900/90 backdrop-blur-sm flex px-4 py-4 border-zinc-800 border shadow-lg pointer-events-auto"> {/* Image Size Adjustment */} <Popover> <PopoverTrigger asChild> <div className="h-10 w-10 flex items-center justify-center cursor-pointer hover:bg-zinc-800 rounded-lg transition-all hover:scale-105 hover:shadow"> <Image className="h-5 w-5 text-zinc-300" /> </div> </PopoverTrigger> <PopoverContent className="w-72 p-4 bg-zinc-900 border-zinc-800 text-zinc-300" sideOffset={16} side="top" align="center" > <div className="space-y-4"> <h4 className="font-medium text-sm">Fotogröße anpassen</h4> <div className="flex items-center gap-3"> <ZoomIn className="h-4 w-4 text-zinc-400" /> <Slider value={[gridSize]} min={1} max={6} step={1} onValueChange={(value) => setGridSize(value[0])} className="flex-1" /> <ZoomOut className="h-4 w-4 text-zinc-400" /> </div> </div> </PopoverContent> </Popover> <div className="h-6 w-px bg-zinc-700 mx-2" /> {/* Dark/Light Mode Toggle */} <div className="h-10 w-10 flex items-center justify-center cursor-pointer hover:bg-zinc-800 rounded-lg transition-all hover:scale-105 hover:shadow"> <Sun className="h-5 w-5 text-zinc-300" /> </div> <div className="h-6 w-px bg-zinc-700 mx-2" /> {/* Table of Contents */} <Popover> <PopoverTrigger asChild> <div className="h-10 w-10 flex items-center justify-center cursor-pointer hover:bg-zinc-800 rounded-lg transition-all hover:scale-105 hover:shadow"> <List className="h-5 w-5 text-zinc-300" /> </div> </PopoverTrigger> <PopoverContent className="w-72 p-0 bg-zinc-900 border-zinc-800 text-zinc-300 max-h-96 overflow-y-auto" sideOffset={16} side="top" align="center" > <div className="p-3 border-b border-zinc-800"> <h4 className="font-medium">Inhaltsverzeichnis</h4> </div> <div className="p-2"> {sections.map((section, index) => ( <div key={index} onClick={() => scrollToSection(section.title)} className="p-2 hover:bg-zinc-800 rounded cursor-pointer transition-colors" > {section.title} </div> ))} </div> </PopoverContent> </Popover> <div className="h-6 w-px bg-zinc-700 mx-2" /> {/* Personal Info */} <Popover> <PopoverTrigger asChild> <div className="h-10 w-10 flex items-center justify-center cursor-pointer hover:bg-zinc-800 rounded-lg transition-all hover:scale-105 hover:shadow"> <UserRound className="h-5 w-5 text-zinc-300" /> </div> </PopoverTrigger> <PopoverContent className="w-80 p-0 bg-zinc-900/95 border-zinc-800 text-zinc-300 shadow-xl" sideOffset={16} side="top" align="center" > <div className="overflow-hidden rounded-md"> <div className="relative p-6"> <div className="absolute inset-0 z-0"> <div className="absolute inset-0 bg-gradient-to-r from-zinc-900/80 to-zinc-900/10"></div> <img src="/background-image.jpg" alt="Background" className="w-full h-full object-cover object-center opacity-90" /> </div> <div className="w-16 h-16 rounded-full bg-zinc-800 flex items-center justify-center mb-3 ring-2 ring-white/20 shadow-lg overflow-hidden relative z-10"> <img src="/avatar.jpg" alt="Avatar" className="w-full h-full object-cover object-center" onError={(e) => { e.currentTarget.style.display = 'none'; e.currentTarget.parentElement.innerHTML = '<span class="text-white text-xl font-bold">P</span>'; }} /> </div> <h3 className="font-bold text-white text-xl relative z-10"> {clientConfig?.photographerName || "Fotograf"} </h3> <div className="flex items-center gap-2 mt-1 relative z-10"> <div className="h-1 w-6 bg-indigo-400 rounded-full"></div> <p className="text-white/90 text-sm font-medium"> {clientConfig?.photographerCredit || "Professionelle Fotografie"} </p> </div> </div> <div className="p-4 space-y-4 bg-gradient-to-b from-zinc-900 to-zinc-950"> <div className="space-y-3 pt-1"> <div className="flex items-center gap-3 text-zinc-300 p-2 rounded-md hover:bg-zinc-800/50 transition-colors"> <div className="bg-indigo-800/30 p-2 rounded-md"> <Mail className="h-4 w-4 text-indigo-300" /> </div> <a href={`mailto:${clientConfig?.photographerEmail || "info@example.com"}`} className="text-sm hover:text-indigo-300 transition-colors flex-1" > {clientConfig?.photographerEmail || "info@example.com"} </a> </div> <div className="flex items-center gap-3 text-zinc-300 p-2 rounded-md hover:bg-zinc-800/50 transition-colors"> <div className="bg-indigo-800/30 p-2 rounded-md"> <Instagram className="h-4 w-4 text-indigo-300" /> </div> <a href={clientConfig?.photographerInstagram || "#"} target="_blank" rel="noopener noreferrer" className="text-sm hover:text-indigo-300 transition-colors flex-1" > Instagram </a> </div> </div> <div className="relative flex items-center py-2"> <div className="flex-grow border-t border-zinc-800"></div> <span className="flex-shrink mx-3 text-zinc-500 text-xs">FOTOGRAF</span> <div className="flex-grow border-t border-zinc-800"></div> </div> <p className="text-sm text-zinc-400 italic"> "Hallo, mein Name ist Justin Faltus, ich bin ein Perfektionistischer Fotograf, ansässig in Heidenheim, Baden-Württemberg. Meine Liebe zur Fotografie wurde durch zauberhafte Augenblicke und Andenken geprägt. Ich lege stets Professionalität und Perfektionismus in meine Arbeit, mit dem Ziel, Ihnen atemberaubende Bilder zu liefern, die für immer in Erinnerung bleiben." </p> <Button className="w-full mt-2 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 border-0 text-indigo-100" onClick={() => window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })} > Kontaktieren </Button> </div> </div> </PopoverContent> </Popover> <div className="h-6 w-px bg-zinc-700 mx-2" /> {/* Scroll to Top */} <div className="h-10 w-10 flex items-center justify-center cursor-pointer hover:bg-zinc-800 rounded-lg transition-all hover:scale-105 hover:shadow" onClick={scrollToTop} > <ChevronUp className="h-5 w-5 text-zinc-300" /> </div> </div> </motion.div> ) } export default ScrollToolbar
Editor is loading...
Leave a Comment