Retour au catalogue

Mobile App Device

Mockup de telephone centre avec ecran placeholder, texte descriptif, stats et badges store.

mobile-appmedium Both Responsive a11y
minimalcorporatesaasuniversalcentered
Theme
"use client";

import { motion } from "framer-motion";
import { Star, Download } from "lucide-react";

interface MobileAppDeviceProps {
  title?: string;
  titleAccent?: string;
  description?: string;
  badge?: string;
  rating?: string;
  downloads?: string;
  appStoreCta?: string;
  playStoreCta?: string;
  screenColor?: string;
}

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

export default function MobileAppDevice({
  title = "Votre application mobile",
  titleAccent = "intuitive",
  description = "Une experience mobile fluide et performante.",
  badge = "Disponible maintenant",
  rating = "4.9",
  downloads = "100k+",
  appStoreCta = "App Store",
  playStoreCta = "Google Play",
  screenColor = "var(--color-accent-subtle)",
}: MobileAppDeviceProps) {
  return (
    <section
      style={{
        position: "relative",
        overflow: "hidden",
        paddingTop: "var(--section-padding-y-lg)",
        paddingBottom: "var(--section-padding-y-lg)",
        background: "var(--color-background)",
      }}
    >
      <div
        style={{
          width: "100%",
          maxWidth: "var(--container-max-width)",
          margin: "0 auto",
          padding: "0 var(--container-padding-x)",
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          gap: "3rem",
        }}
      >
        {/* Text content */}
        <div style={{ textAlign: "center", maxWidth: "600px" }}>
          {badge && (
            <motion.span
              initial={{ opacity: 0, y: 8 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.4, ease: EASE }}
              style={{
                display: "inline-block",
                padding: "0.5rem 1.25rem",
                borderRadius: "var(--radius-full)",
                border: "1px solid var(--color-accent-border)",
                background: "var(--color-accent-subtle)",
                fontSize: "0.8125rem",
                fontWeight: 500,
                color: "var(--color-foreground-muted)",
                marginBottom: "1.5rem",
              }}
            >
              {badge}
            </motion.span>
          )}

          <motion.h2
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.6, delay: 0.06, ease: EASE }}
            style={{
              fontFamily: "var(--font-sans)",
              fontSize: "clamp(2rem, 4vw, 3.5rem)",
              fontWeight: 700,
              lineHeight: 1.1,
              letterSpacing: "-0.03em",
              color: "var(--color-foreground)",
              marginBottom: "1rem",
            }}
          >
            {title}{" "}
            <em
              style={{
                fontFamily: "var(--font-serif)",
                fontStyle: "italic",
                fontWeight: 400,
                color: "var(--color-accent)",
              }}
            >
              {titleAccent}
            </em>
          </motion.h2>

          <motion.p
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.5, delay: 0.12, ease: EASE }}
            style={{
              fontSize: "1.125rem",
              lineHeight: 1.7,
              color: "var(--color-foreground-muted)",
              marginBottom: "1.5rem",
            }}
          >
            {description}
          </motion.p>

          {/* Stats row */}
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            transition={{ duration: 0.5, delay: 0.18, ease: EASE }}
            style={{ display: "flex", justifyContent: "center", gap: "2rem", marginBottom: "1.5rem" }}
          >
            <div style={{ display: "flex", alignItems: "center", gap: "0.375rem", color: "var(--color-foreground-muted)", fontSize: "0.875rem" }}>
              <Star style={{ width: 16, height: 16, color: "var(--color-accent)" }} />
              <span style={{ fontWeight: 600, color: "var(--color-foreground)" }}>{rating}</span> note
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: "0.375rem", color: "var(--color-foreground-muted)", fontSize: "0.875rem" }}>
              <Download style={{ width: 16, height: 16, color: "var(--color-accent)" }} />
              <span style={{ fontWeight: 600, color: "var(--color-foreground)" }}>{downloads}</span> telechargements
            </div>
          </motion.div>

          {/* Store buttons */}
          <motion.div
            initial={{ opacity: 0, y: 8 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.45, delay: 0.24, ease: EASE }}
            style={{ display: "flex", justifyContent: "center", gap: "0.75rem", flexWrap: "wrap" }}
          >
            {[appStoreCta, playStoreCta].map((label) => (
              <a
                key={label}
                href="#"
                style={{
                  display: "inline-flex",
                  alignItems: "center",
                  gap: "8px",
                  padding: "0.75rem 1.75rem",
                  borderRadius: "var(--radius-md)",
                  background: "var(--color-foreground)",
                  color: "var(--color-background)",
                  fontWeight: 600,
                  fontSize: "0.875rem",
                  textDecoration: "none",
                }}
              >
                {label}
              </a>
            ))}
          </motion.div>
        </div>

        {/* Phone mockup */}
        <motion.div
          initial={{ opacity: 0, y: 40 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.7, delay: 0.3, ease: EASE }}
          style={{
            width: 280,
            height: 560,
            borderRadius: 40,
            border: `3px solid var(--color-border)`,
            background: "var(--color-background-card)",
            padding: 12,
            boxShadow: "0 24px 60px rgba(0,0,0,0.15)",
          }}
        >
          {/* Notch */}
          <div
            style={{
              width: 120,
              height: 28,
              borderRadius: "0 0 16px 16px",
              background: "var(--color-background-card)",
              margin: "0 auto",
              position: "relative",
              top: -12,
              zIndex: 2,
              border: `2px solid var(--color-border)`,
              borderTop: "none",
            }}
          />
          {/* Screen placeholder */}
          <div
            style={{
              width: "100%",
              height: "calc(100% - 20px)",
              borderRadius: 28,
              background: screenColor,
              marginTop: -8,
            }}
          />
        </motion.div>
      </div>
    </section>
  );
}

Avis

Mobile App Device — React Mobile-app Section — Incubator