Retour au catalogue

Contact Chat Bubbles

Formulaire deguise en conversation chat. Questions en bulles stagger, reponses en bulles utilisateur. Tres engageant.

contactcomplex Both Responsive a11y
playfulboldsaasagencyuniversalcentered
Theme

Cómo crear un formulario de contacto con burbujas de chat en React

Un formulario de contacto con burbujas de chat en React sustituye el formulario tradicional por una conversación secuencial: cada pregunta aparece como una burbuja del bot animada con Framer Motion, el usuario escribe una respuesta y pulsa Enter, y la siguiente pregunta se desliza debajo. El state controla el índice del paso actual y un array de respuestas recopiladas.

  • Stack: React 18 + Framer Motion 11 + lucide-react, ~155 líneas, cero dependencias adicionales.
  • Animación: cada BotBubble se monta con opacity/y/scale mediante AnimatePresence; UserBubble refleja el mismo spring.
  • Admite los tipos de input text, email y textarea por paso, configurados mediante la prop steps.
  • Accesible: elementos input semánticos, envío con el teclado al pulsar Enter (Shift+Enter inserta un salto de línea en el textarea).
  • Totalmente responsive de fábrica; la tarjeta se limita a 600px centrada y usa tokens CSS para los espaciados.

Contact Chat Bubbles convierte un aburrido formulario de múltiples campos en una conversación de ida y vuelta. El bot hace una pregunta cada vez en una burbuja alineada a la izquierda; la respuesta del usuario flota a la derecha. Elimina la carga visual de un formulario tradicional y hace que ponerse en contacto resulte más ligero, sobre todo para agencias creativas y productos SaaS dirigidos a un público no técnico.

Anatomía

El componente es una única tarjeta centrada limitada a 600px. La tarjeta tiene tres zonas apiladas verticalmente: una barra de cabecera con el nombre del bot y un indicador de conexión, un área de mensajes scrollable con una altura mínima de 320px, y una fila de entrada en la parte inferior. Las burbujas del bot se sitúan a la izquierda con un avatar de icono de 32px; las respuestas del usuario son burbujas con color de acento alineadas a la derecha con una esquina de border-radius invertida. La fila de entrada desaparece una vez completados todos los pasos, sustituida por una burbuja de confirmación final.

Cómo funciona

El state clave son dos valores: `currentStep` (un entero) y `answers` (un array de strings). Cuando el usuario envía, el valor del input se añade a answers y currentStep se incrementa. El área de mensajes renderiza `steps.slice(0, currentStep + 1)`, por lo que todas las preguntas y respuestas anteriores permanecen visibles. Cada BotBubble recibe una prop `delay`: los pasos ya respondidos se montan con delay 0 (se restauran, no se revelan), mientras que el nuevo paso actual recibe un delay de 0.3s para dar la sensación de que el bot está escribiendo. AnimatePresence envuelve la lista con mode='sync' para que las nuevas burbujas se monten con fluidez sin desmontar las existentes.

