Retour au catalogue

Social Login

Page de connexion centree sur les providers sociaux (Google, GitHub, Apple, Twitter).

authsimple Both Responsive a11y
minimalplayfulsaasuniversalcentered
Theme

Cómo crear una página de login social en React con Framer Motion

Una página de login social React muestra una lista de botones de proveedores OAuth con una animación de entrada escalonada por elemento mediante Framer Motion, seguida de un fallback email opcional separado por un divisor. Toda la tarjeta aparece con fundido al montar mediante una curva de ease cercana a un spring.

  • Stack: React 18 + Framer Motion 11 + Tailwind v4 + Lucide React, ~80 líneas.
  • Animación de entrada: la tarjeta sube con fundido (opacity 0→1, y 20→0, 600ms) más un escalonado de 50ms por botón.
  • Totalmente personalizable mediante propiedades CSS custom; ningún color escrito a fuego en ningún sitio.
  • Accesible: el input email usa type="email", el formulario evita el envío por defecto, los botones son elementos <button> nativos.
  • La lista de proveedores se basa en datos, pasa cualquier array de { name, icon } para renderizar nuevos botones sin tocar el JSX.

Auth Social Login es una tarjeta de autenticación React centrada, diseñada para apps que dependen de proveedores OAuth como vía principal de inicio de sesión. Renderiza cada proveedor como su propio botón, los anima con un ligero escalonado y ofrece un input email más abajo para los usuarios que prefieren no vincular una cuenta social. El layout es autónomo y personalizable, listo para integrar en cualquier design system.

Anatomía

El motion.div externo es el wrapper animado de la tarjeta (max-w-sm, centrado). Dentro, una cabecera contiene un cuadrado monograma de marca (primera letra de brandName), el título de la página y un subtítulo opcional. Debajo, una pila vertical de elementos motion.button representa los proveedores OAuth. Cuando showEmailFallback es true, un divisor flex con la etiqueta "ou par email" separa la lista de proveedores de una fila que contiene un input email y un botón de envío ArrowRight.

Cómo funciona

Dos capas de Framer Motion gestionan la animación. El wrapper de la tarjeta se anima una vez al montar: initial={{ opacity: 0, y: 20 }} → animate={{ opacity: 1, y: 0 }} durante 600ms con una ease cubic-bezier(0.16, 1, 0.3, 1), la misma curva out-expo cercana a un spring que prefieren Linear y Vercel. Cada botón de proveedor recibe su propio motion.button con una transición de 30ms y un delay de i * 50ms, creando el escalonado sin ninguna API de orquestación. Sin scroll triggers ni gestos; la animación se dispara exactamente una vez al montar.

Cómo crearlo en React

  1. Definir la interfaz Provider y las props

    Crea un tipo Provider con los campos name e icon. Expón providers como prop array junto a brandName, title, subtitle y showEmailFallback. Esto mantiene el componente puramente presentacional, el padre gestiona las redirecciones OAuth.

    interface Provider { name: string; icon: string; }
    interface AuthSocialLoginProps {
      providers?: Provider[];
      showEmailFallback?: boolean;
      brandName?: string;
    }
  2. Animar el wrapper de la tarjeta al montar

    Envuelve toda la tarjeta en un motion.div con la constante de ease out-expo. Esta única animación cubre la cabecera, la lista de proveedores y el fallback email al mismo tiempo, sin necesidad de orquestación anidada.

    const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];
    
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.6, ease }}
    >
  3. Escalonar los botones de proveedores con el delay de índice

    Recorre el array providers y renderiza cada entrada como un motion.button. Pon delay: i * 0.05 en la transición. El primer botón aparece casi al instante; cada siguiente llega 50ms después. Mantén la duración por botón corta (300ms) para que el escalonado resulte ágil en lugar de lento.

    {providers.map((provider, i) => (
      <motion.button
        key={provider.name}
        initial={{ opacity: 0, y: 10 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.3, ease, delay: i * 0.05 }}
      >
        Continuer avec {provider.name}
      </motion.button>
    ))}
  4. Añadir el fallback email condicional

    Condiciona el divisor y la fila email con showEmailFallback. El divisor son dos divs flex-1 tipo hr que flanquean un label centrado. El formulario usa onSubmit={(e) => e.preventDefault()}, la lógica de envío real reside en el padre.

    {showEmailFallback && (
      <>
        <div className="flex items-center gap-3 my-6">
          <div className="flex-1 h-px" style={{ background: "var(--color-border)" }} />
          <span className="text-xs">ou par email</span>
          <div className="flex-1 h-px" style={{ background: "var(--color-border)" }} />
        </div>
        <form onSubmit={(e) => e.preventDefault()} className="flex gap-2">
          <input type="email" placeholder="[email protected]" className="flex-1 px-4 py-3 rounded-lg text-sm" />
          <button type="submit"><ArrowRight size={16} /></button>
        </form>
      </>
    )}

