style: finalize industrial design system and fix typography conflicts
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 22s
Build & Deploy / 🧪 QA (push) Failing after 1m5s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 22s
Build & Deploy / 🧪 QA (push) Failing after 1m5s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
- Refactor app/[locale]/[slug]/page.tsx to handle fullBleed layouts cleanly - Fix heading styling on 'About Us' and other MDX pages - Implement staggered Framer Motion animations across all core blocks - Resolve InteractiveGermanyMap reference error - Standardize typography tokens for prose and custom headings - Consolidate support CTA placement
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
export interface JobListingBlockProps {
|
||||
title?: string;
|
||||
@@ -21,7 +24,27 @@ export interface JobListingBlockProps {
|
||||
emptyStateLinkHref?: string;
|
||||
}
|
||||
|
||||
export const JobListingBlock = async (props: JobListingBlockProps) => {
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.15,
|
||||
delayChildren: 0.1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { opacity: 0, y: 30 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] },
|
||||
},
|
||||
};
|
||||
|
||||
export const JobListingBlock = (props: JobListingBlockProps) => {
|
||||
const {
|
||||
title,
|
||||
showJobs = true,
|
||||
@@ -45,11 +68,23 @@ export const JobListingBlock = async (props: JobListingBlockProps) => {
|
||||
<div className="container mx-auto">
|
||||
{showFairs && (
|
||||
<div className="mb-24 relative">
|
||||
<h3 className="font-heading font-extrabold text-4xl text-neutral-dark mb-12 flex items-center gap-4">
|
||||
<motion.h3
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
|
||||
className="font-heading font-extrabold text-4xl text-neutral-dark mb-12 flex items-center gap-4"
|
||||
>
|
||||
<span className="w-12 h-1.5 bg-primary rounded-full" />
|
||||
{fairsTitle}
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
</motion.h3>
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
|
||||
>
|
||||
{fairs.map((messe, idx) => {
|
||||
const isLink = !!messe.url;
|
||||
const innerContent = (
|
||||
@@ -120,58 +155,77 @@ export const JobListingBlock = async (props: JobListingBlockProps) => {
|
||||
|
||||
if (isLink) {
|
||||
return (
|
||||
<a key={`fair-${idx}`} href={messe.url} target="_blank" rel="noopener noreferrer" className={`${baseClasses} cursor-pointer`}>
|
||||
<motion.a variants={itemVariants} key={`fair-${idx}`} href={messe.url} target="_blank" rel="noopener noreferrer" className={`${baseClasses} cursor-pointer`}>
|
||||
{innerContent}
|
||||
</a>
|
||||
</motion.a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={`fair-${idx}`} className={baseClasses}>
|
||||
<motion.div variants={itemVariants} key={`fair-${idx}`} className={baseClasses}>
|
||||
{innerContent}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showJobs && (
|
||||
<div className="mb-12">
|
||||
<h2 className="font-heading font-extrabold text-4xl text-neutral-dark mb-8">
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
|
||||
className="font-heading font-extrabold text-4xl text-neutral-dark mb-8"
|
||||
>
|
||||
{title || 'Aktuelle Stellenangebote'}
|
||||
</h2>
|
||||
</motion.h2>
|
||||
|
||||
{jobs.length > 0 ? (
|
||||
<div className="grid gap-6">
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
className="grid gap-6"
|
||||
>
|
||||
{jobs.map((job: any) => (
|
||||
<Link
|
||||
key={job.id}
|
||||
href={`/karriere/${job.slug}`}
|
||||
className="group bg-white border border-neutral-100 p-8 rounded-2xl shadow-sm hover:shadow-xl hover:border-primary/20 transition-all flex flex-col md:flex-row md:items-center justify-between gap-6"
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<span className="px-3 py-1 bg-primary/10 text-primary text-xs font-bold rounded-full uppercase">{job.type}</span>
|
||||
<span className="text-text-secondary text-sm font-medium">{job.department}</span>
|
||||
<motion.div variants={itemVariants} key={job.id}>
|
||||
<Link
|
||||
href={`/karriere/${job.slug}`}
|
||||
className="group bg-white border border-neutral-100 p-8 rounded-2xl shadow-sm hover:shadow-xl hover:border-primary/20 transition-all flex flex-col md:flex-row md:items-center justify-between gap-6 block"
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<span className="px-3 py-1 bg-primary/10 text-primary text-xs font-bold rounded-full uppercase">{job.type}</span>
|
||||
<span className="text-text-secondary text-sm font-medium">{job.department}</span>
|
||||
</div>
|
||||
<h4 className="font-heading font-bold text-2xl text-neutral-dark group-hover:text-primary transition-colors">{job.title}</h4>
|
||||
<p className="text-text-secondary mt-1">{job.location}</p>
|
||||
</div>
|
||||
<h4 className="font-heading font-bold text-2xl text-neutral-dark group-hover:text-primary transition-colors">{job.title}</h4>
|
||||
<p className="text-text-secondary mt-1">{job.location}</p>
|
||||
</div>
|
||||
<div className="flex items-center text-primary font-bold group-hover:translate-x-2 transition-transform">
|
||||
Details ansehen
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5 ml-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex items-center text-primary font-bold group-hover:translate-x-2 transition-transform">
|
||||
Details ansehen
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5 ml-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
||||
</div>
|
||||
</Link>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
) : (
|
||||
<div className="bg-neutral-50 border border-neutral-100 rounded-2xl p-12 text-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
|
||||
className="bg-neutral-50 border border-neutral-100 rounded-2xl p-12 text-center"
|
||||
>
|
||||
<p className="text-text-secondary text-lg">{emptyStateMessage}</p>
|
||||
<Button href={emptyStateLinkHref} variant="primary" className="mt-6">
|
||||
{emptyStateLinkText}
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user