Retour au catalogue

About Team Intro

Section about avec focus sur l'equipe : photo de groupe et chiffres cles.

aboutsimple Both Responsive a11y
corporateorganicuniversalagencysplit
Theme

Cómo crear una sección About con intro de equipo en React

Una sección about-team-intro en React usa una cuadrícula de dos columnas: la columna izquierda contiene un badge, un título, una descripción y filas de destacados animadas que se deslizan desde la izquierda al hacer scroll; la columna derecha muestra una imagen cuadrada del equipo que aparece con fundido y un ligero scale. Ambas columnas usan whileInView de Framer Motion con once:true para animarse exactamente una vez cuando el usuario pasa con el scroll.

  • Stack: React 18, Framer Motion 11, Lucide React, Tailwind v4. ~145 líneas, cero dependencias runtime adicionales.
  • Los iconos se resuelven dinámicamente desde el namespace lucide-react, cualquier nombre de icono Lucide puede pasarse como prop string.
  • Totalmente personalizable mediante propiedades CSS custom (--color-accent, --color-background-alt, --radius-md, etc.), sin colores codificados en duro.
  • Accesible: section semántica + h2, los iconos son decorativos (aria-hidden por defecto vía Lucide), responsive hasta 375px.
  • Todas las props son opcionales, el badge, la imagen y los highlights pueden omitirse sin romper el layout.

About Team Intro es una sección React en dos columnas que combina un bloque de texto con una foto de equipo para dar un rostro al producto. La parte izquierda lleva un badge, título, párrafo y una lista vertical de destacados ilustrados con iconos; la parte derecha enmarca una imagen cuadrada que entra con un sutil scale al hacer scroll. En conjunto transmiten confianza y cultura sin añadir carga cognitiva.

Anatomía

Una sección a todo el ancho con un contenedor centrado max-w-6xl contiene una cuadrícula CSS responsive (1 columna en móvil, 2 en md+). La columna izquierda es un motion.div que agrupa un badge pill opcional, un título h2, un párrafo de descripción y una lista flex-col de filas de destacados. Cada fila es su propio motion.div con un contenedor de icono opcional (cuadrado redondeado 10×10 con fondo accent tintado) y un par de textos (label en semibold + descripción en muted). La columna derecha es un motion.div cuadrado con overflow:hidden que muestra la imagen del equipo como background-image CSS.

Cómo funciona

Dos patrones de entrada de Framer Motion distintos corren en paralelo. La columna izquierda usa initial:{opacity:0, y:20} con whileInView:{opacity:1, y:0}, una duración de 500ms y un margen de viewport de -80px para que la animación se dispare un poco antes de que el elemento entre en el viewport. Cada fila de destacados añade un retraso escalonado de 100ms + (index × 80ms) y se desliza desde x:-12 en lugar de y, dando a la lista un efecto cascada. La columna derecha usa initial:{opacity:0, scale:0.96} con una curva cubic-bezier personalizada [0.16, 1, 0.3, 1] sobre 600ms para un sutil pop tipo spring. Todas las animaciones se disparan una sola vez (once:true) sin importar el re-scroll.

