Compare commits
9 Commits
v2.2.13-rc
...
v2.2.13-rc
| Author | SHA1 | Date | |
|---|---|---|---|
| 5101b8bd1e | |||
| afe3565155 | |||
| e677089ff9 | |||
| b7d9a4b0d0 | |||
| 6c8614f147 | |||
| aa4e121fea | |||
| 6697703c91 | |||
| e779c6ac22 | |||
| 02c4f06108 |
@@ -75,7 +75,7 @@ const Icons = {
|
|||||||
|
|
||||||
export function BenefitGrid({ badge, title, description, benefits }: BenefitGridProps) {
|
export function BenefitGrid({ badge, title, description, benefits }: BenefitGridProps) {
|
||||||
return (
|
return (
|
||||||
<section className="bg-white py-12 md:py-24 relative overflow-hidden border-t border-neutral-100">
|
<section className="bg-white py-16 md:py-24 lg:py-32 relative overflow-hidden border-t border-neutral-100">
|
||||||
<div className="container px-4 max-w-7xl mx-auto relative z-10">
|
<div className="container px-4 max-w-7xl mx-auto relative z-10">
|
||||||
|
|
||||||
<div className="max-w-3xl mx-auto text-center mb-16">
|
<div className="max-w-3xl mx-auto text-center mb-16">
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export function CertificatesBlock({ badge, title, description, certificates = de
|
|||||||
|
|
||||||
if (!isMounted) {
|
if (!isMounted) {
|
||||||
return (
|
return (
|
||||||
<section className="py-12 md:py-24 bg-neutral-50 relative overflow-hidden">
|
<section className="py-16 md:py-24 lg:py-32 bg-neutral-50 relative overflow-hidden">
|
||||||
<Container>
|
<Container>
|
||||||
{!hideHeader && (
|
{!hideHeader && (
|
||||||
<div className="text-center max-w-3xl mx-auto mb-16">
|
<div className="text-center max-w-3xl mx-auto mb-16">
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export function CompanyTimeline({
|
|||||||
const lineHeight = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
|
const lineHeight = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-12 md:py-32 bg-[#FAFAFA] relative overflow-hidden">
|
<section className="py-16 md:py-24 lg:py-32 bg-[#FAFAFA] relative overflow-hidden">
|
||||||
{/* Background Decor */}
|
{/* Background Decor */}
|
||||||
<div className="absolute top-0 right-0 w-[600px] h-[600px] bg-primary/5 rounded-full blur-[100px] pointer-events-none -translate-y-1/2 translate-x-1/3" />
|
<div className="absolute top-0 right-0 w-[600px] h-[600px] bg-primary/5 rounded-full blur-[100px] pointer-events-none -translate-y-1/2 translate-x-1/3" />
|
||||||
<div className="absolute bottom-0 left-0 w-[800px] h-[800px] bg-neutral-200/40 rounded-full blur-[120px] pointer-events-none translate-y-1/3 -translate-x-1/3" />
|
<div className="absolute bottom-0 left-0 w-[800px] h-[800px] bg-neutral-200/40 rounded-full blur-[120px] pointer-events-none translate-y-1/3 -translate-x-1/3" />
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export function CompetenceBentoGrid(props: CompetenceBentoGridProps) {
|
|||||||
// Static fallback for SSR
|
// Static fallback for SSR
|
||||||
if (!isMounted) {
|
if (!isMounted) {
|
||||||
return (
|
return (
|
||||||
<section className="py-12 md:py-24 bg-neutral text-neutral-dark overflow-hidden relative">
|
<section className="py-16 md:py-24 lg:py-32 bg-neutral text-neutral-dark overflow-hidden relative">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-between items-end mb-12">
|
<div className="flex flex-col md:flex-row justify-between items-end mb-12">
|
||||||
<div className="max-w-2xl">
|
<div className="max-w-2xl">
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export const ContactSection: React.FC<ContactSectionProps> = (props) => {
|
|||||||
const { showForm, showMap } = props;
|
const { showForm, showMap } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section className="bg-neutral-light py-12 md:py-28 relative overflow-hidden">
|
<Section className="bg-neutral-light relative overflow-hidden">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 md:gap-16">
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 md:gap-16">
|
||||||
<motion.div
|
<motion.div
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const FaqBlock: React.FC<FaqBlockProps> = ({
|
|||||||
if (!questions || questions.length === 0) return null;
|
if (!questions || questions.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-12 md:py-16">
|
<section className="py-16 md:py-24 lg:py-32">
|
||||||
<div className="max-w-3xl mx-auto">
|
<div className="max-w-3xl mx-auto">
|
||||||
<div className="mb-10 text-center">
|
<div className="mb-10 text-center">
|
||||||
{subtitle && (
|
{subtitle && (
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { MapPin, Factory, Zap, CheckCircle2, ArrowUpRight } from 'lucide-react';
|
import { MapPin, Factory, Zap, CheckCircle2, ArrowUpRight } from 'lucide-react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
import { useRouter, usePathname } from 'next/navigation';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { AnimatedGlossyBorder } from '@/components/ui/AnimatedGlossyBorder';
|
import { AnimatedGlossyBorder } from '@/components/ui/AnimatedGlossyBorder';
|
||||||
import { Location, defaultLocations, minorLocations, projectLocations } from '@/lib/map-data';
|
import { Location, defaultLocations, minorLocations, projectLocations } from '@/lib/map-data';
|
||||||
@@ -38,10 +38,13 @@ export function InteractiveGermanyMap({
|
|||||||
hideStandorte = false
|
hideStandorte = false
|
||||||
}: InteractiveGermanyMapProps) {
|
}: InteractiveGermanyMapProps) {
|
||||||
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
|
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
|
||||||
const [hoverTimeout, setHoverTimeout] = useState<NodeJS.Timeout | null>(null);
|
const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
const handleMouseEnter = (loc: Location) => {
|
const handleMouseEnter = (loc: Location) => {
|
||||||
if (hoverTimeout) clearTimeout(hoverTimeout);
|
if (hoverTimeoutRef.current) {
|
||||||
|
clearTimeout(hoverTimeoutRef.current);
|
||||||
|
hoverTimeoutRef.current = null;
|
||||||
|
}
|
||||||
setActiveLocation(loc);
|
setActiveLocation(loc);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,10 +52,11 @@ export function InteractiveGermanyMap({
|
|||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
setActiveLocation(null);
|
setActiveLocation(null);
|
||||||
}, 200);
|
}, 200);
|
||||||
setHoverTimeout(timeout);
|
hoverTimeoutRef.current = timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
const t = useTranslations('InteractiveGermanyMap');
|
const t = useTranslations('InteractiveGermanyMap');
|
||||||
const tStandard = useTranslations('StandardPage');
|
const tStandard = useTranslations('StandardPage');
|
||||||
@@ -81,15 +85,14 @@ export function InteractiveGermanyMap({
|
|||||||
}, [locations, hideStandorte]);
|
}, [locations, hideStandorte]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={isHero ? "relative w-full" : "relative w-full max-w-7xl mx-auto py-12 md:py-24 px-4 sm:px-6 mt-16 md:mt-20"}>
|
<div key={isHero ? `hero-map-${pathname}` : undefined} className={isHero ? "relative w-full" : "relative w-full max-w-7xl mx-auto py-12 md:py-24 px-4 sm:px-6 mt-16 md:mt-20"}>
|
||||||
<div className={`bg-[#050B14] ${isHero ? 'pt-32 pb-16 md:pt-40 md:pb-24' : 'rounded-[2.5rem] md:rounded-[3.5rem] shadow-2xl border border-white/5'} overflow-visible relative group/map`}>
|
<div className={`bg-[#050B14] ${isHero ? 'pt-32 pb-16 md:pt-40 md:pb-24' : 'rounded-[2.5rem] md:rounded-[3.5rem] shadow-2xl border border-white/5'} overflow-visible relative group/map`}>
|
||||||
{/* Animated Border Glow (disabled in hero due to performance lag on 100vw) */}
|
{/* Animated Border Glow */}
|
||||||
{!isHero && <AnimatedGlossyBorder opacity={0.7} className="z-30" />}
|
{!isHero && <AnimatedGlossyBorder opacity={0.7} className="z-30" />}
|
||||||
|
|
||||||
{/* Background Effects */}
|
{/* Background Effects */}
|
||||||
<div className={`absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322] to-[#050B14] ${!isHero ? 'rounded-[2.5rem] md:rounded-[3.5rem]' : ''} overflow-hidden`}>
|
<div className={`absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322] to-[#050B14] ${!isHero && 'rounded-[2.5rem] md:rounded-[3.5rem]'} overflow-hidden`} />
|
||||||
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-primary/5 rounded-full blur-[120px] pointer-events-none translate-x-1/3 -translate-y-1/3" />
|
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-primary/5 rounded-full blur-[120px] pointer-events-none translate-x-1/3 -translate-y-1/3 overflow-hidden" />
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`relative z-10 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-12 gap-12 items-center min-h-[600px] ${isHero ? 'max-w-7xl mx-auto px-4 sm:px-6' : 'p-8 md:p-12 lg:p-16'}`}>
|
<div className={`relative z-10 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-12 gap-12 items-center min-h-[600px] ${isHero ? 'max-w-7xl mx-auto px-4 sm:px-6' : 'p-8 md:p-12 lg:p-16'}`}>
|
||||||
|
|
||||||
@@ -162,10 +165,12 @@ export function InteractiveGermanyMap({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Minor Location Markers (The 100+ generic projects) */}
|
{/* Minor Location Markers (The 100+ generic projects) */}
|
||||||
{finalLocations.filter(l => l.type === 'minor_node').map((loc, idx) => (
|
{finalLocations.filter(l => l.type === 'minor_node').map((loc, idx) => {
|
||||||
|
const isActive = activeLocation === loc;
|
||||||
|
return (
|
||||||
<div
|
<div
|
||||||
key={`minor-${idx}`}
|
key={`minor-${idx}`}
|
||||||
className="absolute z-10 group/minor cursor-pointer w-10 h-10 flex items-center justify-center"
|
className={`absolute group/minor cursor-pointer w-8 h-8 md:w-5 md:h-5 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-10 hover:z-30'}`}
|
||||||
style={{
|
style={{
|
||||||
left: `${loc.x}%`,
|
left: `${loc.x}%`,
|
||||||
top: `${loc.y}%`,
|
top: `${loc.y}%`,
|
||||||
@@ -173,12 +178,13 @@ export function InteractiveGermanyMap({
|
|||||||
}}
|
}}
|
||||||
onMouseEnter={() => handleMouseEnter(loc)}
|
onMouseEnter={() => handleMouseEnter(loc)}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
|
onTouchStart={() => handleMouseEnter(loc)}
|
||||||
onClick={() => handleMouseEnter(loc)}
|
onClick={() => handleMouseEnter(loc)}
|
||||||
>
|
>
|
||||||
<div className="w-1.5 h-1.5 bg-primary/80 rounded-full group-hover/minor:bg-white group-hover/minor:scale-150 transition-all duration-300" />
|
<div className={`w-1.5 h-1.5 rounded-full transition-all duration-300 ${isActive ? 'bg-white scale-150 shadow-[0_0_10px_rgba(130,237,32,1)]' : 'bg-primary/80 group-hover/minor:bg-white group-hover/minor:scale-150'}`} />
|
||||||
<div className="absolute inset-0 m-auto w-2 h-2 bg-primary rounded-full opacity-0 group-hover/minor:animate-ping" />
|
<div className="absolute inset-0 m-auto w-2 h-2 bg-primary rounded-full opacity-0 group-hover/minor:animate-ping" />
|
||||||
</div>
|
</div>
|
||||||
))}
|
)})}
|
||||||
|
|
||||||
{/* Major Location Markers (HQ, Branch, Project) */}
|
{/* Major Location Markers (HQ, Branch, Project) */}
|
||||||
{finalLocations.filter(l => l.type !== 'minor_node').map((loc, idx) => {
|
{finalLocations.filter(l => l.type !== 'minor_node').map((loc, idx) => {
|
||||||
@@ -189,10 +195,11 @@ export function InteractiveGermanyMap({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={loc.id}
|
key={loc.id}
|
||||||
className={`absolute transform -translate-x-1/2 -translate-y-1/2 group/pin cursor-pointer w-16 h-16 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-20'}`}
|
className={`absolute transform -translate-x-1/2 -translate-y-1/2 group/pin cursor-pointer w-16 h-16 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-20 hover:z-40'}`}
|
||||||
style={{ left: `${loc.x}%`, top: `${loc.y}%` }}
|
style={{ left: `${loc.x}%`, top: `${loc.y}%` }}
|
||||||
onMouseEnter={() => handleMouseEnter(loc)}
|
onMouseEnter={() => handleMouseEnter(loc)}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
|
onTouchStart={() => handleMouseEnter(loc)}
|
||||||
onClick={() => handleMouseEnter(loc)}
|
onClick={() => handleMouseEnter(loc)}
|
||||||
>
|
>
|
||||||
{/* Ping Animation for HQ / Branch */}
|
{/* Ping Animation for HQ / Branch */}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export function ReferencesSlider(props: ReferencesSliderProps) {
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="referenzen" className="py-12 md:py-24 bg-neutral-dark text-white relative overflow-hidden">
|
<section id="referenzen" className="py-16 md:py-24 lg:py-32 bg-neutral-dark text-white relative overflow-hidden">
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-neutral-dark via-neutral-900 to-neutral-dark z-0" />
|
<div className="absolute inset-0 bg-gradient-to-b from-neutral-dark via-neutral-900 to-neutral-dark z-0" />
|
||||||
|
|
||||||
<div className="container relative z-10 mb-12 flex flex-col md:flex-row justify-between items-end gap-6">
|
<div className="container relative z-10 mb-12 flex flex-col md:flex-row justify-between items-end gap-6">
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export function ServiceDetailGrid({
|
|||||||
panels
|
panels
|
||||||
}: ServiceDetailGridProps) {
|
}: ServiceDetailGridProps) {
|
||||||
return (
|
return (
|
||||||
<section className="bg-neutral-50 py-12 md:py-24 border-b border-neutral-100 relative overflow-hidden">
|
<section className="bg-neutral-50 py-16 md:py-24 lg:py-32 border-b border-neutral-100 relative overflow-hidden">
|
||||||
|
|
||||||
<div className="container relative z-10 px-4 max-w-7xl mx-auto">
|
<div className="container relative z-10 px-4 max-w-7xl mx-auto">
|
||||||
<div className="max-w-3xl mb-12 md:mb-20 text-left">
|
<div className="max-w-3xl mb-12 md:mb-20 text-left">
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export function SubCompanyTiles(props: SubCompanyTilesProps) {
|
|||||||
})) || defaultCompanies;
|
})) || defaultCompanies;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="unternehmen" className="py-12 md:py-24 bg-neutral-dark border-b border-neutral-800 relative overflow-hidden">
|
<section id="unternehmen" className="py-16 md:py-24 lg:py-32 bg-neutral-dark border-b border-neutral-800 relative overflow-hidden">
|
||||||
<div className="container relative z-10 px-4">
|
<div className="container relative z-10 px-4">
|
||||||
|
|
||||||
{(badge || title) && (
|
{(badge || title) && (
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function TeamGrid({ members }: TeamGridProps) {
|
|||||||
if (!members || members.length === 0) return null;
|
if (!members || members.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-12 md:py-24 bg-white relative overflow-hidden">
|
<section className="py-16 md:py-24 lg:py-32 bg-white relative overflow-hidden">
|
||||||
<div className="container relative z-10">
|
<div className="container relative z-10">
|
||||||
<div className="mb-12">
|
<div className="mb-12">
|
||||||
<h2 className="text-primary font-bold tracking-wider uppercase text-sm mb-3">{t('badge')}</h2>
|
<h2 className="text-primary font-bold tracking-wider uppercase text-sm mb-3">{t('badge')}</h2>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export default function CTA({ data }: { data?: any }) {
|
|||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section className="bg-primary text-white py-16 md:py-32 relative overflow-hidden">
|
<Section className="bg-primary text-white relative overflow-hidden">
|
||||||
<div className="absolute top-0 right-0 w-1/3 h-full bg-accent/5 -skew-x-12 translate-x-1/2" />
|
<div className="absolute top-0 right-0 w-1/3 h-full bg-accent/5 -skew-x-12 translate-x-1/2" />
|
||||||
<div className="absolute bottom-0 left-0 w-1/4 h-1/2 bg-primary/10 rounded-full blur-3xl -translate-x-1/2 translate-y-1/2" />
|
<div className="absolute bottom-0 left-0 w-1/4 h-1/2 bg-primary/10 rounded-full blur-3xl -translate-x-1/2 translate-y-1/2" />
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export default function Experience({ data }: { data?: any }) {
|
|||||||
const t = useTranslations('Home.experience');
|
const t = useTranslations('Home.experience');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section className="relative py-16 md:py-48 overflow-hidden text-white">
|
<Section className="relative overflow-hidden text-white">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
<Image
|
<Image
|
||||||
src="/uploads/2024/12/1694273920124-copy-2.webp"
|
src="/uploads/2024/12/1694273920124-copy-2.webp"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export default function GallerySection({ data }: { data?: any }) {
|
|||||||
const lightboxIndex = photoParam ? parseInt(photoParam, 10) : 0;
|
const lightboxIndex = photoParam ? parseInt(photoParam, 10) : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section className="bg-white text-white py-16 md:py-32">
|
<Section className="bg-white text-white">
|
||||||
<Container>
|
<Container>
|
||||||
<Heading level={2} subtitle={data?.subtitle || t('subtitle')} align="center">
|
<Heading level={2} subtitle={data?.subtitle || t('subtitle')} align="center">
|
||||||
{data?.title || t('title')}
|
{data?.title || t('title')}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function MeetTheTeam({ data }: { data?: any }) {
|
|||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section className="relative py-16 md:py-48 overflow-hidden">
|
<Section className="relative overflow-hidden">
|
||||||
<div className="absolute inset-0 z-0">
|
<div className="absolute inset-0 z-0">
|
||||||
<Image
|
<Image
|
||||||
src="/uploads/2024/12/DSC08036-Large.webp"
|
src="/uploads/2024/12/DSC08036-Large.webp"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function Footer({ companyInfo }: FooterProps) {
|
|||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-[#050B14] text-neutral-light pt-40 pb-10 md:pt-16 md:pb-16 relative overflow-hidden border-t border-white/5">
|
<footer className="bg-[#050B14] text-neutral-light pt-40 pb-10 md:pt-40 md:pb-16 relative overflow-hidden border-t border-white/5">
|
||||||
{/* Subtle background tech grid */}
|
{/* Subtle background tech grid */}
|
||||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#8080800a_1px,transparent_1px),linear-gradient(to_bottom,#8080800a_1px,transparent_1px)] bg-[size:32px_32px] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_100%)] pointer-events-none" />
|
<div className="absolute inset-0 bg-[linear-gradient(to_right,#8080800a_1px,transparent_1px),linear-gradient(to_bottom,#8080800a_1px,transparent_1px)] bg-[size:32px_32px] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_100%)] pointer-events-none" />
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default function Gallery() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section className="bg-primary-dark py-16 md:py-32">
|
<Section className="bg-primary-dark">
|
||||||
<Container>
|
<Container>
|
||||||
<Heading level={2} subtitle={t('gallery.subtitle')} align="center" className="text-white mb-12 md:mb-20">
|
<Heading level={2} subtitle={t('gallery.subtitle')} align="center" className="text-white mb-12 md:mb-20">
|
||||||
<span className="text-white">{t('gallery.title')}</span>
|
<span className="text-white">{t('gallery.title')}</span>
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ interface AnimatedGlossyBorderProps {
|
|||||||
borderWidth?: 1 | 2;
|
borderWidth?: 1 | 2;
|
||||||
opacity?: number;
|
opacity?: number;
|
||||||
color?: 'white' | 'primary';
|
color?: 'white' | 'primary';
|
||||||
|
disableAnimation?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AnimatedGlossyBorder({
|
export function AnimatedGlossyBorder({
|
||||||
className,
|
className,
|
||||||
borderWidth = 1,
|
borderWidth = 1,
|
||||||
color = 'white'
|
color = 'white',
|
||||||
|
disableAnimation = false
|
||||||
}: AnimatedGlossyBorderProps) {
|
}: AnimatedGlossyBorderProps) {
|
||||||
const isWhite = color === 'white';
|
const isWhite = color === 'white';
|
||||||
const glowColor = isWhite ? 'rgba(255,255,255,0.6)' : 'rgba(17,124,97,0.6)';
|
const glowColor = isWhite ? 'rgba(255,255,255,0.6)' : 'rgba(17,124,97,0.6)';
|
||||||
@@ -35,7 +37,10 @@ export function AnimatedGlossyBorder({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[250%] aspect-square animate-[spin_8s_linear_infinite]"
|
className={cn(
|
||||||
|
"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[250%] aspect-square",
|
||||||
|
!disableAnimation && "animate-[spin_8s_linear_infinite]"
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
background: `conic-gradient(from 0deg, ${gradientColors})`
|
background: `conic-gradient(from 0deg, ${gradientColors})`
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { cn } from './utils';
|
|||||||
|
|
||||||
export function Section({ className, children, ...props }: React.HTMLAttributes<HTMLElement>) {
|
export function Section({ className, children, ...props }: React.HTMLAttributes<HTMLElement>) {
|
||||||
return (
|
return (
|
||||||
<section className={cn('py-12 md:py-28 lg:py-36 overflow-hidden content-visibility-auto', className)} {...props}>
|
<section className={cn('py-16 md:py-24 lg:py-32 overflow-hidden content-visibility-auto', className)} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
2020
lib/map-data.ts
2020
lib/map-data.ts
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { defaultLocations } from '../lib/map-data';
|
import { defaultLocations, minorLocations } from '../lib/map-data';
|
||||||
|
|
||||||
describe('Task 12 TDD - Bohrtechnik and Reference Links', () => {
|
describe('Task 12 TDD - Bohrtechnik and Reference Links', () => {
|
||||||
const deHomePath = path.join(process.cwd(), 'content', 'de', 'home.mdx');
|
const deHomePath = path.join(process.cwd(), 'content', 'de', 'home.mdx');
|
||||||
@@ -27,10 +27,11 @@ describe('Task 12 TDD - Bohrtechnik and Reference Links', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should verify that all reference projects in map-data have no href links', () => {
|
it('should verify that all reference projects in map-data have no href links', () => {
|
||||||
// Check that all defaultLocations of type 'project' have href undefined or removed
|
// Check that all minorLocations of type 'minor_node' have href undefined
|
||||||
const projects = defaultLocations.filter(loc => loc.type === 'project');
|
// since all projects were downgraded to minor nodes without links.
|
||||||
|
const projects = minorLocations.filter(loc => loc.type === 'minor_node');
|
||||||
expect(projects.length).toBeGreaterThan(0);
|
expect(projects.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
projects.forEach(project => {
|
projects.forEach(project => {
|
||||||
expect(project.href).toBeUndefined();
|
expect(project.href).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user