Cuándo usarlo

Usa este componente en rutas de autenticación independientes donde el login social sea la vía principal y quieras que la interfaz se sienta ligera y enfocada. Encaja en herramientas SaaS, plataformas para desarrolladores y cualquier app cuyos usuarios ya tengan cuentas de Google o GitHub. Evítalo cuando necesites un formulario de login completo con contraseña, MFA o magic links, esos casos requieren campos y estado que el componente excluye deliberadamente. En móvil el layout funciona tal cual; solo asegúrate de que el flujo de redirección OAuth se gestione fuera del componente.

Usado por

  • Linear, Tarjeta OAuth centrada y limpia con GitHub y Google como las dos opciones principales de login, sin campo de contraseña.
  • Vercel, Login social con GitHub, GitLab y Bitbucket listados como botones de proveedor antes de cualquier opción de email.
  • Supabase, La librería Auth UI de Supabase incluye de serie una lista de botones de proveedores sociales configurable con el mismo patrón de divisor + email.
  • Clerk, El componente SignIn prediseñado apila los botones de proveedores OAuth sobre un fallback email/contraseña, coincidiendo exactamente con esta disposición.

FAQ

¿Cómo conecto redirecciones OAuth reales?

El componente es presentacional, no expone una prop onClick en los botones de proveedor por defecto. En el padre, recorre los providers y añade un onClick que llame a tu librería de auth (NextAuth signIn, Supabase signInWithOAuth, flujo OAuth de Clerk, etc.).

¿Puedo añadir un campo de contraseña a este componente?

El diseño separa intencionadamente el login social de la autenticación por contraseña. Añade un campo de contraseña extendiendo AuthSocialLoginProps y renderizando condicionalmente un input adicional bajo la fila email, pero llegado ese punto estás construyendo un patrón distinto (formulario de login combinado) en lugar de una tarjeta social-first.

¿Por qué escalonar los botones con el delay de índice en lugar de staggerChildren de Framer Motion?

staggerChildren requiere un objeto variants tanto en el padre como en cada hijo, lo que añade boilerplate. El patrón delay: i * 0.05 logra el mismo resultado visual con menos código y se lee más fácil de un vistazo cuando la lista se genera dinámicamente.

¿Gestiona el componente el estado de carga durante las redirecciones OAuth?

No. La implementación actual es estática, los botones no tienen estado deshabilitado ni de carga. Gestiona la carga por proveedor en el padre con un useState, pásalo hacia abajo y renderiza condicionalmente un spinner dentro del botón. La simplicidad del componente facilita esta extensión.

"use client";

import { motion } from "framer-motion";
import { ArrowRight } from "lucide-react";

interface Provider {
  name: string;
  icon: string;
}

interface AuthSocialLoginProps {
  brandName?: string;
  title?: string;
  subtitle?: string;
  providers?: Provider[];
  showEmailFallback?: boolean;
}

const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];

export default function AuthSocialLogin({
  brandName = "Acme",

Code complet réservé à Pro

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

Passer en Pro, 9,99€/mois

Reseñas

UI React login social, botones OAuth + fallback email