From c4d0462288635f00d149b68afa517fa9b1161bba Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 04:50:44 +0000 Subject: [PATCH] feat: add loading state to login button Added disabled state, `aria-busy` attribute, and visual text change during async login submissions. Ensured original state is robustly restored using a try...finally block. Co-authored-by: singhaditya21 <53948039+singhaditya21@users.noreply.github.com> --- .Jules/palette.md | 3 +++ web-demo/js/app.js | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..f0adc6b --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2024-05-14 - Missing Loading States on Async Actions +**Learning:** In the ClimaAI app, form buttons (Login, Register, Google Auth) lack visual feedback and disable states during async API requests. +**Action:** Always add loading spinners/text changes and disable the button natively (via `disabled=true` and `aria-busy=true`) during async submissions to prevent double-clicks and provide immediate feedback. Use `try...finally` to ensure state is cleaned up robustly. diff --git a/web-demo/js/app.js b/web-demo/js/app.js index 11508de..3ccf8a7 100644 --- a/web-demo/js/app.js +++ b/web-demo/js/app.js @@ -144,6 +144,15 @@ class ClimaAI { e.preventDefault(); const email = document.getElementById('loginEmail').value; const password = document.getElementById('loginPassword').value; + const submitBtn = e.submitter; + let originalContent = ''; + + if (submitBtn) { + originalContent = submitBtn.innerHTML; + submitBtn.disabled = true; + submitBtn.setAttribute('aria-busy', 'true'); + submitBtn.innerHTML = 'Signing in...'; + } try { this.showToast('Logging in...', 'info'); @@ -155,6 +164,12 @@ class ClimaAI { this.checkSubscription(); } catch (error) { this.showToast(error.message || 'Login failed', 'error'); + } finally { + if (submitBtn) { + submitBtn.disabled = false; + submitBtn.removeAttribute('aria-busy'); + submitBtn.innerHTML = originalContent; + } } }