performance
All checks were successful
Build & Deploy MB Grid Solutions / build-and-deploy (push) Successful in 1m38s

This commit is contained in:
2026-01-29 17:08:45 +01:00
parent e033fd6290
commit 25759f3d4a
16 changed files with 95 additions and 57 deletions

View File

@@ -1,6 +1,7 @@
'use client'; 'use client';
import React from 'react'; import React from 'react';
import Image from 'next/image';
import { Award, Clock, Lightbulb, Linkedin, MessageSquare, ShieldCheck, Truck } from 'lucide-react'; import { Award, Clock, Lightbulb, Linkedin, MessageSquare, ShieldCheck, Truck } from 'lucide-react';
import { Reveal } from './Reveal'; import { Reveal } from './Reveal';
import { TechBackground } from './TechBackground'; import { TechBackground } from './TechBackground';
@@ -13,9 +14,12 @@ export default function About() {
{/* Hero Section */} {/* Hero Section */}
<section className="relative min-h-[60vh] flex items-center pt-32 pb-20 overflow-hidden"> <section className="relative min-h-[60vh] flex items-center pt-32 pb-20 overflow-hidden">
<div className="absolute inset-0 z-0"> <div className="absolute inset-0 z-0">
<div <Image
className="absolute inset-0 bg-cover bg-center" src="/media/drums/about-hero.jpg"
style={{ backgroundImage: 'url("/media/drums/iStock-487538226 (1).jpg")' }} alt="About MB Grid Solutions"
fill
className="object-cover"
priority
/> />
<div className="absolute inset-0 bg-gradient-to-r from-white via-white/95 to-white/40" /> <div className="absolute inset-0 bg-gradient-to-r from-white via-white/95 to-white/40" />
<TechBackground /> <TechBackground />

View File

@@ -1,7 +1,7 @@
'use client'; 'use client';
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import { motion } from 'framer-motion'; import { m, LazyMotion, domAnimation } from 'framer-motion';
import Link from 'next/link'; import Link from 'next/link';
import { ArrowRight } from 'lucide-react'; import { ArrowRight } from 'lucide-react';
@@ -60,13 +60,15 @@ export const Button = ({
); );
const spotlight = ( const spotlight = (
<motion.div <LazyMotion features={domAnimation}>
<m.div
className="absolute inset-0 z-0 pointer-events-none transition-opacity duration-500" className="absolute inset-0 z-0 pointer-events-none transition-opacity duration-500"
style={{ style={{
opacity: isHovered ? 1 : 0, opacity: isHovered ? 1 : 0,
background: `radial-gradient(600px circle at ${mousePosition.x}px ${mousePosition.y}px, rgba(255,255,255,0.15), transparent 40%)`, background: `radial-gradient(600px circle at ${mousePosition.x}px ${mousePosition.y}px, rgba(255,255,255,0.15), transparent 40%)`,
}} }}
/> />
</LazyMotion>
); );
const buttonProps = { const buttonProps = {

View File

@@ -1,6 +1,7 @@
'use client'; 'use client';
import React, { useState } from 'react'; import React, { useState } from 'react';
import Image from 'next/image';
import { Mail, MapPin, CheckCircle } from 'lucide-react'; import { Mail, MapPin, CheckCircle } from 'lucide-react';
import { Button } from './Button'; import { Button } from './Button';
import { Counter } from './Counter'; import { Counter } from './Counter';
@@ -41,9 +42,12 @@ export default function Contact() {
{/* Hero Section */} {/* Hero Section */}
<section className="relative min-h-[40vh] flex items-center pt-32 pb-20 overflow-hidden"> <section className="relative min-h-[40vh] flex items-center pt-32 pb-20 overflow-hidden">
<div className="absolute inset-0 z-0"> <div className="absolute inset-0 z-0">
<div <Image
className="absolute inset-0 bg-cover bg-center" src="/media/laying/contact-hero.jpg"
style={{ backgroundImage: 'url("/media/laying/iStock-1282259999.jpg")' }} alt="Contact MB Grid Solutions"
fill
className="object-cover"
priority
/> />
<div className="absolute inset-0 bg-gradient-to-r from-white via-white/95 to-white/40" /> <div className="absolute inset-0 bg-gradient-to-r from-white via-white/95 to-white/40" />
<TechBackground /> <TechBackground />

View File

@@ -1,7 +1,8 @@
'use client'; 'use client';
import { motion } from 'framer-motion'; import { m, LazyMotion, domAnimation } from 'framer-motion';
import { BarChart3, CheckCircle2, ChevronRight, Shield, Zap } from 'lucide-react'; import { BarChart3, CheckCircle2, ChevronRight, Shield, Zap } from 'lucide-react';
import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import { Button } from './Button'; import { Button } from './Button';
import { Counter } from './Counter'; import { Counter } from './Counter';
@@ -59,9 +60,13 @@ export default function Home() {
{/* Hero Section */} {/* Hero Section */}
<section className="relative min-h-[90vh] flex items-center pt-32 pb-20 overflow-hidden"> <section className="relative min-h-[90vh] flex items-center pt-32 pb-20 overflow-hidden">
<div className="absolute inset-0 z-0"> <div className="absolute inset-0 z-0">
<div <Image
className="absolute inset-0 bg-cover bg-center" src="/media/business/hero-bg.jpg"
style={{ backgroundImage: 'url("/media/business/iStock-1068752548.jpg")' }} alt="MB Grid Solutions Hero"
fill
className="object-cover"
priority
quality={90}
/> />
<div className="absolute inset-0 bg-gradient-to-r from-slate-100/80 via-white/90 to-white/40 md:to-transparent" /> <div className="absolute inset-0 bg-gradient-to-r from-slate-100/80 via-white/90 to-white/40 md:to-transparent" />
<TechBackground /> <TechBackground />
@@ -169,9 +174,11 @@ export default function Home() {
<Reveal direction="right"> <Reveal direction="right">
<div className="relative overflow-hidden rounded-2xl shadow-lg group"> <div className="relative overflow-hidden rounded-2xl shadow-lg group">
<div className="absolute inset-0 bg-accent/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10 pointer-events-none" /> <div className="absolute inset-0 bg-accent/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10 pointer-events-none" />
<img <Image
src="/media/cables/HS Kabel.png" src="/media/cables/hs-kabel.png"
alt="Technical Engineering" alt="Technical Engineering"
width={800}
height={600}
className="w-full h-[400px] md:h-[500px] object-cover hover:scale-105 transition-transform duration-700" className="w-full h-[400px] md:h-[500px] object-cover hover:scale-105 transition-transform duration-700"
/> />
<div className="tech-corner top-4 left-4 border-t-2 border-l-2 z-20" /> <div className="tech-corner top-4 left-4 border-t-2 border-l-2 z-20" />
@@ -214,10 +221,11 @@ export default function Home() {
{/* Technical Specs Section */} {/* Technical Specs Section */}
<section className="relative py-24 md:py-32 text-white overflow-hidden bg-slate-900"> <section className="relative py-24 md:py-32 text-white overflow-hidden bg-slate-900">
<div className="absolute inset-0 opacity-20"> <div className="absolute inset-0 opacity-20">
<img <Image
src="/media/drums/iStock-487538226 (1).jpg" src="/media/drums/about-hero.jpg"
alt="Background" alt="Background"
className="w-full h-full object-cover" fill
className="object-cover"
/> />
<div className="absolute inset-0 bg-gradient-to-b from-slate-900 via-slate-900/80 to-slate-900" /> <div className="absolute inset-0 bg-gradient-to-b from-slate-900 via-slate-900/80 to-slate-900" />
</div> </div>
@@ -277,23 +285,25 @@ export default function Home() {
<div className="tech-corner bottom-8 right-8 border-b-2 border-r-2" /> <div className="tech-corner bottom-8 right-8 border-b-2 border-r-2" />
<div className="absolute top-0 right-0 w-1/2 h-full opacity-10 pointer-events-none"> <div className="absolute top-0 right-0 w-1/2 h-full opacity-10 pointer-events-none">
<LazyMotion features={domAnimation}>
<svg viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<motion.circle <m.circle
animate={{ r: [400, 410, 400], opacity: [0.1, 0.2, 0.1] }} animate={{ r: [400, 410, 400], opacity: [0.1, 0.2, 0.1] }}
transition={{ duration: 5, repeat: Infinity, ease: "easeInOut" }} transition={{ duration: 5, repeat: Infinity, ease: "easeInOut" }}
cx="400" cy="0" r="400" stroke="white" strokeWidth="2" cx="400" cy="0" r="400" stroke="white" strokeWidth="2"
/> />
<motion.circle <m.circle
animate={{ r: [300, 310, 300], opacity: [0.1, 0.2, 0.1] }} animate={{ r: [300, 310, 300], opacity: [0.1, 0.2, 0.1] }}
transition={{ duration: 4, repeat: Infinity, ease: "easeInOut", delay: 0.5 }} transition={{ duration: 4, repeat: Infinity, ease: "easeInOut", delay: 0.5 }}
cx="400" cy="0" r="300" stroke="white" strokeWidth="2" cx="400" cy="0" r="300" stroke="white" strokeWidth="2"
/> />
<motion.circle <m.circle
animate={{ r: [200, 210, 200], opacity: [0.1, 0.2, 0.1] }} animate={{ r: [200, 210, 200], opacity: [0.1, 0.2, 0.1] }}
transition={{ duration: 3, repeat: Infinity, ease: "easeInOut", delay: 1 }} transition={{ duration: 3, repeat: Infinity, ease: "easeInOut", delay: 1 }}
cx="400" cy="0" r="200" stroke="white" strokeWidth="2" cx="400" cy="0" r="200" stroke="white" strokeWidth="2"
/> />
</svg> </svg>
</LazyMotion>
</div> </div>
<div className="relative z-10"> <div className="relative z-10">

View File

@@ -1,7 +1,8 @@
'use client'; 'use client';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, m, LazyMotion, domAnimation } from 'framer-motion';
import { ArrowUp, Home, Info, Menu, X } from 'lucide-react'; import { ArrowUp, Home, Info, Menu, X } from 'lucide-react';
import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
@@ -55,12 +56,15 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
className="relative z-10 flex items-center group" className="relative z-10 flex items-center group"
aria-label="MB Grid Solutions - Zur Startseite" aria-label="MB Grid Solutions - Zur Startseite"
> >
<img <div className={`relative transition-all duration-300 ${isScrolled ? 'h-[50px] md:h-[80px] w-[120px] md:w-[200px] my-[-5px]' : 'h-[80px] md:h-[140px] w-[180px] md:w-[320px] my-[-10px] md:my-[-20px]'}`}>
src="/assets/logo.png" <Image
alt="MB Grid Solutions" src="/assets/logo.png"
className={`transition-all duration-300 object-contain ${isScrolled ? 'h-[50px] md:h-[80px] my-[-5px]' : 'h-[80px] md:h-[140px] my-[-10px] md:my-[-20px]'}`} alt="MB Grid Solutions"
loading="eager" fill
/> className="object-contain"
priority
/>
</div>
</Link> </Link>
{/* Desktop Navigation */} {/* Desktop Navigation */}
@@ -100,9 +104,10 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
</Reveal> </Reveal>
{/* Mobile Menu Overlay */} {/* Mobile Menu Overlay */}
<LazyMotion features={domAnimation}>
<AnimatePresence> <AnimatePresence>
{isMobileMenuOpen && ( {isMobileMenuOpen && (
<motion.div <m.div
initial={{ opacity: 0, y: -20 }} initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }} exit={{ opacity: 0, y: -20 }}
@@ -130,9 +135,10 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
Projekt anfragen Projekt anfragen
</Button> </Button>
</nav> </nav>
</motion.div> </m.div>
)} )}
</AnimatePresence> </AnimatePresence>
</LazyMotion>
<main className="flex-grow"> <main className="flex-grow">
{children} {children}
@@ -153,16 +159,18 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
<div className="absolute inset-0 grid-pattern opacity-[0.08] pointer-events-none" /> <div className="absolute inset-0 grid-pattern opacity-[0.08] pointer-events-none" />
{/* Animated Tech Lines */} {/* Animated Tech Lines */}
<motion.div <LazyMotion features={domAnimation}>
<m.div
animate={{ x: ['-100%', '100%'] }} animate={{ x: ['-100%', '100%'] }}
transition={{ duration: 15, repeat: Infinity, ease: "linear" }} transition={{ duration: 15, repeat: Infinity, ease: "linear" }}
className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/30 to-transparent" className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/30 to-transparent"
/> />
<motion.div <m.div
animate={{ x: ['100%', '-100%'] }} animate={{ x: ['100%', '-100%'] }}
transition={{ duration: 20, repeat: Infinity, ease: "linear" }} transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/20 to-transparent" className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-accent/20 to-transparent"
/> />
</LazyMotion>
{/* Corner Accents */} {/* Corner Accents */}
<div className="tech-corner top-8 left-8 border-t border-l border-white/10 group-hover:border-accent/30 transition-colors duration-700" /> <div className="tech-corner top-8 left-8 border-t border-l border-white/10 group-hover:border-accent/30 transition-colors duration-700" />
@@ -172,12 +180,14 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-10 md:gap-12 mb-12 md:mb-16"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-10 md:gap-12 mb-12 md:mb-16">
<div className="lg:col-span-2"> <div className="lg:col-span-2">
<Link href="/" className="inline-block mb-6 md:mb-8 group"> <Link href="/" className="inline-block mb-6 md:mb-8 group">
<img <div className="relative h-16 md:h-20 w-48 brightness-0 invert opacity-80 group-hover:opacity-100 transition-opacity">
src="/assets/logo.png" <Image
alt="MB Grid Solutions" src="/assets/logo.png"
className="h-16 md:h-20 brightness-0 invert opacity-80 group-hover:opacity-100 transition-opacity" alt="MB Grid Solutions"
loading="lazy" fill
/> className="object-contain object-left"
/>
</div>
</Link> </Link>
<p className="text-slate-400 max-w-md leading-relaxed mb-8"> <p className="text-slate-400 max-w-md leading-relaxed mb-8">
Ihr spezialisierter Partner für herstellerneutrale technische Beratung und Projektbegleitung bei Energiekabelprojekten bis 110 kV. Ihr spezialisierter Partner für herstellerneutrale technische Beratung und Projektbegleitung bei Energiekabelprojekten bis 110 kV.

View File

@@ -1,7 +1,7 @@
'use client'; 'use client';
import React from 'react'; import React from 'react';
import { motion } from 'framer-motion'; import { m, LazyMotion, domAnimation } from 'framer-motion';
interface RevealProps { interface RevealProps {
children: React.ReactNode; children: React.ReactNode;
@@ -26,7 +26,8 @@ export const Reveal = ({
}; };
return ( return (
<motion.div <LazyMotion features={domAnimation}>
<m.div
initial={{ initial={{
opacity: 0, opacity: 0,
...directions[direction] ...directions[direction]
@@ -47,7 +48,8 @@ export const Reveal = ({
className={`${fullWidth ? 'w-full' : ''} ${className} motion-fix`} className={`${fullWidth ? 'w-full' : ''} ${className} motion-fix`}
> >
{children} {children}
</motion.div> </m.div>
</LazyMotion>
); );
}; };
@@ -63,7 +65,8 @@ export const Stagger = ({
staggerDelay = 0.1 staggerDelay = 0.1
}: StaggerProps) => { }: StaggerProps) => {
return ( return (
<motion.div <LazyMotion features={domAnimation}>
<m.div
initial="initial" initial="initial"
whileInView="animate" whileInView="animate"
viewport={{ once: true, margin: "-50px" }} viewport={{ once: true, margin: "-50px" }}
@@ -77,6 +80,7 @@ export const Stagger = ({
className={className} className={className}
> >
{children} {children}
</motion.div> </m.div>
</LazyMotion>
); );
}; };

View File

@@ -1,7 +1,7 @@
'use client'; 'use client';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { motion } from 'framer-motion'; import { m, LazyMotion, domAnimation } from 'framer-motion';
export const TileGrid = () => { export const TileGrid = () => {
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
@@ -17,6 +17,7 @@ export const TileGrid = () => {
return ( return (
<div className="absolute inset-0 pointer-events-none overflow-hidden z-[1]"> <div className="absolute inset-0 pointer-events-none overflow-hidden z-[1]">
<LazyMotion features={domAnimation}>
<div className="flex flex-col gap-3 min-w-[120%] min-h-[120%] -left-[10%] -top-[10%] absolute"> <div className="flex flex-col gap-3 min-w-[120%] min-h-[120%] -left-[10%] -top-[10%] absolute">
{[...Array(rows)].map((_, rowIndex) => ( {[...Array(rows)].map((_, rowIndex) => (
<div <div
@@ -27,7 +28,7 @@ export const TileGrid = () => {
}} }}
> >
{[...Array(cols)].map((_, colIndex) => ( {[...Array(cols)].map((_, colIndex) => (
<motion.div <m.div
key={`${rowIndex}-${colIndex}`} key={`${rowIndex}-${colIndex}`}
initial={{ opacity: 0.05 }} initial={{ opacity: 0.05 }}
animate={{ animate={{
@@ -46,6 +47,7 @@ export const TileGrid = () => {
</div> </div>
))} ))}
</div> </div>
</LazyMotion>
</div> </div>
); );
}; };

View File

@@ -0,0 +1,2 @@
import { domAnimation } from "framer-motion"
export default domAnimation

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 MiB