Cómo crearlo en React

  1. Configurar la cuadrícula de dos columnas

    Crea una section con un contenedor centrado max-w-6xl. Dentro, usa una cuadrícula CSS que pasa a una columna en móvil y a dos en el breakpoint md. Añade items-center para alinear verticalmente las columnas cuando sus alturas difieren.

    <div className="grid grid-cols-1 gap-12 items-center md:grid-cols-2">
      {/* text column */}
      {/* image column */}
    </div>
  2. Animar la columna de texto al hacer scroll

    Envuelve la columna de texto en un motion.div con opacity inicial a 0 y un desplazamiento y de 20px. Usa whileInView para restaurarlos y configura viewport en once:true con un margen de -80px para que el fade comience antes de que el elemento entre por completo en la pantalla.

    <motion.div
      initial={{ opacity: 0, y: 20 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, margin: "-80px" }}
      transition={{ duration: 0.5 }}
    >
  3. Escalonar las filas de destacados

    Cada fila es un motion.div separado que se desliza desde x:-12. Añade un retraso calculado a partir del index, 0.1s de base más 0.08s por item. Esto crea una cascada natural sin ninguna API de orquestación adicional.

    <motion.div
      initial={{ opacity: 0, x: -12 }}
      whileInView={{ opacity: 1, x: 0 }}
      viewport={{ once: true }}
      transition={{ delay: 0.1 + i * 0.08, duration: 0.4 }}
    >
  4. Revelar la imagen del equipo con un scale pop

    La columna de imagen es un motion.div cuadrado (aspect-square) con overflow:hidden y un token de border radius. Configura el scale inicial a 0.96 y anímalo a 1 con una curva custom [0.16, 1, 0.3, 1] sobre 600ms, esto imita un spring sin importar la API spring.

    <motion.div
      initial={{ opacity: 0, scale: 0.96 }}
      whileInView={{ opacity: 1, scale: 1 }}
      viewport={{ once: true, margin: "-60px" }}
      transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
      className="aspect-square rounded-[var(--radius-xl)] overflow-hidden"
    >

Cuándo usarlo

Usa esta sección a media página en landing pages de agencias, productos SaaS y startups que necesitan establecer confianza antes de un bloque de pricing o testimonios. Funciona bien como segunda o tercera sección, después de un hero. Sáltatela si tu audiencia ya conoce bien al equipo (herramientas internas, docs para desarrolladores) o si la página está puramente orientada a la conversión y una foto de equipo sería una distracción. En móvil la cuadrícula se reduce a una sola columna, así que verifica que el aspect-ratio de la imagen parezca intencional a 375px en lugar de recortado de forma torpe.

Usado por

  • Stripe, Layout dividido que combina texto editorial con una foto de equipo/oficina en la página about para humanizar una marca orientada a desarrolladores.
  • Linear, Narrativa de empresa con bullets de valores ilustrados con iconos junto a una imagen, el patrón exacto que implementa este componente.
  • Loom, Secciones about en dos columnas con revelaciones de texto escalonadas y fotografía de equipo para comunicar la cultura.

FAQ

¿Cómo resuelvo un icono Lucide por su nombre string en tiempo de ejecución?

Castea el namespace lucide-react a Record<string, React.ElementType> y busca el nombre del icono como clave. Devuelve null si la clave falta para que el layout se degrade de forma elegante sin contenedor de icono.

¿Puedo reemplazar la imagen por un vídeo o una cuadrícula de retratos?

La columna derecha es un div simple con overflow:hidden, reemplaza el div background-image por cualquier elemento. Un vídeo (autoplay muted loop) o una cuadrícula CSS de retratos encaja sin tocar el código de animación.

¿Por qué usar background-image CSS en lugar de una etiqueta img para la foto?

background-image con background-size:cover maneja cualquier aspect ratio sin layout shift. En producción, reemplázalo por un componente Next.js Image con objectFit:cover para obtener la optimización automática y el lazy loading.

La animación en cascada se siente demasiado lenta en listas largas. ¿Cómo la ajusto?

Reduce el incremento de retraso por item de 0.08 a 0.05 o menos, y limita el retraso total con Math.min(0.1 + i * 0.05, 0.4) para que los items más allá del quinto no esperen sensiblemente más tiempo.

"use client";

import React from "react";
import { motion } from "framer-motion";
import * as LucideIcons from "lucide-react";

interface HighlightItem {
  icon?: string;
  label: string;
  description: string;
}

interface AboutTeamIntroProps {
  badge?: string;
  title?: string;
  description?: string;
  image?: string;
  highlights?: HighlightItem[];
}

function getIcon(name?: string) {
  if (!name) return null;

Code complet réservé à Pro

Code source intégral, export multi-framework et playground.

Passer en Pro, 9,99€/mois

Reseñas

Sección About React con intro de equipo, layout dividido