From 5e31ccfee21547844d889e3475ecf34177874983 Mon Sep 17 00:00:00 2001 From: Timothy Jacobs Date: Sat, 24 Oct 2020 03:32:46 +0000 Subject: [PATCH] App Passwords: Improve accessibility. - Make form inputs stacked instead of inline. - Provide a visible label for the app name. - Add screen reader text to dismiss button. - Make "Revoke" button label more descriptive. - Use aria-disabled instead of disabled to avoid focus loss. - Display password in a readonly input to assist copy and paste. - Remove large sections of italic text. - Use `.form-wrap` and `.form-field` to give consistent form styling. - Improve labeling and placeholder text. Props alexstine, georgestephanis, afercia, TimothyBlynJacobs. Fixes #51580. git-svn-id: https://develop.svn.wordpress.org/trunk@49294 602fd350-edb4-49c9-b593-d223f7449a82 --- .../_enqueues/admin/application-passwords.js | 11 +++-- src/js/_enqueues/admin/auth-app.js | 16 ++++--- src/wp-admin/authorize-application.php | 44 ++++++++++++++----- src/wp-admin/css/forms.css | 17 +++++++ ...ss-wp-application-passwords-list-table.php | 22 ++++++++-- src/wp-admin/user-edit.php | 16 ++++--- 6 files changed, 93 insertions(+), 33 deletions(-) diff --git a/src/js/_enqueues/admin/application-passwords.js b/src/js/_enqueues/admin/application-passwords.js index 1ba6e0e665..4ff58afddb 100644 --- a/src/js/_enqueues/admin/application-passwords.js +++ b/src/js/_enqueues/admin/application-passwords.js @@ -17,6 +17,11 @@ $newAppPassButton.click( function( e ) { e.preventDefault(); + + if ( $newAppPassButton.prop( 'aria-disabled' ) ) { + return; + } + var name = $newAppPassField.val(); if ( 0 === name.length ) { @@ -25,8 +30,7 @@ } clearErrors(); - $newAppPassField.prop( 'disabled', true ); - $newAppPassButton.prop( 'disabled', true ); + $newAppPassButton.prop( 'aria-disabled', true ).addClass( 'disabled' ); var request = { name: name @@ -47,8 +51,7 @@ method: 'POST', data: request } ).always( function() { - $newAppPassField.prop( 'disabled', false ); - $newAppPassButton.prop( 'disabled', false ); + $newAppPassButton.removeProp( 'aria-disabled' ).removeClass( 'disabled' ); } ).done( function( response ) { $newAppPassField.val( '' ); $newAppPassButton.prop( 'disabled', false ); diff --git a/src/js/_enqueues/admin/auth-app.js b/src/js/_enqueues/admin/auth-app.js index 592e074fb6..bd7fd5ac1a 100644 --- a/src/js/_enqueues/admin/auth-app.js +++ b/src/js/_enqueues/admin/auth-app.js @@ -21,13 +21,16 @@ e.preventDefault(); + if ( $approveBtn.prop( 'aria-disabled' ) ) { + return; + } + if ( 0 === name.length ) { $appNameField.focus(); return; } - $appNameField.prop( 'disabled', true ); - $approveBtn.prop( 'disabled', true ); + $approveBtn.prop( 'aria-disabled', true ).addClass( 'disabled' ); var request = { name: name @@ -82,17 +85,17 @@ message = wp.i18n.sprintf( wp.i18n.__( 'Your new password for %1$s is: %2$s.' ), '', - '' + '' ); $notice = $( '
' ) .attr( 'role', 'alert' ) .attr( 'tabindex', 0 ) .addClass( 'notice notice-success notice-alt' ) - .append( $( '

' ).html( message ) ); + .append( $( '

' ).addClass( 'application-password-display' ).html( message ) ); // We're using .text() to write the variables to avoid any chance of XSS. $( 'strong', $notice ).text( name ); - $( 'kbd', $notice ).text( response.password ); + $( 'input', $notice ).val( response.password ); $form.replaceWith( $notice ); $notice.focus(); @@ -116,8 +119,7 @@ $( 'h1' ).after( $notice ); - $appNameField.prop( 'disabled', false ); - $approveBtn.prop( 'disabled', false ); + $approveBtn.removeProp( 'aria-disabled', false ).removeClass( 'disabled' ); /** * Fires when an Authorize Application Password request encountered an error when trying to approve the request. diff --git a/src/wp-admin/authorize-application.php b/src/wp-admin/authorize-application.php index 6f4378892a..ea09b0486a 100644 --- a/src/wp-admin/authorize-application.php +++ b/src/wp-admin/authorize-application.php @@ -127,7 +127,7 @@ require_once ABSPATH . 'wp-admin/admin-header.php';

get_error_message(); ?>

-
+

@@ -170,13 +170,13 @@ require_once ABSPATH . 'wp-admin/admin-header.php';

-

+

' . esc_html( $app_name ) . '', - '' . esc_html( WP_Application_Passwords::chunk_password( $new_password ) ) . '' + sprintf( '', esc_attr( WP_Application_Passwords::chunk_password( $new_password ) ) ) ); ?>

@@ -195,15 +195,17 @@ require_once ABSPATH . 'wp-admin/admin-header.php'; do_action( 'wp_authorize_application_password_form', $request, $user ); ?> -
+ - - +
+ + +
-

-
+ 'description-approve', + ) + ); + ?> +

-

-

-
+ 'description-reject', + ) + ); + ?> +

-

diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index ea0cf75401..462b4bdec9 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -851,11 +851,28 @@ table.form-table td .updated p { cursor: pointer; } +.create-application-password .form-field { + max-width: 25em; +} + +.create-application-password label { + font-weight: 600; +} + +.create-application-password p.submit { + margin-bottom: 0; + padding-bottom: 0; +} + .new-application-password-notice.notice { margin-top: 20px; margin-bottom: 0; } +.application-password-display input.code { + width: 19em; +} + /*------------------------------------------------------------------------------ 19.0 - Tools ------------------------------------------------------------------------------*/ diff --git a/src/wp-admin/includes/class-wp-application-passwords-list-table.php b/src/wp-admin/includes/class-wp-application-passwords-list-table.php index d7f21f9fcc..b41190fac7 100644 --- a/src/wp-admin/includes/class-wp-application-passwords-list-table.php +++ b/src/wp-admin/includes/class-wp-application-passwords-list-table.php @@ -104,9 +104,20 @@ class WP_Application_Passwords_List_Table extends WP_List_Table { * Handles the revoke column output. * * @since 5.6.0 + * + * @param array $item The current application password item. */ - public function column_revoke() { - submit_button( __( 'Revoke' ), 'delete', 'revoke-application-password', false ); + public function column_revoke( $item ) { + submit_button( + __( 'Revoke' ), + 'delete', + 'revoke-application-password-' . $item['uuid'], + false, + array( + /* translators: %s: the application password's given name. */ + 'title' => sprintf( __( 'Revoke "%s"' ), $item['name'] ), + ) + ); } /** @@ -220,7 +231,12 @@ class WP_Application_Passwords_List_Table extends WP_List_Table { echo "{{ data.last_ip || '—' }}"; break; case 'revoke': - echo $this->column_revoke(); + printf( + '', + esc_attr( __( 'Revoke' ) ), + /* translators: %s: the application password's given name. */ + esc_attr( sprintf( __( 'Revoke "%s"' ), '{{ data.name }}' ) ) + ); break; default: /** diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 6f03001f8a..ed646bfd6c 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -739,9 +739,11 @@ endif; } } ?> -
- - +
+
+ + +
- +
@@ -856,19 +858,19 @@ endif;