Skip to content

Commit 6dbc7f0

Browse files
committed
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 <provider>/login, which GitHub Pages serves from login.html); they are kept in sync here. Signed-off-by: Lee Calcote <lee.calcote@layer5.io>
1 parent 5ac99b3 commit 6dbc7f0

2 files changed

Lines changed: 304 additions & 52 deletions

File tree

index.html

Lines changed: 152 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,26 @@
88
:root {
99
/* Intel Branding Colors */
1010
--intel-blue: #0068B5;
11+
--intel-blue-hover: #00558f;
1112
--bg-color: #f4f5f7;
1213
--card-bg: #ffffff;
1314
--text-main: #333333;
1415
--text-muted: #6b7280;
15-
16+
1617
/* Warning Colors */
1718
--warning-bg: #fee2e2;
1819
--warning-text: #991b1b;
1920
--warning-border: #ef4444;
20-
21-
/* Disabled Input Colors */
21+
22+
/* Info Colors (verification in progress) */
23+
--info-bg: #e0f2fe;
24+
--info-text: #075985;
25+
--info-border: #0284c7;
26+
27+
/* Input Colors */
28+
--enabled-bg: #ffffff;
29+
--enabled-text: #111827;
30+
--enabled-border: #cbd5e1;
2231
--disabled-bg: #f3f4f6;
2332
--disabled-text: #9ca3af;
2433
--disabled-border: #d1d5db;
@@ -63,24 +72,36 @@
6372
margin: 0 0 25px 0;
6473
}
6574

