performance
All checks were successful
Build & Deploy MB Grid Solutions / build-and-deploy (push) Successful in 1m38s
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import Image from 'next/image';
|
||||
import { Award, Clock, Lightbulb, Linkedin, MessageSquare, ShieldCheck, Truck } from 'lucide-react';
|
||||
import { Reveal } from './Reveal';
|
||||
import { TechBackground } from './TechBackground';
|
||||
@@ -13,9 +14,12 @@ export default function About() {
|
||||
{/* Hero Section */}
|
||||
<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 bg-cover bg-center"
|
||||
style={{ backgroundImage: 'url("/media/drums/iStock-487538226 (1).jpg")' }}
|
||||
<Image
|
||||
src="/media/drums/about-hero.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" />
|
||||
<TechBackground />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
||||
import Link from 'next/link';
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
|
||||
@@ -60,13 +60,15 @@ export const Button = ({
|
||||
);
|
||||
|
||||
const spotlight = (
|
||||
<motion.div
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.div
|
||||
className="absolute inset-0 z-0 pointer-events-none transition-opacity duration-500"
|
||||
style={{
|
||||
opacity: isHovered ? 1 : 0,
|
||||
background: `radial-gradient(600px circle at ${mousePosition.x}px ${mousePosition.y}px, rgba(255,255,255,0.15), transparent 40%)`,
|
||||
}}
|
||||
/>
|
||||
</LazyMotion>
|
||||
);
|
||||
|
||||
const buttonProps = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { Mail, MapPin, CheckCircle } from 'lucide-react';
|
||||
import { Button } from './Button';
|
||||
import { Counter } from './Counter';
|
||||
@@ -41,9 +42,12 @@ export default function Contact() {
|
||||
{/* Hero Section */}
|
||||
<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 bg-cover bg-center"
|
||||
style={{ backgroundImage: 'url("/media/laying/iStock-1282259999.jpg")' }}
|
||||
<Image
|
||||
src="/media/laying/contact-hero.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" />
|
||||
<TechBackground />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
||||
import { BarChart3, CheckCircle2, ChevronRight, Shield, Zap } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { Button } from './Button';
|
||||
import { Counter } from './Counter';
|
||||
@@ -59,9 +60,13 @@ export default function Home() {
|
||||
{/* Hero Section */}
|
||||
<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 bg-cover bg-center"
|
||||
style={{ backgroundImage: 'url("/media/business/iStock-1068752548.jpg")' }}
|
||||
<Image
|
||||
src="/media/business/hero-bg.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" />
|
||||
<TechBackground />
|
||||
@@ -169,9 +174,11 @@ export default function Home() {
|
||||
<Reveal direction="right">
|
||||
<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" />
|
||||
<img
|
||||
src="/media/cables/HS Kabel.png"
|
||||
<Image
|
||||
src="/media/cables/hs-kabel.png"
|
||||
alt="Technical Engineering"
|
||||
width={800}
|
||||
height={600}
|
||||
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" />
|
||||
@@ -214,10 +221,11 @@ export default function Home() {
|
||||
{/* Technical Specs Section */}
|
||||
<section className="relative py-24 md:py-32 text-white overflow-hidden bg-slate-900">
|
||||
<div className="absolute inset-0 opacity-20">
|
||||
<img
|
||||
src="/media/drums/iStock-487538226 (1).jpg"
|
||||
alt="Background"
|
||||
className="w-full h-full object-cover"
|
||||
<Image
|
||||
src="/media/drums/about-hero.jpg"
|
||||
alt="Background"
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-slate-900 via-slate-900/80 to-slate-900" />
|
||||
</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="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">
|
||||
<motion.circle
|
||||
<m.circle
|
||||
animate={{ r: [400, 410, 400], opacity: [0.1, 0.2, 0.1] }}
|
||||
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] }}
|
||||
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] }}
|
||||
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>
|
||||
</LazyMotion>
|
||||
</div>
|
||||
|
||||
<div className="relative z-10">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
'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 Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@@ -55,12 +56,15 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
className="relative z-10 flex items-center group"
|
||||
aria-label="MB Grid Solutions - Zur Startseite"
|
||||
>
|
||||
<img
|
||||
src="/assets/logo.png"
|
||||
alt="MB Grid Solutions"
|
||||
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]'}`}
|
||||
loading="eager"
|
||||
/>
|
||||
<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]'}`}>
|
||||
<Image
|
||||
src="/assets/logo.png"
|
||||
alt="MB Grid Solutions"
|
||||
fill
|
||||
className="object-contain"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
@@ -100,9 +104,10 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
</Reveal>
|
||||
|
||||
{/* Mobile Menu Overlay */}
|
||||
<LazyMotion features={domAnimation}>
|
||||
<AnimatePresence>
|
||||
{isMobileMenuOpen && (
|
||||
<motion.div
|
||||
<m.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
@@ -130,9 +135,10 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
Projekt anfragen
|
||||
</Button>
|
||||
</nav>
|
||||
</motion.div>
|
||||
</m.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</LazyMotion>
|
||||
|
||||
<main className="flex-grow">
|
||||
{children}
|
||||
@@ -153,16 +159,18 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
<div className="absolute inset-0 grid-pattern opacity-[0.08] pointer-events-none" />
|
||||
|
||||
{/* Animated Tech Lines */}
|
||||
<motion.div
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.div
|
||||
animate={{ x: ['-100%', '100%'] }}
|
||||
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"
|
||||
/>
|
||||
<motion.div
|
||||
<m.div
|
||||
animate={{ x: ['100%', '-100%'] }}
|
||||
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"
|
||||
/>
|
||||
</LazyMotion>
|
||||
|
||||
{/* 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" />
|
||||
@@ -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="lg:col-span-2">
|
||||
<Link href="/" className="inline-block mb-6 md:mb-8 group">
|
||||
<img
|
||||
src="/assets/logo.png"
|
||||
alt="MB Grid Solutions"
|
||||
className="h-16 md:h-20 brightness-0 invert opacity-80 group-hover:opacity-100 transition-opacity"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div className="relative h-16 md:h-20 w-48 brightness-0 invert opacity-80 group-hover:opacity-100 transition-opacity">
|
||||
<Image
|
||||
src="/assets/logo.png"
|
||||
alt="MB Grid Solutions"
|
||||
fill
|
||||
className="object-contain object-left"
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
<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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
||||
|
||||
interface RevealProps {
|
||||
children: React.ReactNode;
|
||||
@@ -26,9 +26,10 @@ export const Reveal = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{
|
||||
opacity: 0,
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.div
|
||||
initial={{
|
||||
opacity: 0,
|
||||
...directions[direction]
|
||||
}}
|
||||
whileInView={{
|
||||
@@ -47,7 +48,8 @@ export const Reveal = ({
|
||||
className={`${fullWidth ? 'w-full' : ''} ${className} motion-fix`}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</m.div>
|
||||
</LazyMotion>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -63,7 +65,8 @@ export const Stagger = ({
|
||||
staggerDelay = 0.1
|
||||
}: StaggerProps) => {
|
||||
return (
|
||||
<motion.div
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.div
|
||||
initial="initial"
|
||||
whileInView="animate"
|
||||
viewport={{ once: true, margin: "-50px" }}
|
||||
@@ -77,6 +80,7 @@ export const Stagger = ({
|
||||
className={className}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</m.div>
|
||||
</LazyMotion>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { m, LazyMotion, domAnimation } from 'framer-motion';
|
||||
|
||||
export const TileGrid = () => {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
@@ -17,26 +17,27 @@ export const TileGrid = () => {
|
||||
|
||||
return (
|
||||
<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">
|
||||
{[...Array(rows)].map((_, rowIndex) => (
|
||||
<div
|
||||
key={rowIndex}
|
||||
<div
|
||||
key={rowIndex}
|
||||
className="flex gap-3 justify-center"
|
||||
style={{
|
||||
style={{
|
||||
transform: rowIndex % 2 === 0 ? 'translateX(0)' : 'translateX(80px)',
|
||||
}}
|
||||
>
|
||||
{[...Array(cols)].map((_, colIndex) => (
|
||||
<motion.div
|
||||
<m.div
|
||||
key={`${rowIndex}-${colIndex}`}
|
||||
initial={{ opacity: 0.05 }}
|
||||
animate={{
|
||||
animate={{
|
||||
opacity: [0.05, Math.random() > 0.9 ? 0.25 : 0.05, 0.05],
|
||||
scale: [1, Math.random() > 0.9 ? 1.05 : 1, 1]
|
||||
}}
|
||||
transition={{
|
||||
duration: 5 + Math.random() * 5,
|
||||
repeat: Infinity,
|
||||
transition={{
|
||||
duration: 5 + Math.random() * 5,
|
||||
repeat: Infinity,
|
||||
delay: Math.random() * 20,
|
||||
ease: "easeInOut"
|
||||
}}
|
||||
@@ -46,6 +47,7 @@ export const TileGrid = () => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</LazyMotion>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
2
context/framer-features.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import { domAnimation } from "framer-motion"
|
||||
export default domAnimation
|
||||
BIN
public/media/business/hero-bg.jpg
Normal file
|
After Width: | Height: | Size: 350 KiB |
|
Before Width: | Height: | Size: 6.3 MiB |
|
Before Width: | Height: | Size: 189 KiB |
BIN
public/media/cables/hs-kabel.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/media/drums/about-hero.jpg
Normal file
|
After Width: | Height: | Size: 414 KiB |
|
Before Width: | Height: | Size: 1.6 MiB |
BIN
public/media/laying/contact-hero.jpg
Normal file
|
After Width: | Height: | Size: 736 KiB |
|
Before Width: | Height: | Size: 7.2 MiB |