Pequeño cambio de calidad de vida hoy. Hasta ahora, hacer clic en iniciar sesión te mandaba a una página de login separada, lo que significaba perder tu lugar en lo que estuvieras leyendo. Inicias sesión a mitad de un artículo porque quieres comentar, y el sitio te deja de vuelta en la portada después. Una falta de respeto, la verdad.
Así que iniciar sesión y registrarse ahora abren en un pequeño diálogo encima de la página en la que ya estás. Inicias sesión, la caja se cierra, la barra lateral cambia a tu cuenta, y el artículo que estabas leyendo no se ha movido ni un píxel. El diálogo es el mismo vidrio esmerilado que el resto del sitio, así que parece haber crecido de la página en lugar de estar pegado encima.

Lo que más me importa es lo que no cambió. Las páginas completas de inicio de sesión y registro siguen existiendo y siguen funcionando. Los enlaces de la barra lateral conservan sus direcciones reales, y un poco de script simplemente intercepta el clic para abrir el diálogo en su lugar. Sin script, sin diálogo, y todo se comporta como antes. Lo mismo pasa con la lógica de inicio de sesión en sí: el diálogo no tiene código de login propio, envía a las mismas acciones del servidor exactas que usan las páginas completas. Una sola implementación de login, dos puertas de entrada.
La parte interesante fue qué pasa cuando todo sale bien. El servidor responde a un inicio de sesión exitoso con una redirección, porque eso es lo que necesita la página completa. Pero el diálogo no debe seguirla, seguirla es exactamente el comportamiento que estoy eliminando. Así que el manejador de envío del diálogo captura el resultado y, ante una redirección, lo trata como una señal de éxito en lugar de un destino:
return async ({ result }: { result: ActionResult }) => {
if (result.type === 'redirect') {
open = false;
await invalidateAll();
return;
}
if (result.type === 'failure') {
loginResult = result.data as typeof loginResult;
}
};El invalidateAll es lo que hace que la barra lateral se actualice en el sitio: le dice a la aplicación que vuelva a leer todo lo que sabe, incluyendo quién ha iniciado sesión, sin navegar a ningún lado. La contraseña incorrecta también se queda en la caja, con el error mostrado directamente ahí, así que un error de tipeo tampoco te cuesta tu posición de lectura.
El error que vale la pena admitir salió en la revisión: mi manejador de clics agarraba cualquier clic sobre el enlace de inicio de sesión, incluyendo ctrl-clic y clic central. Alguien que hace ctrl-clic en un enlace está diciendo abre esto en una pestaña nueva, y secuestrar eso hacia un diálogo en la página actual es el tipo de pequeña falta de respeto que hace que un sitio se sienta mal. El manejador ahora se hace a un lado ante cualquier clic modificado o no primario y deja que el navegador haga exactamente lo que se le pidió.
Detalles que importan pero que nadie va a notar: es un elemento dialog nativo, así que Esc lo cierra gratis, hacer clic en el fondo oscuro lo cierra, el foco se mueve dentro de la caja cuando se abre y de vuelta al enlace que lo abrió cuando se cierra. Y cada texto dentro existe en los tres idiomas, porque esa es la regla de la casa ahora.
Un error más para el registro de honestidad: la primera versión abría la caja en la esquina superior izquierda en vez del centro de la página. Un elemento dialog se centra solo de serie, pero el reset de CSS del sitio pone todos los márgenes a cero, y eso mató en silencio el margin auto del navegador que lo centraba. Una regla en el componente compartido de diálogo lo trajo de vuelta, para este diálogo y para todos los demás del sitio.
Función pequeña, una tarde, y el sitio dejó de echar a la gente de su lectura para preguntarles quiénes son.