Retour au catalogue
Careers Benefits Visual
Avantages affiches en cartes visuelles avec icones et animations de revelation au scroll.
careersmedium Both Responsive a11y
playfulelegantboldsaasuniversalgrid
Theme
"use client";
import { motion } from "framer-motion";
import {
Laptop,
GraduationCap,
HeartPulse,
Plane,
Baby,
Dumbbell,
PiggyBank,
Utensils,
} from "lucide-react";
import type { LucideIcon } from "lucide-react";
interface Benefit {
icon: string;
title: string;
description: string;
}
interface CareersBenefitsVisualProps {
title?: string;
subtitle?: string;
benefits?: Benefit[];
}
const EASE = [0.16, 1, 0.3, 1] as const;
const ICON_MAP: Record<string, LucideIcon> = {
laptop: Laptop,
"graduation-cap": GraduationCap,
"heart-pulse": HeartPulse,
plane: Plane,
baby: Baby,
dumbbell: Dumbbell,
"piggy-bank": PiggyBank,
utensils: Utensils,
};
export default function CareersBenefitsVisual({
title = "Pourquoi nous rejoindre",
subtitle = "Des avantages concrets.",
benefits = [],
}: CareersBenefitsVisualProps) {
return (
<section style={{ paddingTop: "var(--section-padding-y-lg)", paddingBottom: "var(--section-padding-y-lg)", background: "var(--color-background)" }}>
<div style={{ maxWidth: "var(--container-max-width)", margin: "0 auto", padding: "0 var(--container-padding-x)" }}>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, ease: EASE }}
style={{ textAlign: "center", maxWidth: 560, margin: "0 auto 3rem" }}
>
<h2 style={{ fontFamily: "var(--font-sans)", fontSize: "clamp(1.75rem, 3vw, 2.5rem)", fontWeight: 700, color: "var(--color-foreground)", marginBottom: "0.75rem" }}>{title}</h2>
<p style={{ fontSize: "1.0625rem", color: "var(--color-foreground-muted)", lineHeight: 1.7 }}>{subtitle}</p>
</motion.div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: "1.25rem" }}>
{benefits.map((b, i) => {
const Icon = ICON_MAP[b.icon] ?? Laptop;
return (
<motion.div
key={b.title}
initial={{ opacity: 0, y: 24, scale: 0.96 }}
whileInView={{ opacity: 1, y: 0, scale: 1 }}
viewport={{ once: true, margin: "-30px" }}
transition={{ duration: 0.5, delay: i * 0.05, ease: EASE }}
whileHover={{ y: -4, transition: { duration: 0.2 } }}
style={{ padding: "1.5rem", borderRadius: "var(--radius-xl)", border: "1px solid var(--color-border)", background: "var(--color-background-card)", textAlign: "center", cursor: "default" }}
>
<motion.div
initial={{ scale: 0 }}
whileInView={{ scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.4, delay: 0.1 + i * 0.05, ease: EASE, type: "spring", stiffness: 200 }}
style={{ width: 52, height: 52, borderRadius: "var(--radius-lg)", background: "var(--color-accent-subtle)", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 1rem" }}
>
<Icon style={{ width: 24, height: 24, color: "var(--color-accent)" }} />
</motion.div>
<h3 style={{ fontFamily: "var(--font-sans)", fontSize: "0.9375rem", fontWeight: 700, color: "var(--color-foreground)", marginBottom: "0.4rem" }}>{b.title}</h3>
<p style={{ fontSize: "0.8125rem", lineHeight: 1.6, color: "var(--color-foreground-muted)" }}>{b.description}</p>
</motion.div>
);
})}
</div>
</div>
</section>
);
}