Retour au catalogue

Mega Footer Magazine

Footer style magazine avec colonnes editoriales, articles recents et mise en page typographique.

mega-footermedium Both Responsive a11y
editorialelegantagencyportfoliogrid
Theme
"use client";

import { motion } from "framer-motion";
import { ArrowUpRight, Newspaper } from "lucide-react";

interface FooterLink {
  label: string;
  href: string;
}

interface FooterColumn {
  title: string;
  links: FooterLink[];
}

interface RecentArticle {
  title: string;
  date: string;
  href: string;
}

interface MegaFooterMagazineProps {
  companyName?: string;
  tagline?: string;
  columns?: FooterColumn[];
  recentArticles?: RecentArticle[];
  copyright?: string;
}

const EASE = [0.16, 1, 0.3, 1] as const;

export default function MegaFooterMagazine({
  companyName = "Revue Digitale",
  tagline = "L'actualite tech et design, chaque semaine.",
  columns = [],
  recentArticles = [],
  copyright = "2026 Revue Digitale. Tous droits reserves.",
}: MegaFooterMagazineProps) {
  return (
    <footer
      style={{
        paddingTop: "var(--section-padding-y)",
        paddingBottom: "2rem",
        background: "var(--color-background-alt)",
        borderTop: "1px solid var(--color-border)",
      }}
    >
      <div
        style={{
          maxWidth: "var(--container-max-width)",
          margin: "0 auto",
          padding: "0 var(--container-padding-x)",
        }}
      >
        {/* Top: masthead-style branding */}
        <motion.div
          initial={{ opacity: 0, y: 16 }}
          whileInView={{ opacity: 1, y: 0 }}
          viewport={{ once: true }}
          transition={{ duration: 0.5, ease: EASE }}
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            flexWrap: "wrap",
            gap: "1rem",
            paddingBottom: "2rem",
            borderBottom: "2px solid var(--color-foreground)",
            marginBottom: "2.5rem",
          }}
        >
          <div style={{ display: "flex", alignItems: "center", gap: "0.75rem" }}>
            <Newspaper
              style={{ width: 28, height: 28, color: "var(--color-foreground)" }}
            />
            <h2
              style={{
                fontSize: "clamp(1.5rem, 3vw, 2rem)",
                fontWeight: 800,
                color: "var(--color-foreground)",
                letterSpacing: "-0.02em",
                textTransform: "uppercase",
              }}
            >
              {companyName}
            </h2>
          </div>
          <p
            style={{
              fontSize: "0.875rem",
              color: "var(--color-foreground-muted)",
              fontStyle: "italic",
            }}
          >
            {tagline}
          </p>
        </motion.div>

        {/* Content grid: columns + recent articles */}
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
            gap: "2.5rem",
            marginBottom: "3rem",
          }}
        >
          {/* Link columns */}
          {columns.map((column, ci) => (
            <motion.div
              key={ci}
              initial={{ opacity: 0, y: 12 }}
              whileInView={{ opacity: 1, y: 0 }}
              viewport={{ once: true }}
              transition={{ duration: 0.4, delay: 0.05 * ci, ease: EASE }}
            >
              <h3
                style={{
                  fontSize: "0.6875rem",
                  fontWeight: 700,
                  textTransform: "uppercase",
                  letterSpacing: "0.12em",
                  color: "var(--color-foreground)",
                  marginBottom: "1rem",
                  paddingBottom: "0.5rem",
                  borderBottom: "1px solid var(--color-border)",
                }}
              >
                {column.title}
              </h3>
              <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: "0.625rem" }}>
                {column.links.map((link, li) => (
                  <li key={li}>
                    <a
                      href={link.href}
                      style={{
                        fontSize: "0.875rem",
                        color: "var(--color-foreground-muted)",
                        textDecoration: "none",
                        transition: "color 0.2s",
                      }}
                      onMouseEnter={(e) => (e.currentTarget.style.color = "var(--color-accent)")}
                      onMouseLeave={(e) => (e.currentTarget.style.color = "var(--color-foreground-muted)")}
                    >
                      {link.label}
                    </a>
                  </li>
                ))}
              </ul>
            </motion.div>
          ))}

          {/* Recent articles column */}
          {recentArticles.length > 0 && (
            <motion.div
              initial={{ opacity: 0, y: 12 }}
              whileInView={{ opacity: 1, y: 0 }}
              viewport={{ once: true }}
              transition={{ duration: 0.4, delay: 0.15, ease: EASE }}
              style={{ gridColumn: "span 1" }}
            >
              <h3
                style={{
                  fontSize: "0.6875rem",
                  fontWeight: 700,
                  textTransform: "uppercase",
                  letterSpacing: "0.12em",
                  color: "var(--color-foreground)",
                  marginBottom: "1rem",
                  paddingBottom: "0.5rem",
                  borderBottom: "1px solid var(--color-border)",
                }}
              >
                Articles recents
              </h3>
              <div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
                {recentArticles.map((article, ai) => (
                  <a
                    key={ai}
                    href={article.href}
                    style={{
                      display: "block",
                      textDecoration: "none",
                      paddingBottom: ai < recentArticles.length - 1 ? "1rem" : 0,
                      borderBottom:
                        ai < recentArticles.length - 1
                          ? "1px solid var(--color-border)"
                          : "none",
                    }}
                  >
                    <p
                      style={{
                        fontSize: "0.875rem",
                        fontWeight: 600,
                        color: "var(--color-foreground)",
                        lineHeight: 1.4,
                        marginBottom: "0.25rem",
                      }}
                    >
                      {article.title}
                      <ArrowUpRight
                        style={{
                          display: "inline",
                          width: 14,
                          height: 14,
                          marginLeft: 4,
                          verticalAlign: "middle",
                          color: "var(--color-accent)",
                        }}
                      />
                    </p>
                    <span
                      style={{
                        fontSize: "0.75rem",
                        color: "var(--color-foreground-muted)",
                      }}
                    >
                      {article.date}
                    </span>
                  </a>
                ))}
              </div>
            </motion.div>
          )}
        </div>

        {/* Bottom bar */}
        <div
          style={{
            borderTop: "1px solid var(--color-border)",
            paddingTop: "1.5rem",
            textAlign: "center",
          }}
        >
          <p style={{ fontSize: "0.75rem", color: "var(--color-foreground-muted)" }}>
            {copyright}
          </p>
        </div>
      </div>
    </footer>
  );
}

Avis

Mega Footer Magazine — React Mega-footer Section — Incubator