passwords: Add keyboard accessibility for show/hide password icons.

Tweaked by tabbott to add the required tabindex configuration in the
password reset, password change, and registration forms as well.
This commit is contained in:
abdelrahman725 2024-03-01 01:29:45 +00:00 committed by Tim Abbott
parent a43e9140f2
commit b0a4b8e439
6 changed files with 33 additions and 12 deletions

View File

@ -109,7 +109,7 @@ page can be easily identified in it's respective JavaScript file. -->
{% if email %} autofocus {% endif %}
required />
<label for="id_password">{{ _('Password') }}</label>
<i class="fa fa-eye-slash password_visibility_toggle" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
</div>
{% else %}
{% include "two_factor/_wizard_forms.html" %}

View File

@ -136,7 +136,7 @@ Form is validated both client-side using jquery-validation (see signup.js) and s
<div class="input-box password-div">
<input id="ldap-password" class="required" type="password" name="password" autocomplete="off" required />
<label for="ldap-password" class="inline-block">{{ _('Password') }}</label>
<i class="fa fa-eye-slash password_visibility_toggle" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
<span class="help-inline">
{{ _('Enter your LDAP/Active Directory password.') }}
</span>
@ -149,7 +149,7 @@ Form is validated both client-side using jquery-validation (see signup.js) and s
data-min-length="{{password_min_length}}"
data-min-guesses="{{password_min_guesses}}" required />
<label for="id_password" class="inline-block">{{ _('Password') }}</label>
<i class="fa fa-eye-slash password_visibility_toggle" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
{% if full_name %}
<span class="help-inline">
{{ _('This is used for mobile applications and other tools that require a password.') }}

View File

@ -34,7 +34,7 @@
maxlength="100"
data-min-length="{{password_min_length}}"
data-min-guesses="{{password_min_guesses}}" autofocus required />
<i class="fa fa-eye-slash password_visibility_toggle" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
{% if form.new_password1.errors %}
{% for error in form.new_password1.errors %}
<div class="alert alert-error">{{ error }}</div>
@ -53,7 +53,7 @@
<input id="id_new_password2" class="required" type="password" name="new_password2" autocomplete="off"
value="{% if form.new_password2.value() %}{{ form.new_password2.value() }}{% endif %}"
maxlength="100" required />
<i class="fa fa-eye-slash password_visibility_toggle" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
{% if form.new_password2.errors %}
{% for error in form.new_password2.errors %}
<div class="alert alert-error">{{ error }}</div>

View File

@ -172,4 +172,11 @@ export function setup_password_visibility_toggle(
e.stopPropagation();
toggle_password_visibility(password_field_id, password_selector, tippy_tooltips);
});
$(password_selector).on("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
e.stopPropagation();
toggle_password_visibility(password_field_id, password_selector, tippy_tooltips);
}
});
}

View File

@ -2,7 +2,7 @@
<div class="password-div">
<label for="old_password" class="dropdown-title">{{t "Old password" }}</label>
<input type="password" autocomplete="off" name="old_password" id="old_password" class="w-200 inline-block modal_password_input" value="" />
<i class="fa fa-eye-slash password_visibility_toggle tippy-zulip-tooltip" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle tippy-zulip-tooltip" role="button" tabindex="0"></i>
<div class="settings-forgot-password">
<a href="/accounts/password/reset/" class="sea-green" target="_blank" rel="noopener noreferrer">{{t "Forgot it?" }}</a>
</div>
@ -11,7 +11,7 @@
<label for="new_password" class="dropdown-title">{{t "New password" }}</label>
<input type="password" autocomplete="new-password" name="new_password" id="new_password" class="w-200 inline-block modal_password_input" value=""
data-min-length="{{password_min_length}}" data-min-guesses="{{password_min_guesses}}" />
<i class="fa fa-eye-slash password_visibility_toggle tippy-zulip-tooltip" role="button"></i>
<i class="fa fa-eye-slash password_visibility_toggle tippy-zulip-tooltip" role="button" tabindex="0"></i>
<div class="progress inline-block" id="pw_strength">
<div class="bar bar-danger hide" style="width: 10%;"></div>
</div>

View File

@ -234,7 +234,13 @@ run_test("show password", () => {
assert.ok(!$(password_selector).hasClass(absent_class));
}
const ev = {
const click_ev = {
preventDefault() {},
stopPropagation() {},
};
const key_ev = {
key: "Enter",
preventDefault() {},
stopPropagation() {},
};
@ -242,15 +248,23 @@ run_test("show password", () => {
set_attribute("password");
common.setup_password_visibility_toggle("#id_password", password_selector);
const handler = $(password_selector).get_on_handler("click");
const click_handler = $(password_selector).get_on_handler("click");
handler(ev);
const key_handler = $(password_selector).get_on_handler("keydown");
click_handler(click_ev);
check_assertion("text", "fa-eye", "fa-eye-slash");
handler(ev);
click_handler(click_ev);
check_assertion("password", "fa-eye-slash", "fa-eye");
handler(ev);
key_handler(key_ev);
check_assertion("text", "fa-eye", "fa-eye-slash");
key_handler(key_ev);
check_assertion("password", "fa-eye-slash", "fa-eye");
click_handler(click_ev);
common.reset_password_toggle_icons("#id_password", password_selector);
check_assertion("password", "fa-eye-slash", "fa-eye");