From 8819b843531977fa0f1cb28c6279c80fc6d4b2d2 Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Wed, 23 Apr 2025 19:53:22 +0530 Subject: [PATCH 01/20] Add caps lock warning on login screen --- src/js/_enqueues/admin/user-profile.js | 27 +++++++++++++ src/wp-admin/css/login.css | 53 ++++++++++++++++++++++++++ src/wp-login.php | 9 +++++ 3 files changed, 89 insertions(+) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 2aebe62a91f94..f46935587e09b 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -203,6 +203,33 @@ } else { // Password field for the login form. $pass1 = $( '#user_pass' ); + + /** + * Monitors the Caps Lock status while the user is typing in the password input field. + * If Caps Lock is detected to be ON, a warning message is shown. + * The warning is hidden when the input field loses focus or when Caps Lock is OFF. + */ + var $capsWarning = $( '#caps-warning' ); + + $pass1.on( 'keypress', function( e ) { + var $charPass = String.fromCharCode( e.which ); + + var $isShift = e.shiftKey; + var $isCapsLockOn = ( $charPass.toUpperCase() === $charPass && !$isShift ) || ( $charPass.toLowerCase() === $charPass && $isShift ); + + if ( $isCapsLockOn ) { + $capsWarning.show(); + } else { + $capsWarning.hide(); + } + }); + + /** + * Hides the Caps Lock warning when the password input loses focus. + */ + $pass1.on( 'blur', function( e ) { + $capsWarning.hide(); + }); } /* diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index bd14b6db22a8e..286f8acdda9b0 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -452,6 +452,59 @@ input::-ms-reveal { margin-bottom: 0; } +.login .caps-warning { + display: none; + position: absolute; + background: #FFF8E5; + border: 1px solid #ddd; + border-radius: 3px; + color: #564300; + font-size: 13px; + padding: 6px 10px; + top: calc(100% - 10px); + left: 24px; + white-space: nowrap; + z-index: 10; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +.login .caps-warning::before { + content: ''; + position: absolute; + bottom: 100%; + left: 15px; + margin-left: -8px; + border-width: 8px; + border-style: solid; + border-color: transparent transparent #ddd transparent; +} + +.login .caps-warning::after { + content: ''; + position: absolute; + bottom: 100%; + left: 15px; + margin-left: -7px; + border-width: 7px; + border-style: solid; + border-color: transparent transparent #fff8e5 transparent; +} + +.login .caps-icon { + display: inline-flex; + justify-content: center; + background-color: #FFA328; + width: 20px; + height: 20px; + border-radius: 3px; + margin-right: 5px; + vertical-align: middle; +} + +.login .caps-warning-text { + vertical-align: middle; +} + @media screen and (max-height: 550px) { #login { padding: 20px 0; diff --git a/src/wp-login.php b/src/wp-login.php index 0d824dea655ea..bfb178d5048fd 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -1522,6 +1522,15 @@ function wp_login_viewport_meta() { +
+ + + + + + + +
Date: Wed, 23 Apr 2025 20:04:23 +0530 Subject: [PATCH 02/20] Fix javaScript coding standards --- src/js/_enqueues/admin/user-profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index f46935587e09b..938ca5812b3cc 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -227,7 +227,7 @@ /** * Hides the Caps Lock warning when the password input loses focus. */ - $pass1.on( 'blur', function( e ) { + $pass1.on( 'blur', function() { $capsWarning.hide(); }); } From 1904fadff107fb686a49bb4c23b16d6ec3ff8389 Mon Sep 17 00:00:00 2001 From: nikunj8866 Date: Thu, 8 May 2025 15:22:01 +0530 Subject: [PATCH 03/20] Added caps warning for Add/Edit Users password field --- src/js/_enqueues/admin/user-profile.js | 44 ++++++++++++++++++--- src/wp-admin/css/forms.css | 55 ++++++++++++++++++++++++++ src/wp-admin/css/login.css | 2 + src/wp-admin/user-edit.php | 9 +++++ src/wp-admin/user-new.php | 9 +++++ 5 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 938ca5812b3cc..74aac9ec0d7eb 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -80,6 +80,28 @@ $pass1.removeClass( 'short bad good strong' ); showOrHideWeakPasswordCheckbox(); } ); + + /** + * Monitors the Caps Lock status while the user is typing in the password input field. + * If Caps Lock is detected to be ON, a warning message is shown. + * The warning is hidden when the input field loses focus or when Caps Lock is OFF. + */ + var $capsWarning = $( '#caps-warning' ); + + $pass1.on( 'keypress', function( e ) { + if ( isCapsLockOn( e ) ) { + $capsWarning.show(); + } else { + $capsWarning.hide(); + } + }); + + /** + * Hides the Caps Lock warning when the password input loses focus. + */ + $pass1.on( 'blur', function() { + $capsWarning.hide(); + }); } function resetToggle( show ) { @@ -212,12 +234,7 @@ var $capsWarning = $( '#caps-warning' ); $pass1.on( 'keypress', function( e ) { - var $charPass = String.fromCharCode( e.which ); - - var $isShift = e.shiftKey; - var $isCapsLockOn = ( $charPass.toUpperCase() === $charPass && !$isShift ) || ( $charPass.toLowerCase() === $charPass && $isShift ); - - if ( $isCapsLockOn ) { + if ( isCapsLockOn( e ) ) { $capsWarning.show(); } else { $capsWarning.hide(); @@ -349,6 +366,21 @@ } } + /** + * Determines if the Caps Lock is on based on keypress event. + */ + function isCapsLockOn( e ) { + const char = String.fromCharCode( e.which || e.keyCode ); + + // Skip non-printable characters + if (!char.match(/[a-zA-Z]/)) return false; + + return ( + (char === char.toUpperCase() && !e.shiftKey) || + (char === char.toLowerCase() && e.shiftKey) + ); + } + function showOrHideWeakPasswordCheckbox() { var passStrengthResult = $('#pass-strength-result'); diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index ffe2c1711e7a1..c20e62cfcd5e7 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -719,6 +719,61 @@ fieldset label, display: inline-block; } +/* Caps lock warning */ +.wp-pwd .caps-warning { + display: none; + position: absolute; + background: #FFF8E5; + border: 1px solid #ddd; + border-radius: 3px; + color: #564300; + font-size: 13px; + padding: 6px 10px; + top: calc(100% - 25px); + left: 24px; + white-space: nowrap; + z-index: 10; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +.wp-pwd .caps-warning::before { + content: ''; + position: absolute; + bottom: 100%; + left: 15px; + margin-left: -8px; + border-width: 8px; + border-style: solid; + border-color: transparent transparent #ddd transparent; +} + +.wp-pwd .caps-warning::after { + content: ''; + position: absolute; + bottom: 100%; + left: 15px; + margin-left: -7px; + border-width: 7px; + border-style: solid; + border-color: transparent transparent #fff8e5 transparent; +} + +.wp-pwd .caps-icon { + display: inline-flex; + justify-content: center; + background-color: #FFA328; + width: 20px; + height: 20px; + border-radius: 3px; + margin-right: 5px; + vertical-align: middle; +} + +.wp-pwd .caps-warning-text { + vertical-align: middle; +} +/* Caps lock warning */ + p.search-box { display: flex; flex-wrap: wrap; diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index 286f8acdda9b0..a00736cc830fe 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -452,6 +452,7 @@ input::-ms-reveal { margin-bottom: 0; } +/* Caps lock warning */ .login .caps-warning { display: none; position: absolute; @@ -504,6 +505,7 @@ input::-ms-reveal { .login .caps-warning-text { vertical-align: middle; } +/* Caps lock warning */ @media screen and (max-height: 550px) { #login { diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index c476a294adf08..45947819f564b 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -689,6 +689,15 @@ +
+ + + + + + + +
diff --git a/src/wp-admin/user-new.php b/src/wp-admin/user-new.php index cdc1dfef1e8d9..0e885bd65c5f0 100644 --- a/src/wp-admin/user-new.php +++ b/src/wp-admin/user-new.php @@ -607,6 +607,15 @@ +
+ + + + + + + +
From 245a022162b260fc6b9c4b920fce80a7a60e86af Mon Sep 17 00:00:00 2001 From: nikunj8866 Date: Wed, 14 May 2025 20:22:48 +0530 Subject: [PATCH 04/20] Changed warning color and bypass warning in macOS --- src/js/_enqueues/admin/user-profile.js | 9 ++++++++- src/wp-admin/css/forms.css | 8 ++++---- src/wp-admin/css/login.css | 8 ++++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 74aac9ec0d7eb..c992d5bfa8464 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -20,7 +20,9 @@ $form, originalFormContent, $passwordWrapper, - successTimeout; + successTimeout, + isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false, + ua = navigator.userAgent.toLowerCase(); function generatePassword() { if ( typeof zxcvbn !== 'function' ) { @@ -375,6 +377,11 @@ // Skip non-printable characters if (!char.match(/[a-zA-Z]/)) return false; + // Skip warning on macOS Safari or Chrome (they show native caps lock warnings) + if ( isMac && ( ua.indexOf( 'safari' ) !== -1 || ua.indexOf( 'chrome' ) !== -1 ) ) { + return false; + } + return ( (char === char.toUpperCase() && !e.shiftKey) || (char === char.toLowerCase() && e.shiftKey) diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index c20e62cfcd5e7..91aa659422517 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -723,10 +723,10 @@ fieldset label, .wp-pwd .caps-warning { display: none; position: absolute; - background: #FFF8E5; + background: #FFE9DE; border: 1px solid #ddd; border-radius: 3px; - color: #564300; + color: #1E1E20; font-size: 13px; padding: 6px 10px; top: calc(100% - 25px); @@ -755,13 +755,13 @@ fieldset label, margin-left: -7px; border-width: 7px; border-style: solid; - border-color: transparent transparent #fff8e5 transparent; + border-color: transparent transparent #FFE9DE transparent; } .wp-pwd .caps-icon { display: inline-flex; justify-content: center; - background-color: #FFA328; + background-color: #E26F56; width: 20px; height: 20px; border-radius: 3px; diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index a00736cc830fe..25eb5f4017bea 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -456,10 +456,10 @@ input::-ms-reveal { .login .caps-warning { display: none; position: absolute; - background: #FFF8E5; + background: #FFE9DE; border: 1px solid #ddd; border-radius: 3px; - color: #564300; + color: #1E1E20; font-size: 13px; padding: 6px 10px; top: calc(100% - 10px); @@ -488,13 +488,13 @@ input::-ms-reveal { margin-left: -7px; border-width: 7px; border-style: solid; - border-color: transparent transparent #fff8e5 transparent; + border-color: transparent transparent #FFE9DE transparent; } .login .caps-icon { display: inline-flex; justify-content: center; - background-color: #FFA328; + background-color: #E26F56; width: 20px; height: 20px; border-radius: 3px; From 91445513c4a0fce36abc291bf0687979a62933d7 Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Mon, 9 Jun 2025 13:28:55 +0530 Subject: [PATCH 05/20] Changed notification color to yellow, Added screen readers capabilities and used KeyboardEvent.getModifierState() for checking --- src/js/_enqueues/admin/user-profile.js | 49 +++++++++++++---------- src/wp-admin/css/forms.css | 6 +-- src/wp-admin/css/login.css | 55 -------------------------- src/wp-admin/user-edit.php | 2 +- src/wp-admin/user-new.php | 2 +- src/wp-login.php | 2 +- 6 files changed, 35 insertions(+), 81 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index c992d5bfa8464..5b866cc6d0732 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -85,14 +85,16 @@ /** * Monitors the Caps Lock status while the user is typing in the password input field. - * If Caps Lock is detected to be ON, a warning message is shown. - * The warning is hidden when the input field loses focus or when Caps Lock is OFF. + * + * Shows a warning if Caps Lock is detected. Also uses wp.a11y.speak() + * for screen readers. Hides the warning on blur or when Caps Lock is not on. */ var $capsWarning = $( '#caps-warning' ); - $pass1.on( 'keypress', function( e ) { - if ( isCapsLockOn( e ) ) { + $pass1.on( 'keydown', function( e ) { + if ( isCapsLockOn( e.originalEvent || e ) ) { $capsWarning.show(); + wp.a11y.speak( __( 'Caps lock is on.' ) ); } else { $capsWarning.hide(); } @@ -230,14 +232,16 @@ /** * Monitors the Caps Lock status while the user is typing in the password input field. - * If Caps Lock is detected to be ON, a warning message is shown. - * The warning is hidden when the input field loses focus or when Caps Lock is OFF. + * + * Shows a warning if Caps Lock is detected. Also uses wp.a11y.speak() + * for screen readers. Hides the warning on blur or when Caps Lock is not on. */ var $capsWarning = $( '#caps-warning' ); - $pass1.on( 'keypress', function( e ) { - if ( isCapsLockOn( e ) ) { + $pass1.on( 'keydown', function( e ) { + if ( isCapsLockOn( e.originalEvent || e ) ) { $capsWarning.show(); + wp.a11y.speak( __( 'Caps lock is on.' ) ); } else { $capsWarning.hide(); } @@ -369,23 +373,28 @@ } /** - * Determines if the Caps Lock is on based on keypress event. + * Determines if Caps Lock is currently enabled. + * + * Uses `KeyboardEvent.getModifierState()` when available, with a fallback + * for older browsers. On macOS Safari and Chrome, the native warning is preferred, + * so this function returns false to suppress custom warnings. + * + * @param {KeyboardEvent} e The keydown event object. + * + * @return {boolean} True if Caps Lock is on, false otherwise. */ function isCapsLockOn( e ) { - const char = String.fromCharCode( e.which || e.keyCode ); - - // Skip non-printable characters - if (!char.match(/[a-zA-Z]/)) return false; - - // Skip warning on macOS Safari or Chrome (they show native caps lock warnings) - if ( isMac && ( ua.indexOf( 'safari' ) !== -1 || ua.indexOf( 'chrome' ) !== -1 ) ) { + // Skip warning on macOS Safari or Chrome (they show native indicators). + if ( + isMac && + ( ua.indexOf( 'safari' ) !== -1 || ua.indexOf( 'chrome' ) !== -1 ) + ) { return false; } - return ( - (char === char.toUpperCase() && !e.shiftKey) || - (char === char.toLowerCase() && e.shiftKey) - ); + if ( typeof e.getModifierState === 'function' ) { + return e.getModifierState( 'CapsLock' ); + } } function showOrHideWeakPasswordCheckbox() { diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index 91aa659422517..0d6d58e42beb6 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -723,7 +723,7 @@ fieldset label, .wp-pwd .caps-warning { display: none; position: absolute; - background: #FFE9DE; + background: #FFFDD6; border: 1px solid #ddd; border-radius: 3px; color: #1E1E20; @@ -755,13 +755,13 @@ fieldset label, margin-left: -7px; border-width: 7px; border-style: solid; - border-color: transparent transparent #FFE9DE transparent; + border-color: transparent transparent #FFFDD6 transparent; } .wp-pwd .caps-icon { display: inline-flex; justify-content: center; - background-color: #E26F56; + background-color: #FFF972; width: 20px; height: 20px; border-radius: 3px; diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index 25eb5f4017bea..bd14b6db22a8e 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -452,61 +452,6 @@ input::-ms-reveal { margin-bottom: 0; } -/* Caps lock warning */ -.login .caps-warning { - display: none; - position: absolute; - background: #FFE9DE; - border: 1px solid #ddd; - border-radius: 3px; - color: #1E1E20; - font-size: 13px; - padding: 6px 10px; - top: calc(100% - 10px); - left: 24px; - white-space: nowrap; - z-index: 10; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); -} - -.login .caps-warning::before { - content: ''; - position: absolute; - bottom: 100%; - left: 15px; - margin-left: -8px; - border-width: 8px; - border-style: solid; - border-color: transparent transparent #ddd transparent; -} - -.login .caps-warning::after { - content: ''; - position: absolute; - bottom: 100%; - left: 15px; - margin-left: -7px; - border-width: 7px; - border-style: solid; - border-color: transparent transparent #FFE9DE transparent; -} - -.login .caps-icon { - display: inline-flex; - justify-content: center; - background-color: #E26F56; - width: 20px; - height: 20px; - border-radius: 3px; - margin-right: 5px; - vertical-align: middle; -} - -.login .caps-warning-text { - vertical-align: middle; -} -/* Caps lock warning */ - @media screen and (max-height: 550px) { #login { padding: 20px 0; diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 45947819f564b..b0f7095b58cc9 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -691,7 +691,7 @@
- + diff --git a/src/wp-admin/user-new.php b/src/wp-admin/user-new.php index 0e885bd65c5f0..c460470508d61 100644 --- a/src/wp-admin/user-new.php +++ b/src/wp-admin/user-new.php @@ -609,7 +609,7 @@
- + diff --git a/src/wp-login.php b/src/wp-login.php index bfb178d5048fd..477d6142194bc 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -1524,7 +1524,7 @@ function wp_login_viewport_meta() {
- + From 4627c8f87dc3e240f6d6aeae1344ff3e024dcbad Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Mon, 9 Jun 2025 18:53:32 +0530 Subject: [PATCH 06/20] Optimize JS code to remove identical code --- src/js/_enqueues/admin/user-profile.js | 70 +++++++++----------------- 1 file changed, 24 insertions(+), 46 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 5b866cc6d0732..efeefa9fed0b3 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -83,29 +83,7 @@ showOrHideWeakPasswordCheckbox(); } ); - /** - * Monitors the Caps Lock status while the user is typing in the password input field. - * - * Shows a warning if Caps Lock is detected. Also uses wp.a11y.speak() - * for screen readers. Hides the warning on blur or when Caps Lock is not on. - */ - var $capsWarning = $( '#caps-warning' ); - - $pass1.on( 'keydown', function( e ) { - if ( isCapsLockOn( e.originalEvent || e ) ) { - $capsWarning.show(); - wp.a11y.speak( __( 'Caps lock is on.' ) ); - } else { - $capsWarning.hide(); - } - }); - - /** - * Hides the Caps Lock warning when the password input loses focus. - */ - $pass1.on( 'blur', function() { - $capsWarning.hide(); - }); + bindCapsLockWarning( $pass1 ); } function resetToggle( show ) { @@ -230,29 +208,7 @@ // Password field for the login form. $pass1 = $( '#user_pass' ); - /** - * Monitors the Caps Lock status while the user is typing in the password input field. - * - * Shows a warning if Caps Lock is detected. Also uses wp.a11y.speak() - * for screen readers. Hides the warning on blur or when Caps Lock is not on. - */ - var $capsWarning = $( '#caps-warning' ); - - $pass1.on( 'keydown', function( e ) { - if ( isCapsLockOn( e.originalEvent || e ) ) { - $capsWarning.show(); - wp.a11y.speak( __( 'Caps lock is on.' ) ); - } else { - $capsWarning.hide(); - } - }); - - /** - * Hides the Caps Lock warning when the password input loses focus. - */ - $pass1.on( 'blur', function() { - $capsWarning.hide(); - }); + bindCapsLockWarning( $pass1 ); } /* @@ -372,6 +328,28 @@ } } + /** + * Binds Caps Lock detection to a given password input field. + * + * @param {jQuery} $input The password input field. + */ + function bindCapsLockWarning( $input ) { + var $capsWarning = $( '#caps-warning' ); + + $input.on( 'keydown', function( e ) { + if ( isCapsLockOn( e.originalEvent || e ) ) { + $capsWarning.show(); + wp.a11y.speak( __( 'Caps lock is on.' ) ); + } else { + $capsWarning.hide(); + } + } ); + + $input.on( 'blur', function() { + $capsWarning.hide(); + } ); + } + /** * Determines if Caps Lock is currently enabled. * From d0f71ebf6eb65b26383d59dac74fc080181de4ae Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Fri, 4 Jul 2025 17:35:22 +0530 Subject: [PATCH 07/20] Remove mac chrome from the skip --- src/js/_enqueues/admin/user-profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index efeefa9fed0b3..7a699735c1814 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -365,7 +365,7 @@ // Skip warning on macOS Safari or Chrome (they show native indicators). if ( isMac && - ( ua.indexOf( 'safari' ) !== -1 || ua.indexOf( 'chrome' ) !== -1 ) + ( ua.indexOf( 'safari' ) !== -1 ) ) { return false; } From 1930260a8e8e2337fffd90832064135d0526afa7 Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Fri, 4 Jul 2025 17:36:24 +0530 Subject: [PATCH 08/20] update js doc comment --- src/js/_enqueues/admin/user-profile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 7a699735c1814..d07f2edc73534 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -354,7 +354,7 @@ * Determines if Caps Lock is currently enabled. * * Uses `KeyboardEvent.getModifierState()` when available, with a fallback - * for older browsers. On macOS Safari and Chrome, the native warning is preferred, + * for older browsers. On macOS Safari, the native warning is preferred, * so this function returns false to suppress custom warnings. * * @param {KeyboardEvent} e The keydown event object. @@ -362,7 +362,7 @@ * @return {boolean} True if Caps Lock is on, false otherwise. */ function isCapsLockOn( e ) { - // Skip warning on macOS Safari or Chrome (they show native indicators). + // Skip warning on macOS Safari (they show native indicators). if ( isMac && ( ua.indexOf( 'safari' ) !== -1 ) From eb15fdf2d2ca97fcd45d9b00ac20ea8184814296 Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Tue, 9 Sep 2025 19:02:15 +0530 Subject: [PATCH 09/20] fix browser detection issue for macOS and disable checking capslock for every keydown --- src/js/_enqueues/admin/user-profile.js | 46 ++++++++++++++++++-------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index d07f2edc73534..a5f299caaf047 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -22,7 +22,9 @@ $passwordWrapper, successTimeout, isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false, - ua = navigator.userAgent.toLowerCase(); + ua = navigator.userAgent.toLowerCase(), + isSafari = ua.indexOf( 'safari' ) !== -1 && ua.indexOf( 'chrome' ) === -1, + isFirefox = ua.indexOf( 'firefox' ) !== -1; function generatePassword() { if ( typeof zxcvbn !== 'function' ) { @@ -334,18 +336,40 @@ * @param {jQuery} $input The password input field. */ function bindCapsLockWarning( $input ) { - var $capsWarning = $( '#caps-warning' ); + var $capsWarning = $( '#caps-warning' ), + capsLockOn = false; $input.on( 'keydown', function( e ) { - if ( isCapsLockOn( e.originalEvent || e ) ) { - $capsWarning.show(); - wp.a11y.speak( __( 'Caps lock is on.' ) ); - } else { - $capsWarning.hide(); + var ev = e.originalEvent || e; + + // Skip CapsLock key itself. + if ( ev.key === 'CapsLock' ) { + return; + } + + // Skip if key is not a printable character. + // Key length > 1 usually means non-printable (e.g., "Enter", "Tab"). + if ( ev.ctrlKey || ev.metaKey || ev.altKey || ! ev.key || ev.key.length !== 1 ) { + return; + } + + var state = isCapsLockOn( ev ); + + // Only react when the state changes. + if ( state !== capsLockOn ) { + capsLockOn = state; + + if ( capsLockOn ) { + $capsWarning.show(); + wp.a11y.speak( __( 'Caps lock is on.' ) ); + } else { + $capsWarning.hide(); + } } } ); $input.on( 'blur', function() { + capsLockOn = false; $capsWarning.hide(); } ); } @@ -353,8 +377,7 @@ /** * Determines if Caps Lock is currently enabled. * - * Uses `KeyboardEvent.getModifierState()` when available, with a fallback - * for older browsers. On macOS Safari, the native warning is preferred, + * On macOS Safari and Firefox, the native warning is preferred, * so this function returns false to suppress custom warnings. * * @param {KeyboardEvent} e The keydown event object. @@ -363,10 +386,7 @@ */ function isCapsLockOn( e ) { // Skip warning on macOS Safari (they show native indicators). - if ( - isMac && - ( ua.indexOf( 'safari' ) !== -1 ) - ) { + if ( isMac && ( isSafari || isFirefox ) ) { return false; } From 6fe7673f9bdb95796c9ba86c228f75ab26c0cf4e Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Tue, 9 Sep 2025 19:05:34 +0530 Subject: [PATCH 10/20] update comment text --- src/js/_enqueues/admin/user-profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index a5f299caaf047..3c6ccf1f2c96d 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -385,7 +385,7 @@ * @return {boolean} True if Caps Lock is on, false otherwise. */ function isCapsLockOn( e ) { - // Skip warning on macOS Safari (they show native indicators). + // Skip warning on macOS Safari + Firefox (they show native indicators). if ( isMac && ( isSafari || isFirefox ) ) { return false; } From 0543ef5ded316a96165a9cdd23bb6a5856d4735e Mon Sep 17 00:00:00 2001 From: Nikunj Hatkar Date: Mon, 22 Sep 2025 19:47:39 +0530 Subject: [PATCH 11/20] hide warning when capslock off and fix popup design --- src/js/_enqueues/admin/user-profile.js | 4 +++ src/wp-admin/css/forms.css | 38 +++----------------------- src/wp-admin/user-edit.php | 18 ++++++------ src/wp-admin/user-new.php | 18 ++++++------ src/wp-login.php | 2 +- 5 files changed, 27 insertions(+), 53 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 91dc3278b48e6..1dd1588432a13 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -354,6 +354,10 @@ // Skip CapsLock key itself. if ( ev.key === 'CapsLock' ) { + if (capsLockOn) { + capsLockOn = false; + $capsWarning.hide(); + } return; } diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index ecd48b937992f..31c70430b5e76 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -717,46 +717,16 @@ fieldset label, /* Caps lock warning */ .wp-pwd .caps-warning { display: none; - position: absolute; - background: #FFFDD6; - border: 1px solid #ddd; - border-radius: 3px; - color: #1E1E20; - font-size: 13px; + position: relative; + background: #f5e6ab; padding: 6px 10px; - top: calc(100% - 25px); - left: 24px; - white-space: nowrap; - z-index: 10; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); -} - -.wp-pwd .caps-warning::before { - content: ''; - position: absolute; - bottom: 100%; - left: 15px; - margin-left: -8px; - border-width: 8px; - border-style: solid; - border-color: transparent transparent #ddd transparent; -} - -.wp-pwd .caps-warning::after { - content: ''; - position: absolute; - bottom: 100%; - left: 15px; - margin-left: -7px; - border-width: 7px; - border-style: solid; - border-color: transparent transparent #FFFDD6 transparent; + top: -8px; } .wp-pwd .caps-icon { display: inline-flex; justify-content: center; - background-color: #FFF972; + background-color: #fcf9e8; width: 20px; height: 20px; border-radius: 3px; diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 8189eed66ab5e..335d2079d237a 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -698,6 +698,15 @@
+
+ + + + + + + +
-
- - - - - - - -
diff --git a/src/wp-admin/user-new.php b/src/wp-admin/user-new.php index c460470508d61..4a7b4045e04a6 100644 --- a/src/wp-admin/user-new.php +++ b/src/wp-admin/user-new.php @@ -602,20 +602,20 @@
+
+ + + + + + + +
-
- - - - - - - -
diff --git a/src/wp-login.php b/src/wp-login.php index 99f0490eea86b..cfd461ad54e77 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -1524,7 +1524,7 @@ function wp_login_viewport_meta() {
- + From 325b0ef6248c124cc7937dd9ebf914746a62d9c3 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 11:30:01 -0500 Subject: [PATCH 12/20] Incorporate suggestions from @westonruter I have some additional changes I want to make to this and haven't seen any activity from @nikunj8866 recently. --- src/js/_enqueues/admin/user-profile.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 1dd1588432a13..32a21c4fc7220 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -349,12 +349,17 @@ var $capsWarning = $( '#caps-warning' ), capsLockOn = false; - $input.on( 'keydown', function( e ) { - var ev = e.originalEvent || e; + // Skip warning on macOS Safari + Firefox (they show native indicators). + if ( isMac && ( isSafari || isFirefox ) ) { + return; + } + + $input.on( 'keydown', function( jqEvent ) { + var event = jqEvent.originalEvent; // Skip CapsLock key itself. if ( ev.key === 'CapsLock' ) { - if (capsLockOn) { + if ( capsLockOn ) { capsLockOn = false; $capsWarning.hide(); } @@ -363,11 +368,11 @@ // Skip if key is not a printable character. // Key length > 1 usually means non-printable (e.g., "Enter", "Tab"). - if ( ev.ctrlKey || ev.metaKey || ev.altKey || ! ev.key || ev.key.length !== 1 ) { + if ( event.ctrlKey || event.metaKey || event.altKey || ! event.key || event.key.length !== 1 ) { return; } - var state = isCapsLockOn( ev ); + var state = isCapsLockOn( event ); // Only react when the state changes. if ( state !== capsLockOn ) { @@ -398,15 +403,8 @@ * * @return {boolean} True if Caps Lock is on, false otherwise. */ - function isCapsLockOn( e ) { - // Skip warning on macOS Safari + Firefox (they show native indicators). - if ( isMac && ( isSafari || isFirefox ) ) { - return false; - } - - if ( typeof e.getModifierState === 'function' ) { - return e.getModifierState( 'CapsLock' ); - } + function isCapsLockOn( event ) { + return event.getModifierState( 'CapsLock' ); } function showOrHideWeakPasswordCheckbox() { From a136b1882f939f33f9d8f7d84d01d6f337eacccf Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 13:15:32 -0500 Subject: [PATCH 13/20] Caps lock warning improvements Move caps lock warning output to JS to reduce code duplication; fix issue where changes were not registered in capslock key pressed; improve comments; styling changes. --- src/js/_enqueues/admin/user-profile.js | 27 +++++++++++++------------- src/wp-admin/css/forms.css | 16 +++++++-------- src/wp-admin/user-edit.php | 9 --------- src/wp-admin/user-new.php | 9 --------- src/wp-login.php | 9 --------- 5 files changed, 22 insertions(+), 48 deletions(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 32a21c4fc7220..f5bcb9df9ac61 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -346,26 +346,24 @@ * @param {jQuery} $input The password input field. */ function bindCapsLockWarning( $input ) { - var $capsWarning = $( '#caps-warning' ), - capsLockOn = false; + var $capsWarning, + capsLockOn = false; // Skip warning on macOS Safari + Firefox (they show native indicators). if ( isMac && ( isSafari || isFirefox ) ) { return; } + $capsWarning = $( '
' ); + $capsIcon = $( '' ); + $capsText = $( '' + __( 'Caps lock is on.' ) + '' ); + $capsWarning.append( $capsIcon, $capsText ); + + $input.parent( 'div' ).append( $capsWarning ); + $input.on( 'keydown', function( jqEvent ) { var event = jqEvent.originalEvent; - // Skip CapsLock key itself. - if ( ev.key === 'CapsLock' ) { - if ( capsLockOn ) { - capsLockOn = false; - $capsWarning.hide(); - } - return; - } - // Skip if key is not a printable character. // Key length > 1 usually means non-printable (e.g., "Enter", "Tab"). if ( event.ctrlKey || event.metaKey || event.altKey || ! event.key || event.key.length !== 1 ) { @@ -374,13 +372,16 @@ var state = isCapsLockOn( event ); - // Only react when the state changes. + // React when the state changes or if caps lock is on when the user starts typing. if ( state !== capsLockOn ) { capsLockOn = state; if ( capsLockOn ) { $capsWarning.show(); - wp.a11y.speak( __( 'Caps lock is on.' ) ); + // Don't duplicate existing screen reader Caps lock notifications. + if ( event.key !== 'CapsLock' ) { + wp.a11y.speak( __( 'Caps lock is on.' ), 'assertive' ); + } } else { $capsWarning.hide(); } diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index 7c4e7cccb06f2..7ae32810bceb3 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -717,20 +717,20 @@ fieldset label, .wp-pwd .caps-warning { display: none; position: relative; - background: #f5e6ab; + background: #fcf9e8; + border: 1px solid #f0c33c; + color: #1d2327; padding: 6px 10px; top: -8px; } .wp-pwd .caps-icon { display: inline-flex; - justify-content: center; - background-color: #fcf9e8; - width: 20px; - height: 20px; - border-radius: 3px; - margin-right: 5px; - vertical-align: middle; + justify-content: center; + width: 20px; + height: 20px; + margin-right: 5px; + vertical-align: middle; } .wp-pwd .caps-warning-text { diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 335d2079d237a..1b5381be3f20c 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -698,15 +698,6 @@
-
- - - - - - - -
-
- - - - - - - -
Date: Sun, 19 Oct 2025 13:36:51 -0500 Subject: [PATCH 14/20] Adjust profile page styles to merge better with existing styling. --- src/wp-admin/css/forms.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index 7ae32810bceb3..67348c899a74d 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -724,6 +724,12 @@ fieldset label, top: -8px; } +.profile-php .wp-pwd .caps-warning { + padding: 3px 5px; + top: -4px; + border-radius: 4px; +} + .wp-pwd .caps-icon { display: inline-flex; justify-content: center; From 3a1f38ed8e298099b6dc6e76ce2c616f542b2f63 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 13:57:25 -0500 Subject: [PATCH 15/20] Fix Safari test so it doesn't return true on Chrome --- src/js/_enqueues/admin/user-profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index f5bcb9df9ac61..0a53748980e3f 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -23,7 +23,7 @@ successTimeout, isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false, ua = navigator.userAgent.toLowerCase(), - isSafari = ua.indexOf( 'safari' ) !== -1 && ua.indexOf( 'chrome' ) === -1, + isSafari = window.safari !== 'undefined' && typeof window.safari === 'object', isFirefox = ua.indexOf( 'firefox' ) !== -1; function generatePassword() { From 8c2362ff20852acd9743f7222ba79f58ec4216af Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 13:59:28 -0500 Subject: [PATCH 16/20] Missing var declarations --- src/js/_enqueues/admin/user-profile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 0a53748980e3f..a435929d802c9 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -347,6 +347,8 @@ */ function bindCapsLockWarning( $input ) { var $capsWarning, + $capsIcon, + $capsText, capsLockOn = false; // Skip warning on macOS Safari + Firefox (they show native indicators). From 113498e3b5f703b52d8e24b96b744be7cf0737b2 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 14:00:45 -0500 Subject: [PATCH 17/20] Change function description to be declarative. --- src/js/_enqueues/admin/user-profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index a435929d802c9..aa12d5b00f67e 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -341,7 +341,7 @@ } /** - * Binds Caps Lock detection to a given password input field. + * Bind Caps Lock detection to a password input field. * * @param {jQuery} $input The password input field. */ From af58caf573352ab0fe86eb841eea00c56ede3b9e Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 14:13:46 -0500 Subject: [PATCH 18/20] Update padding on mobile to match password strength --- src/wp-admin/css/forms.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index 67348c899a74d..31aca661db5a0 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -1672,6 +1672,10 @@ table.form-table td .updated p { padding: 8px; } + .profile-php .wp-pwd .caps-warning { + padding: 8px; + } + .password-input-wrapper { display: block; } From bee36eaad505ab5106930d9d668eecf392ea3634 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Sun, 19 Oct 2025 14:40:27 -0500 Subject: [PATCH 19/20] Only fire blur within the same document. --- src/js/_enqueues/admin/user-profile.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index aa12d5b00f67e..47acfe456f26c 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -391,6 +391,9 @@ } ); $input.on( 'blur', function() { + if ( ! document.hasFocus() ) { + return; + } capsLockOn = false; $capsWarning.hide(); } ); From 5f51e284166fe05f95ef33746b73561421013759 Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Mon, 20 Oct 2025 09:48:17 -0500 Subject: [PATCH 20/20] Update src/js/_enqueues/admin/user-profile.js Co-authored-by: Weston Ruter --- src/js/_enqueues/admin/user-profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/admin/user-profile.js b/src/js/_enqueues/admin/user-profile.js index 47acfe456f26c..5614078bb584a 100644 --- a/src/js/_enqueues/admin/user-profile.js +++ b/src/js/_enqueues/admin/user-profile.js @@ -358,7 +358,7 @@ $capsWarning = $( '
' ); $capsIcon = $( '' ); - $capsText = $( '' + __( 'Caps lock is on.' ) + '' ); + $capsText = $( '', { 'class': 'caps-warning-text', text: __( 'Caps lock is on.' ) } ); $capsWarning.append( $capsIcon, $capsText ); $input.parent( 'div' ).append( $capsWarning );