From 6dbc7f073cd744657bf826192626ea1b2330f858 Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Tue, 26 May 2026 22:38:18 -0500 Subject: [PATCH] login-ui: enable form for 5s, then show a verifying spinner before the access-restricted notice The login page previously rendered the form fields server-disabled with the access-restricted warning shown immediately. That communicates the final state but skips the perception of a real network-gate check. Make the page feel like an actual eligibility check: Phase 1 (0-5s): form fields and submit button start enabled. Users can type and tab through the form normally. Phase 2 (after 5s or on submit, whichever first): inputs and button go disabled, the button label flips to "Verifying...", and an info box with a CSS-only spinner appears ("Verifying network access - Confirming that your network is approved for this Meshery remote provider..."). Phase 3 (after a 3s verifying window): the spinner box hides and the existing "Access Restricted" warning reveals. Fields stay disabled, button returns to "Sign In". Notes: - No external assets. The spinner is a pure CSS keyframe and is suppressed under prefers-reduced-motion. - The info box is role=status / aria-live=polite; the restricted box is role=alert. Inputs get autocomplete hints and a visible focus ring. - Inline onsubmit was replaced with a delegated submit listener that also short-circuits the 5s wait so submission gives immediate feedback. - index.html and login.html were byte-identical and serve the same role (Meshery's InitiateLogin redirects to /login, which GitHub Pages serves from login.html); they are kept in sync here. Signed-off-by: Lee Calcote --- index.html | 178 +++++++++++++++++++++++++++++++++++++++++++++-------- login.html | 178 +++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 304 insertions(+), 52 deletions(-) diff --git a/index.html b/index.html index 97e3cee..83d43df 100644 --- a/index.html +++ b/index.html @@ -8,17 +8,26 @@ :root { /* Intel Branding Colors */ --intel-blue: #0068B5; + --intel-blue-hover: #00558f; --bg-color: #f4f5f7; --card-bg: #ffffff; --text-main: #333333; --text-muted: #6b7280; - + /* Warning Colors */ --warning-bg: #fee2e2; --warning-text: #991b1b; --warning-border: #ef4444; - - /* Disabled Input Colors */ + + /* Info Colors (verification in progress) */ + --info-bg: #e0f2fe; + --info-text: #075985; + --info-border: #0284c7; + + /* Input Colors */ + --enabled-bg: #ffffff; + --enabled-text: #111827; + --enabled-border: #cbd5e1; --disabled-bg: #f3f4f6; --disabled-text: #9ca3af; --disabled-border: #d1d5db; @@ -63,24 +72,36 @@ margin: 0 0 25px 0; } - .warning-box { - background-color: var(--warning-bg); - color: var(--warning-text); - border-left: 4px solid var(--warning-border); - padding: 12px 16px; + .status-box { border-radius: 4px; + padding: 12px 16px; font-size: 0.85rem; margin-bottom: 25px; text-align: left; line-height: 1.5; } - .warning-box strong { + .status-box strong { display: block; margin-bottom: 4px; font-size: 0.9rem; } + .status-box.info { + background-color: var(--info-bg); + color: var(--info-text); + border-left: 4px solid var(--info-border); + display: flex; + align-items: center; + gap: 12px; + } + + .status-box.warning { + background-color: var(--warning-bg); + color: var(--warning-text); + border-left: 4px solid var(--warning-border); + } + .form-group { text-align: left; margin-bottom: 18px; @@ -97,21 +118,33 @@ .form-group input { width: 100%; padding: 12px; - border: 1px solid var(--disabled-border); + border: 1px solid var(--enabled-border); border-radius: 4px; box-sizing: border-box; - background-color: var(--disabled-bg); - color: var(--disabled-text); + background-color: var(--enabled-bg); + color: var(--enabled-text); font-size: 0.95rem; - cursor: not-allowed; - transition: all 0.2s ease; + transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; + } + + .form-group input:focus { + outline: 2px solid rgba(0, 104, 181, 0.25); + outline-offset: 0; + border-color: var(--intel-blue); } .form-group input::placeholder { - color: var(--disabled-text); + color: var(--text-muted); opacity: 0.7; } + .form-group input:disabled { + background-color: var(--disabled-bg); + color: var(--disabled-text); + border-color: var(--disabled-border); + cursor: not-allowed; + } + button { width: 100%; padding: 12px; @@ -121,40 +154,133 @@ border-radius: 4px; font-size: 1rem; font-weight: 600; + margin-top: 10px; + cursor: pointer; + transition: background-color 0.2s ease, opacity 0.2s ease; + } + + button:not(:disabled):hover, + button:not(:disabled):focus { + background-color: var(--intel-blue-hover); + } + + button:disabled { opacity: 0.5; cursor: not-allowed; - margin-top: 10px; - transition: opacity 0.2s ease; + } + + .spinner { + flex-shrink: 0; + width: 18px; + height: 18px; + border: 2px solid rgba(2, 132, 199, 0.25); + border-top-color: var(--info-border); + border-radius: 50%; + animation: spin 0.8s linear infinite; + } + + @keyframes spin { + to { transform: rotate(360deg); } + } + + @media (prefers-reduced-motion: reduce) { + .spinner { + animation: none; + } + } + + [hidden] { + display: none !important; }