Cómo crearlo en React

  1. Definir el array de steps

    Cada paso es un objeto simple con una question, un inputType ('text' | 'email' | 'textarea') y un placeholder. Pasa el array como prop para que el guion del chat quede fuera del componente y sea fácil de traducir o probar en A/B.

    const steps = [
      { question: "What's your name?", inputType: "text", placeholder: "Jane Doe" },
      { question: "Your email?",       inputType: "email", placeholder: "[email protected]" },
      { question: "How can we help?",  inputType: "textarea", placeholder: "Tell us…" },
    ];
  2. Gestionar el state de los pasos

    Mantén currentStep y answers en useState. El handler de envío valida que inputValue no esté vacío, lo añade a answers, limpia el campo e incrementa el paso. Un único flag isComplete derivado de currentStep >= steps.length controla lo que se renderiza.

    const [currentStep, setCurrentStep] = useState(0);
    const [answers, setAnswers] = useState<string[]>([]);
    
    const handleSubmit = () => {
      if (!inputValue.trim()) return;
      setAnswers(prev => [...prev, inputValue.trim()]);
      setInputValue("");
      setCurrentStep(prev => prev + 1);
    };
  3. Animar las burbujas del bot con un delay de stagger

    El componente BotBubble acepta una prop delay. Pasa `delay={0}` para los pasos ya vistos (aparecen al instante al re-renderizar) y `delay={0.3}` para la pregunta recién revelada. Esta pequeña distinción hace que el chat se sienta en vivo sin un indicador de escritura falso.

    <BotBubble
      text={step.question}
      delay={i === currentStep && answers.length === i ? 0.3 : 0}
    />
  4. Gestionar el envío con el teclado

    Para los inputs text y email, asocia `onKeyDown` para llamar a handleSubmit al pulsar Enter. Para el textarea, comprueba además `!e.shiftKey` para que el usuario pueda añadir saltos de línea con Shift+Enter antes de enviar. Llama a `e.preventDefault()` al pulsar Enter en el textarea para evitar el envío del formulario o saltos de línea sobrantes.

    onKeyDown={(e) => {
      if (e.key === "Enter" && !e.shiftKey) {
        e.preventDefault();
        handleSubmit();
      }
    }}

Cuándo usarlo

Recurre a este patrón cuando el formulario de contacto es un punto de conversión principal y quieres reducir la fricción percibida: una solicitud de presupuesto de agencia, un alta a una prueba SaaS o la presentación de un estudio creativo. La naturaleza secuencial mantiene al usuario centrado en una pregunta a la vez. Evítalo cuando el formulario tiene más de seis o siete pasos (se vuelve pesado), cuando hay que editar los campos tras el envío, o cuando necesitas validación en el servidor por paso con mensajes de error en tiempo real, la implementación actual recopila las respuestas en el cliente y las envía todas de una vez.

Usado por

  • Typeform, Popularizó el patrón de formulario conversacional de una pregunta a la vez en el que se inspira este componente.
  • Intercom, Usa flujos de UI con burbujas de chat para la cualificación de leads y el enrutado del soporte directamente en los sitios de sus clientes.
  • Drift, Construyó todo su producto en torno a formularios conversacionales integrados como widgets de chat en las landing pages.

FAQ

¿Cómo envío las respuestas recopiladas a mi backend?

Cuando isComplete pasa a true, lanza una llamada fetch o axios dentro de un useEffect que observe currentStep. Mapea answers sobre tu array steps para reconstruir un payload con nombres antes de enviar.

¿Puedo validar cada respuesta antes de pasar al siguiente paso?

Sí. Añade una función `validate` a cada objeto step. En handleSubmit, ejecuta validate(inputValue) y si devuelve un texto de error, escríbelo en un state local y detente antes de incrementar currentStep.

¿Por qué la burbuja del bot usa una prop delay de stagger en lugar de animation-delay de CSS?

Una prop delay del lado de JS a través de Framer Motion se integra con AnimatePresence, de modo que el delay solo se dispara en el montaje inicial, no en los re-renders provocados por cambios de state del padre. Un animation-delay de CSS se reproduciría en cada ciclo de renderizado.

¿Funciona en móvil?

El layout es totalmente responsive y la tarjeta ocupa su contenedor en pantallas pequeñas. En iOS, toca el input para abrir el teclado; el botón Enviar mide 44px de lado para cumplir las recomendaciones de tamaño de objetivo táctil. No hay dependencia de pointer events, así que el táctil funciona sin ningún tratamiento especial.

"use client";

import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Send, Bot } from "lucide-react";

interface ChatStep {
  question: string;
  inputType: "text" | "email" | "textarea";
  placeholder: string;
}

interface ContactChatBubblesProps {
  heading?: string;
  subtitle?: string;
  steps?: ChatStep[];
  ctaLabel?: string;
  botName?: string;
}

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

Code complet réservé à Pro

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

Passer en Pro, 9,99€/mois

Reseñas

Formulario de contacto con burbujas de chat React, Código +