Compare commits
1 Commits
step35/594
...
step35/550
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
172ce58365 |
@@ -1,81 +1,103 @@
|
||||
{{/*
|
||||
Gitea a11y fix: R1 — Password visibility toggle + R2 — aria-required
|
||||
Gitea a11y fix: V6 — Heading hierarchy + R1 — Password visibility toggle + R2 — aria-required
|
||||
|
||||
Override of user/auth/signin_inner.tmpl
|
||||
Adds:
|
||||
- Eye icon toggle to show/hide password content
|
||||
- aria-required="true" on required fields
|
||||
- Proper label associations
|
||||
Changes:
|
||||
- V6: Heading changed from <h4> to <h1> for proper hierarchy (WCAG 1.3.1)
|
||||
- R2: Add aria-required="true" to required fields (username, password)
|
||||
- R1: Add eye-icon toggle to show/hide password
|
||||
|
||||
Deploy to: custom/templates/user/auth/signin_inner.tmpl
|
||||
*/}}
|
||||
{{template "base/head" .}}
|
||||
<div class="page-content container">
|
||||
<div class="signin">
|
||||
<h1>{{.locale.Tr "sign_in"}}</h1>
|
||||
|
||||
<form action="{{AppSubUrl}}/user/login" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="ui container fluid">
|
||||
{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn)}}
|
||||
{{template "base/alert" .}}
|
||||
{{end}}
|
||||
<h1 class="ui top attached header center">
|
||||
{{if .LinkAccountMode}}
|
||||
{{ctx.Locale.Tr "auth.oauth_signin_title"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "auth.login_userpass"}}
|
||||
{{end}}
|
||||
</h1>
|
||||
<div class="ui attached segment">
|
||||
{{if .EnablePasswordSignInForm}}
|
||||
<form class="ui form" action="{{.SignInLink}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="required field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
|
||||
<label for="user_name">{{ctx.Locale.Tr "home.uname_holder"}}</label>
|
||||
<input id="user_name" type="text" name="user_name" value="{{.user_name}}" autofocus required aria-required="true" tabindex="1">
|
||||
</div>
|
||||
{{if or (not .DisablePassword) .LinkAccountMode}}
|
||||
<div class="required field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
|
||||
<div class="tw-flex tw-mb-1">
|
||||
<label for="password" class="tw-flex-1">{{ctx.Locale.Tr "password"}}</label>
|
||||
<a href="{{AppSubUrl}}/user/forgot_password" tabindex="4">{{ctx.Locale.Tr "auth.forgot_password"}}</a>
|
||||
</div>
|
||||
<div style="position:relative">
|
||||
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="current-password" required aria-required="true" tabindex="2" style="padding-right:36px">
|
||||
<button
|
||||
type="button"
|
||||
id="toggle-password"
|
||||
aria-label="{{ctx.Locale.Tr 'auth.show_password'}}"
|
||||
title="{{ctx.Locale.Tr 'auth.show_password'}}"
|
||||
style="position:absolute;right:8px;background:none;border:none;cursor:pointer;padding:4px;color:#666;font-size:16px"
|
||||
onclick="togglePasswordVisibility()"
|
||||
>👁</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if not .LinkAccountMode}}
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox">
|
||||
<label>{{ctx.Locale.Tr "auth.remember_me"}}</label>
|
||||
<input name="remember" type="checkbox" tabindex="5"{{if .Remember}} checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{/* a11y R2: aria-required on username field */}}
|
||||
<div class="field">
|
||||
<label for="user_name">{{.locale.Tr "username"}}</label>
|
||||
<input
|
||||
id="user_name"
|
||||
name="user_name"
|
||||
type="text"
|
||||
value="{{.user_name}}"
|
||||
autofocus
|
||||
required
|
||||
aria-required="true"
|
||||
autocomplete="username"
|
||||
placeholder="{{.locale.Tr "username"}}"
|
||||
/>
|
||||
</div>
|
||||
{{template "user/auth/captcha" .}}
|
||||
|
||||
{{/* a11y R1: Password field with visibility toggle */}}
|
||||
<div class="field" style="position:relative">
|
||||
<label for="password">{{.locale.Tr "password"}}</label>
|
||||
<div style="display:flex;align-items:center;position:relative">
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
required
|
||||
aria-required="true"
|
||||
autocomplete="current-password"
|
||||
placeholder="{{.locale.Tr "password"}}"
|
||||
style="flex:1;padding-right:36px"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
id="toggle-password"
|
||||
aria-label="Show password"
|
||||
title="Show password"
|
||||
style="position:absolute;right:8px;background:none;border:none;cursor:pointer;padding:4px;color:#666;font-size:16px"
|
||||
onclick="togglePasswordVisibility()"
|
||||
>👁</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<button type="submit" class="ui green button">
|
||||
{{.locale.Tr "sign_in"}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{if .EnableOAuth2}}
|
||||
<div class="ui divider"></div>
|
||||
<div class="field">
|
||||
<a href="{{AppSubUrl}}/user/oauth2" class="ui basic button">
|
||||
{{.locale.Tr "sign_in_with_provider"}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</form>
|
||||
</div>
|
||||
<div class="field">
|
||||
<button class="ui primary button tw-w-full" tabindex="3">
|
||||
{{if .LinkAccountMode}}
|
||||
{{ctx.Locale.Tr "auth.oauth_signin_submit"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "sign_in"}}
|
||||
{{end}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{{end}}{{/*end if .EnablePasswordSignInForm*/}}
|
||||
{{$showExternalAuthMethods := or .OAuth2Providers .EnableOpenIDSignIn .EnableSSPI}}
|
||||
{{if and $showExternalAuthMethods .EnablePasswordSignInForm}}
|
||||
<div class="divider divider-text">{{ctx.Locale.Tr "sign_in_or"}}</div>
|
||||
{{end}}
|
||||
{{if $showExternalAuthMethods}}
|
||||
{{template "user/auth/external_auth_methods" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if or .EnablePasskeyAuth .ShowRegistrationButton}}
|
||||
<div class="ui container fluid">
|
||||
<div class="ui attached segment header top tw-max-w-2xl tw-m-auto tw-flex tw-flex-col tw-items-center">
|
||||
{{if .EnablePasskeyAuth}}
|
||||
{{template "user/auth/webauthn_error" .}}
|
||||
<a class="signin-passkey">{{ctx.Locale.Tr "auth.signin_passkey"}}</a>
|
||||
{{end}}
|
||||
|
||||
{{if .ShowRegistrationButton}}
|
||||
<div class="field">
|
||||
<span>{{ctx.Locale.Tr "auth.need_account"}}</span>
|
||||
<a href="{{AppSubUrl}}/user/sign_up">{{ctx.Locale.Tr "auth.sign_up_now"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
function togglePasswordVisibility() {
|
||||
const input = document.getElementById('password');
|
||||
@@ -83,14 +105,13 @@ function togglePasswordVisibility() {
|
||||
if (input.type === 'password') {
|
||||
input.type = 'text';
|
||||
btn.textContent = '🙈';
|
||||
btn.setAttribute('aria-label', 'Hide password');
|
||||
btn.setAttribute('title', 'Hide password');
|
||||
btn.setAttribute('aria-label', '{{ctx.Locale.Tr "auth.hide_password"}}');
|
||||
btn.setAttribute('title', '{{ctx.Locale.Tr "auth.hide_password"}}');
|
||||
} else {
|
||||
input.type = 'password';
|
||||
btn.textContent = '👁';
|
||||
btn.setAttribute('aria-label', 'Show password');
|
||||
btn.setAttribute('title', 'Show password');
|
||||
btn.setAttribute('aria-label', '{{ctx.Locale.Tr "auth.show_password"}}');
|
||||
btn.setAttribute('title', '{{ctx.Locale.Tr "auth.show_password"}}');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{{template "base/footer" .}}
|
||||
|
||||
Reference in New Issue
Block a user