ReviewOS

also looking at this

loghqorg/loghq

chore(release): promote UI, accessibility, and STX updates to production

#11
Merged glennmichael123 wants to merge main into production
16 files +176 -67

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

resources/views/login.stxmodified+5-5
Changes to resources/views/login.stx
@@ -139,21 +139,21 @@ async function onVerify(e: Event): Promise<void> {
139139
140140 {{-- The shared error box for both steps. `:text` overwrites the (empty)
141141 static label after hydration and never cloaks. --}}
142 <div :show="!!error()" :text="error()" class="mb-4 px-3 py-2 text-sm rounded-lg err-box"></div>
142 <div id="login-error" role="alert" :show="!!error()" :text="error()" class="mb-4 px-3 py-2 text-sm rounded-lg err-box"></div>
143143
144144 {{-- Step 1: credentials. A same-origin fetch, not a native POST — the
145145 submit is intercepted so the browser never navigates to /login itself. --}}
146146 <form :show="mode() === 'credentials'" action="/api/auth/login" method="POST" @submit="onLogin" class="space-y-4">
147147 <div>
148148 <label for="login-email" class="block mb-1.5 font-medium text-muted text-xs">Email</label>
149 <input id="login-email" name="email" type="email" required autocomplete="email" placeholder="you@example.com" :model="email" class="px-3.5 py-2.5 w-full text-sm field">
149 <input id="login-email" name="email" type="email" required autocomplete="email" placeholder="you@example.com" :model="email" class="px-3.5 py-2.5 w-full text-sm field" :aria-invalid="error() ? 'true' : 'false'" :aria-describedby="error() ? 'login-error' : ''">
150150 </div>
151151 <div>
152152 <div class="flex items-center justify-between mb-1.5">
153153 <label for="login-password" class="block font-medium text-muted text-xs">Password</label>
154154 <StxLink to="/forgot-password" class="font-medium text-accent text-xs">Forgot password?</StxLink>
155155 </div>
156 <input id="login-password" name="password" type="password" required autocomplete="current-password" placeholder="••••••••" :model="password" class="px-3.5 py-2.5 w-full text-sm field">
156 <input id="login-password" name="password" type="password" required autocomplete="current-password" placeholder="••••••••" :model="password" class="px-3.5 py-2.5 w-full text-sm field" :aria-invalid="error() ? 'true' : 'false'" :aria-describedby="error() ? 'login-error' : ''">
157157 </div>
158158
159159 {{-- Remember me, default OFF: unchecked is the baseline week, checked is
@@ -171,13 +171,13 @@ async function onVerify(e: Event): Promise<void> {
171171 <p class="text-sm text-subtle">Enter the 6-digit code from your authenticator app.</p>
172172 <div>
173173 <label for="login-code" class="block mb-1.5 font-medium text-muted text-xs">Authentication code</label>
174 <input id="login-code" name="code" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" placeholder="123456" :model="code" class="px-3.5 py-2.5 w-full text-sm field">
174 <input id="login-code" name="code" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" placeholder="123456" :model="code" class="px-3.5 py-2.5 w-full text-sm field" :aria-invalid="error() ? 'true' : 'false'" :aria-describedby="error() ? 'login-error' : ''">
175175 </div>
176176 <button type="submit" :disabled="loading()" :text="loading() ? 'Verifying…' : 'Verify and sign in'" class="py-2.5 w-full font-semibold text-sm btn-solid">Verify and sign in</button>
177177 </form>
178178
179179 @if (oauthError)
180 <div class="mt-4 px-3 py-2 text-sm rounded-lg err-box">{{ oauthError }}</div>
180 <div role="alert" class="mt-4 px-3 py-2 text-sm rounded-lg err-box">{{ oauthError }}</div>
181181 @endif
182182
183183 @if (anyOauth)