React: ayuda de email sin mover el layout
Un buen aviso de email deberia orientar, no sacudir la interfaz.
Cuando un formulario detecta una direccion sospechosa, muchas apps aun meten un error rojo enorme debajo del campo y empujan el boton principal varios pixels hacia abajo. Parece un detalle chico, pero en frontend ese salto rompe ritmo, foco y confianza. He visto equipos arreglar la validacion y aun asi perder claridad porque la ayuda llegaba tarde o entraba como un martillazo visual.
El error comun: avisar tarde y mover todo
La mayoria del problema no esta en la regex. Esta en el momento y en la forma del feedback. Si el mensaje aparece solo cuando el usuario intenta enviar, ya llegaste tarde. Si ademas cambias altura del bloque y mueves el layout, el costo se nota en UX y tambien en rendimiento percibido.
Google recomienda mantener el CLS por debajo de 0.1, y los formularios con mensajes que aparecen sin reservar espacio suelen empeorar justo ahi. No siempre tiran la metrica completa al piso, pero si generan esa sensacion rara de "esto se movio cuando no debia". En mobile se siente peor, honestamente.
Tambien hay un tema semantico: "email invalido" no significa lo mismo que "email no recomendado por politica". Si usas la misma frase para todo, soporte luego hereda preguntas medio tontas y producto pierde señal. Esa confusion pasa muchisimo, mas de lo que deberia.
Una ayuda inline que respeta foco y ritmo
Mi preferencia es reservar el espacio del hint desde el primer render. Asi el mensaje puede aparecer sin reflow, y aria-describedby sigue apuntando al mismo nodo durante todo el flujo.
import { useId, useState } from "react";
const RISKY_DOMAINS = new Set(["mailinator.com", "yopmail.com"]);
export function EmailField() {
const hintId = useId();
const [email, setEmail] = useState("");
const domain = email.split("@")[1]?.toLowerCase() ?? "";
const isRisky = RISKY_DOMAINS.has(domain);
const showHint = domain.length > 3 && isRisky;
return (
<label className="field">
<span>Email</span>
<input
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
aria-describedby={hintId}
aria-invalid={showHint || undefined}
/>
<span id={hintId} className="field-hint" data-visible={showHint}>
{showHint
? "Usa un email personal si quieres recuperar acceso despues."
: " "}
</span>
</label>
);
}
.field-hint {
display: block;
min-height: 1.25rem;
margin-top: 0.35rem;
color: #8a2a1f;
}
.field-hint[data-visible="false"] {
color: transparent;
}
Ese patron es simple, pero evita varios bugs de sensacion. El usuario puede seguir escribiendo, el foco no salta y la pantalla no "respira" raro. Parece una microdecicion, aunque en verdad ordena toda la experiencia.
Donde poner la logica en React
Yo no pondria toda la politica en el cliente. El frontend sirve para avisar temprano; el backend sirve para decidir de verdad. Cuando mezclas ambas cosas en un solo lugar, la regla queda fragil y empiezan los parches.
Normalmente me funciona esta separacion:
- formato del email en el input
- heuristica corta en cliente para avisar pronto
- validacion final en la API
Ese segundo nivel puede usar una lista reducida, o incluso un endpoint cacheado si la app cambia seguido sus reglas. Para demos internas y pruebas de onboarding, un correo temporal gratis ayuda a entender el tipo de bandeja efimera que el producto tal vez quiera detectar o tratar distinto. Lo importante es que el mensaje no suene acusador ni bloquee antes de tiempo.
Tambien conviene contemplar texto sucio en analytics o logs. A veces QA copia cosas como temp mailid, o algun usuario pega una variante mal escrita, y si tu normalizacion es floja terminas clasificando mal el caso. Es una tonteria pequena, pero despues cuesta seguir el rastro.
Si el equipo ya trabaja automatizaciones o checks con contratos claros, me gusta enlazar patrones cercanos como contratos de salida pequenos para automatizaciones. No porque el problema sea igual, sino porque comparten una idea util: estados previsibles, con senales faciles de leer.
Que medir antes de decir que "funciona"
No basta con que el mensaje aparezca. Yo revisaria al menos estas senales:
- si el hint entra sin mover el boton principal
- si VoiceOver o NVDA leen el texto correcto
- si el ratio de correccion mejora antes del submit
- si analytics separa formato invalido de politica interna
Tambien miro si el mensaje mantiene buen contraste y cabe en dos lineas en pantallas pequenas. Hay formularios que "andan" en desktop pero en mobile parten la jerarquia visual de una forma bastante fea. Y luego nadie sabe por que la conversion cae un poco, pero cae.
Otra referencia que me sirve es pensar en alertas comprobables y no ruidosas, parecido a senales comprobables antes de lanzar una alerta. En UI pasa algo parecido: si la ayuda aparece siempre, deja de ayudar; si aparece solo con contexto, el usuario la entiende mas rapido.
Checklist corta para shipping
- reserva altura para el hint desde el primer render
- usa una frase distinta para formato invalido y politica de dominio
- no bloquees mientras la persona aun corrige
- guarda telemetria con razones separadas
- prueba el flujo con teclado y lector de pantalla
No es una lista glamourosa, lo se, pero evita esos bugs que parecen menores y luego quedan meses en produccion. En formularios, la prolijidad visual tambien es arquitectura.
Preguntas frecuentes
Debo bloquear siempre los dominios temporales?
No. En varios productos conviene advertir primero y bloquear solo en pasos de riesgo alto. Bloquear por reflejo aveces es mas comodo para el equipo que para la persona usuaria.
Conviene validar en cada tecla?
Solo cuando el mensaje no castiga. Yo prefiero esperar a tener dominio reconocible o al blur, porque da una experiencia mas calma y menos nerviosa.
Esto afecta performance de verdad?
Si, aunque no siempre en CPU pura. Afecta estabilidad visual, claridad y menos retrabajo del usuario. Y eso, al final, si importa un monton.
Top comments (0)