Créer une page de connexion sociale en React avec Framer Motion
Une page de connexion sociale React affiche une liste de boutons OAuth avec une animation d'entrée décalée par élément via Framer Motion, suivie d'un fallback email optionnel séparé par un trait. La carte entière s'ouvre au montage avec une courbe d'ease proche d'un spring.
- Stack : React 18 + Framer Motion 11 + Tailwind v4 + Lucide React, ~80 lignes.
- Animation d'entrée : la carte monte en fondu (opacity 0→1, y 20→0, 600ms) + décalage de 50ms par bouton.
- Entièrement thématisable via des propriétés CSS custom ; aucune couleur codée en dur.
- Accessible : l'input utilise type="email", le formulaire empêche le rechargement, les boutons sont des éléments <button> natifs.
- La liste de providers est pilotée par données, passe un tableau { name, icon } pour ajouter des boutons sans toucher au JSX.
Auth Social Login est une carte d'authentification React centrée conçue pour les apps qui s'appuient sur des providers OAuth comme principale voie de connexion. Chaque provider s'affiche sous forme de bouton, les boutons arrivent en cascade légère, et un input email attend en dessous pour les utilisateurs qui préfèrent éviter les comptes liés. Le composant est autonome et thématisable, prêt à intégrer dans n'importe quel design system.
Anatomie
Le motion.div externe est le wrapper animé de la carte (max-w-sm, centré). À l'intérieur, un en-tête affiche un carré monogramme (première lettre de brandName), le titre de la page et un sous-titre optionnel. En dessous, une pile verticale de motion.button représente les providers OAuth. Quand showEmailFallback est actif, un séparateur flex labellisé "ou par email" sépare la liste des providers d'une rangée contenant un input email et un bouton de soumission avec flèche.
Comment ça marche
Deux couches Framer Motion gèrent l'animation. Le wrapper de la carte s'anime une fois au montage : initial={{ opacity: 0, y: 20 }} → animate={{ opacity: 1, y: 0 }} sur 600ms avec une ease cubic-bezier(0.16, 1, 0.3, 1), la même courbe out-expo proche d'un spring qu'utilisent Linear et Vercel. Chaque bouton de provider reçoit son propre motion.button avec une durée de 30ms et un délai de i * 50ms, ce qui crée le décalage sans aucune API d'orchestration. Pas de scroll trigger ni de geste ; l'animation se déclenche une seule fois au montage.
Comment le coder en React
Définir l'interface Provider et les props
Crée un type Provider avec les champs name et icon. Expose providers comme prop tableau aux côtés de brandName, title, subtitle et showEmailFallback. Le composant reste purement présentationnel, le parent gère les redirections OAuth.
interface Provider { name: string; icon: string; } interface AuthSocialLoginProps { providers?: Provider[]; showEmailFallback?: boolean; brandName?: string; }Animer le wrapper de carte au montage
Enveloppe toute la carte dans un motion.div avec la constante d'ease out-expo. Cette animation unique couvre l'en-tête, la liste des providers et le fallback email en même temps, pas besoin d'orchestration imbriquée.
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 }} >Décaler les boutons providers avec le délai d'index
Itère sur le tableau providers et rends chaque entrée en motion.button. Passe delay: i * 0.05 dans la transition. Le premier bouton apparaît presque immédiatement ; chaque suivant arrive 50ms plus tard. Garde la durée par bouton courte (300ms) pour que le décalage soit vif plutôt que lent.
{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> ))}Ajouter le fallback email conditionnel
Conditionne le séparateur et la rangée email avec showEmailFallback. Le séparateur est composé de deux div flex-1 encadrant un label centré. Le formulaire utilise onSubmit={(e) => e.preventDefault()}, la logique de soumission réelle appartient au parent.
{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> </> )}
Quand l'utiliser
Utilise ce composant sur des routes d'authentification standalone où la connexion sociale est le chemin principal et où l'interface doit paraître légère et concentrée. Il convient aux outils SaaS, aux plateformes pour développeurs et aux apps dont les utilisateurs ont déjà des comptes Google ou GitHub. À éviter quand tu as besoin d'un formulaire de connexion complet avec mot de passe, MFA ou magic links, ces cas nécessitent des champs et un état que le composant exclut délibérément. Sur mobile le layout fonctionne tel quel ; assure-toi que le flux de redirection OAuth est géré en dehors du composant.
Utilisé par
- Linear, Carte OAuth centrée et épurée avec GitHub et Google comme deux options principales, sans champ mot de passe.
- Vercel, Connexion sociale avec GitHub, GitLab et Bitbucket affichés comme boutons de provider avant toute option email.
- Supabase, La bibliothèque Auth UI de Supabase fournit une liste de boutons de providers sociaux configurable avec le même pattern séparateur + email.
- Clerk, Le composant SignIn pré-construit empile les boutons OAuth au-dessus d'un fallback email/mot de passe, correspondant exactement à cette disposition.
FAQ
Comment brancher de vraies redirections OAuth ?
Le composant est purement présentationnel, il n'expose pas de prop onClick sur les boutons de provider par défaut. Dans le parent, itère sur les providers et attache un onClick qui appelle ta bibliothèque d'auth (NextAuth signIn, Supabase signInWithOAuth, Clerk OAuth, etc.).
Peut-on ajouter un champ mot de passe à ce composant ?
La conception sépare intentionnellement la connexion sociale de l'authentification par mot de passe. Étends AuthSocialLoginProps et rends conditionnellement un input supplémentaire sous la rangée email, mais à ce stade tu construis un autre pattern (formulaire de connexion combiné) plutôt qu'une carte social-first.
Pourquoi décaler les boutons avec le délai d'index plutôt que staggerChildren de Framer Motion ?
staggerChildren nécessite un objet variants sur le parent et chaque enfant, ce qui ajoute du boilerplate. Le pattern delay: i * 0.05 produit le même résultat visuel avec moins de code et se lit plus facilement quand la liste est générée dynamiquement.
Le composant gère-t-il l'état de chargement pendant les redirections OAuth ?
Non. L'implémentation actuelle est statique, les boutons n'ont ni état désactivé ni état de chargement. Gère le chargement par provider dans le parent avec un useState, transmets-le et affiche conditionnellement un spinner dans le bouton. La simplicité du composant facilite cette extension.