66-
.warning-box {
67-
background-color: var(--warning-bg);
68-
color: var(--warning-text);
69-
border-left: 4px solid var(--warning-border);
70-
padding: 12px 16px;
75+
.status-box {
7176
border-radius: 4px;
77+
padding: 12px 16px;
7278
font-size: 0.85rem;
7379
margin-bottom: 25px;
7480
text-align: left;
7581
line-height: 1.5;
7682
}
7783

78-
.warning-box strong {
84+
.status-box strong {
7985
display: block;
8086
margin-bottom: 4px;
8187
font-size: 0.9rem;
8288
}
8389

90+
.status-box.info {
91+
background-color: var(--info-bg);
92+
color: var(--info-text);
93+
border-left: 4px solid var(--info-border);
94+
display: flex;
95+
align-items: center;
96+
gap: 12px;
97+
}
98+
99+
.status-box.warning {
100+
background-color: var(--warning-bg);
101+
color: var(--warning-text);
102+
border-left: 4px solid var(--warning-border);
103+
}
104+
84105
.form-group {
85106
text-align: left;
86107
margin-bottom: 18px;
@@ -97,21 +118,33 @@
97118
.form-group input {
98119
width: 100%;
99120
padding: 12px;
100-
border: 1px solid var(--disabled-border);
121+
border: 1px solid var(--enabled-border);
101122
border-radius: 4px;
102123
box-sizing: border-box;
103-
background-color: var(--disabled-bg);
104-
color: var(--disabled-text);
124+
background-color: var(--enabled-bg);
125+
color: var(--enabled-text);
105126
font-size: 0.95rem;
106-
cursor: not-allowed;
107-
transition: all 0.2s ease;
127+
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
128+
}
129+
130+
.form-group input:focus {
131+
outline: 2px solid rgba(0, 104, 181, 0.25);
132+
outline-offset: 0;
133+
border-color: var(--intel-blue);
108134
}
109135

110136
.form-group input::placeholder {
111-
color: var(--disabled-text);
137+
color: var(--text-muted);
112138
opacity: 0.7;
113139
}
114140

141+
.form-group input:disabled {
142+
background-color: var(--disabled-bg);
143+
color: var(--disabled-text);
144+
border-color: var(--disabled-border);
145+
cursor: not-allowed;
146+
}
147+
115148
button {
116149
width: 100%;
117150
padding: 12px;
@@ -121,40 +154,133 @@
121154
border-radius: 4px;
122155
font-size: 1rem;
123156
font-weight: 600;
157+
margin-top: 10px;
158+
cursor: pointer;
159+
transition: background-color 0.2s ease, opacity 0.2s ease;
160+
}
161+
162+
button:not(:disabled):hover,
163+
button:not(:disabled):focus {
164+
background-color: var(--intel-blue-hover);
165+
}
166+
167+
button:disabled {
124168
opacity: 0.5;
125169
cursor: not-allowed;
126-
margin-top: 10px;
127-
transition: opacity 0.2s ease;
170+
}
171+
172+
.spinner {
173+
flex-shrink: 0;
174+
width: 18px;
175+
height: 18px;
176+
border: 2px solid rgba(2, 132, 199, 0.25);
177+
border-top-color: var(--info-border);
178+
border-radius: 50%;
179+
animation: spin 0.8s linear infinite;
180+
}
181+
182+
@keyframes spin {
183+
to { transform: rotate(360deg); }
184+
}
185+
186+
@media (prefers-reduced-motion: reduce) {
187+
.spinner {
188+
animation: none;
189+
}
190+
}
191+
192+
[hidden] {
193+
display: none !important;
128194
}
129195
</style>
130196
</head>
131197
<body>
132198

133199
<div class="login-container">
134-
<img src="/intel.png" alt="Intel Logo" class="logo">
135-
200+
<img src="/intel.png" alt="Intel Logo" class="logo">
201+
136202
<h1>Intel Performance Platform</h1>
137203
<p class="subtitle">Meshery Remote Provider</p>
138204

139-
<div class="warning-box">
205+
<div id="status-checking" class="status-box info" hidden role="status" aria-live="polite">
206+
<span class="spinner" aria-hidden="true"></span>
207+
<span>
208+
<strong>Verifying network access</strong>
209+
Confirming that your network is approved for this Meshery remote provider...
210+
</span>
211+
</div>
212+
213+
<div id="status-restricted" class="status-box warning" hidden role="alert">
140214
<strong>⚠️ Access Restricted</strong>
141215
Access to this Meshery remote provider is strictly limited to Intel-internal networks only. Authentication is currently disabled.
142216
</div>
143217

144-
<form onsubmit="event.preventDefault();">
218+
<form id="login-form">
145219
<div class="form-group">
146220
<label for="username">Corporate Email</label>
147-
<input type="text" id="username" name="username" placeholder="user@intel.com" disabled>
221+
<input type="text" id="username" name="username" placeholder="user@intel.com" autocomplete="username">
148222
</div>
149-
223+
150224
<div class="form-group">
151225
<label for="password">Password</label>
152-
<input type="password" id="password" name="password" placeholder="••••••••" disabled>
226+
<input type="password" id="password" name="password" placeholder="••••••••" autocomplete="current-password">
153227
</div>
154-
155-
<button type="submit" disabled>Sign In</button>
228+
229+
<button type="submit" id="submit-btn">Sign In</button>
156230
</form>
157231
</div>
158232

233+
<script>
234+
(function () {
235+
var ENABLED_WINDOW_MS = 5000;
236+
var VERIFYING_DURATION_MS = 3000;
237+
238+
var inputs = document.querySelectorAll('#username, #password');
239+
var submitBtn = document.getElementById('submit-btn');
240+
var form = document.getElementById('login-form');
241+
var checkingBox = document.getElementById('status-checking');
242+
var restrictedBox = document.getElementById('status-restricted');
243+
244+
var enabledTimer = null;
245+
var verifyingTimer = null;
246+
var phase = 'enabled';
247+
248+
function lockForm() {
249+
inputs.forEach(function (el) { el.disabled = true; });
250+
submitBtn.disabled = true;
251+
}
252+
253+
function startVerifying() {
254+
if (phase !== 'enabled') return;
255+
phase = 'verifying';
256+
if (enabledTimer !== null) {
257+
window.clearTimeout(enabledTimer);
258+
enabledTimer = null;
259+
}
260+
lockForm();
261+
submitBtn.textContent = 'Verifying...';
262+
checkingBox.hidden = false;
263+
verifyingTimer = window.setTimeout(showRestricted, VERIFYING_DURATION_MS);
264+
}
265+
266+
function showRestricted() {
267+
phase = 'restricted';
268+
verifyingTimer = null;
269+
checkingBox.hidden = true;
270+
submitBtn.textContent = 'Sign In';
271+
restrictedBox.hidden = false;
272+
}
273+
274+
// Submitting during the enabled window jumps straight to verifying so
275+
// the user gets immediate feedback instead of waiting out the timer.
276+
form.addEventListener('submit', function (event) {
277+
event.preventDefault();
278+
startVerifying();
279+
});
280+
281+
enabledTimer = window.setTimeout(startVerifying, ENABLED_WINDOW_MS);
282+
})();
283+
</script>
284+
159285
</body>
160286
</html>

0 commit comments

Comments
 (0)