Index: src/wp-admin/css/forms.css
===================================================================
--- src/wp-admin/css/forms.css	(revision 31866)
+++ src/wp-admin/css/forms.css	(working copy)
@@ -864,11 +864,58 @@
 	margin: 25px;
 }
 
-.request-filesystem-credentials-dialog-content input[type="text"],
-.request-filesystem-credentials-dialog-content input[type="password"] {
-	width: 85%;
+.request-filesystem-credentials-form input[type="text"],
+.request-filesystem-credentials-form input[type="password"] {
+	display: block;
 }
 
+.request-filesystem-credentials-dialog input[type="text"],
+.request-filesystem-credentials-dialog input[type="password"] {
+	width: 100%;
+}
+
+.request-filesystem-credentials-form .field-title {
+	font-weight: 600;
+}
+
+.request-filesystem-credentials-dialog label[for="hostname"],
+.request-filesystem-credentials-dialog label[for="public_key"],
+.request-filesystem-credentials-dialog label[for="private_key"] {
+	display: block;
+	margin-bottom: 1em;
+}
+
+.request-filesystem-credentials-dialog .ftp-username,
+.request-filesystem-credentials-dialog .ftp-password {
+	float: left;
+	width: 48%;
+}
+
+.request-filesystem-credentials-dialog .ftp-password {
+	margin-left: 4%;
+}
+
+.request-filesystem-credentials-dialog .request-filesystem-credentials-action-buttons {
+	text-align: right;
+}
+
+.request-filesystem-credentials-dialog label[for="ftp"] {
+	margin-right: 10px;
+}
+
+#request-filesystem-credentials-dialog .button:not(:last-child) {
+	margin-right: 10px;
+}
+
+#request-filesystem-credentials-form .cancel-button {
+	display: none;
+}
+
+#request-filesystem-credentials-dialog .cancel-button {
+	display: inline;
+}
+
+
 /* =Media Queries
 -------------------------------------------------------------- */
 
Index: src/wp-admin/includes/file.php
===================================================================
--- src/wp-admin/includes/file.php	(revision 31866)
+++ src/wp-admin/includes/file.php	(working copy)
@@ -1112,9 +1112,9 @@
 -->
 </script>
 <form action="<?php echo esc_url( $form_post ) ?>" method="post">
-<div>
-<h3><?php _e('Connection Information') ?></h3>
-<p><?php
+<div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form">
+<h3 id="request-filesystem-credentials-title"><?php _e( 'Connection Information' ) ?></h3>
+<p id="request-filesystem-credentials-desc"><?php
 	$label_user = __('Username');
 	$label_pass = __('Password');
 	_e('To perform the requested action, WordPress needs to access your web server.');
@@ -1133,39 +1133,36 @@
 	}
 	_e('If you do not remember your credentials, you should contact your web host.');
 ?></p>
-<table class="form-table">
-<tr>
-<th scope="row"><label for="hostname"><?php _e('Hostname') ?></label></th>
-<td><input name="hostname" type="text" id="hostname" value="<?php echo esc_attr($hostname); if ( !empty($port) ) echo ":$port"; ?>"<?php disabled( defined('FTP_HOST') ); ?> size="40" /></td>
-</tr>
-
-<tr>
-<th scope="row"><label for="username"><?php echo $label_user; ?></label></th>
-<td><input name="username" type="text" id="username" value="<?php echo esc_attr($username) ?>"<?php disabled( defined('FTP_USER') ); ?> size="40" /></td>
-</tr>
-
-<tr>
-<th scope="row"><label for="password"><?php echo $label_pass; ?></label></th>
-<td><div><input name="password" type="password" id="password" value="<?php if ( defined('FTP_PASS') ) echo '*****'; ?>"<?php disabled( defined('FTP_PASS') ); ?> size="40" /></div>
-<div><em><?php if ( ! defined('FTP_PASS') ) _e( 'This password will not be stored on the server.' ); ?></em></div></td>
-</tr>
-
+<label for="hostname">
+	<span class="field-title"><?php _e( 'Hostname' ) ?></span>
+	<input name="hostname" type="text" id="hostname" aria-describedby="request-filesystem-credentials-desc" class="code" placeholder="<?php esc_attr_e( __( 'example: www.mysite.com' ) ) ?>" value="<?php echo esc_attr($hostname); if ( !empty($port) ) echo ":$port"; ?>"<?php disabled( defined('FTP_HOST') ); ?> />
+</label>
+<div class="ftp-username">
+	<label for="username">
+		<span class="field-title"><?php echo $label_user; ?></span>
+		<input name="username" type="text" id="username" value="<?php echo esc_attr($username) ?>"<?php disabled( defined('FTP_USER') ); ?> />
+	</label>
+</div>
+<div class="ftp-password">
+	<label for="password">
+		<span class="field-title"><?php echo $label_pass; ?></span>
+		<input name="password" type="password" id="password" value="<?php if ( defined('FTP_PASS') ) echo '*****'; ?>"<?php disabled( defined('FTP_PASS') ); ?> />
+		<em><?php if ( ! defined('FTP_PASS') ) _e( 'This password will not be stored on the server.' ); ?></em>
+	</label>
+</div>
 <?php if ( isset($types['ssh']) ) : ?>
-<tr id="ssh_keys" style="<?php if ( 'ssh' != $connection_type ) echo 'display:none' ?>">
-<th scope="row"><?php _e('Authentication Keys') ?>
-<div class="key-labels textright">
-<label for="public_key"><?php _e('Public Key:') ?></label ><br />
-<label for="private_key"><?php _e('Private Key:') ?></label>
-</div></th>
-<td><br /><input name="public_key" type="text" id="public_key" value="<?php echo esc_attr($public_key) ?>"<?php disabled( defined('FTP_PUBKEY') ); ?> size="40" />
-	<br /><input name="private_key" type="text" id="private_key" value="<?php echo esc_attr($private_key) ?>"<?php disabled( defined('FTP_PRIKEY') ); ?> size="40" />
-<div><?php _e('Enter the location on the server where the keys are located. If a passphrase is needed, enter that in the password field above.') ?></div></td>
-</tr>
+<h4><?php _e('Authentication Keys') ?></h4>
+<label for="public_key">
+	<span class="field-title"><?php _e('Public Key:') ?></span>
+	<input name="public_key" type="text" id="public_key" aria-describedby="auth-keys-desc" value="<?php echo esc_attr($public_key) ?>"<?php disabled( defined('FTP_PUBKEY') ); ?> />
+</label>
+<label for="private_key">
+	<span class="field-title"><?php _e('Private Key:') ?></span>
+	<input name="private_key" type="text" id="private_key" value="<?php echo esc_attr($private_key) ?>"<?php disabled( defined('FTP_PRIKEY') ); ?> />
+</label>
+<span id="auth-keys-desc"><?php _e('Enter the location on the server where the public and private keys are located. If a passphrase is needed, enter that in the password field above.') ?></span>
 <?php endif; ?>
-
-<tr>
-<th scope="row"><?php _e('Connection Type') ?></th>
-<td>
+<h4><?php _e('Connection Type') ?></h4>
 <fieldset><legend class="screen-reader-text"><span><?php _e('Connection Type') ?></span></legend>
 <?php
 	$disabled = disabled( (defined('FTP_SSL') && FTP_SSL) || (defined('FTP_SSH') && FTP_SSH), true, false );
@@ -1176,17 +1173,16 @@
 	</label>
 	<?php endforeach; ?>
 </fieldset>
-</td>
-</tr>
-</table>
-
 <?php
 foreach ( (array) $extra_fields as $field ) {
 	if ( isset( $_POST[ $field ] ) )
 		echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( wp_unslash( $_POST[ $field ] ) ) . '" />';
 }
-submit_button( __( 'Proceed' ), 'button', 'upgrade' );
 ?>
+	<p class="request-filesystem-credentials-action-buttons">
+		<button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button>
+		<?php submit_button( __( 'Proceed' ), 'button', 'upgrade', false ); ?>
+	</p>
 </div>
 </form>
 <?php
@@ -1194,7 +1190,7 @@
 }
 
 /**
- * Print the credentials modal when needed  
+ * Print the credentials modal when needed
  *
  * @since 4.2.0
  */
@@ -1210,7 +1206,7 @@
 	?>
 	<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
 		<div class="notification-dialog-background"></div>
-		<div class="notification-dialog">
+		<div class="notification-dialog" role="dialog" aria-labelledby="request-filesystem-credentials-title" tabindex="0">
 			<div class="request-filesystem-credentials-dialog-content">
 				<?php request_filesystem_credentials( site_url() ); ?>
 			<div>
Index: src/wp-admin/js/updates.js
===================================================================
--- src/wp-admin/js/updates.js	(revision 31866)
+++ src/wp-admin/js/updates.js	(working copy)
@@ -392,14 +392,65 @@
 	 *
 	 * @since 4.2.0
 	 */
-	wp.updates.requestFilesystemCredentials = function() {
+	wp.updates.requestFilesystemCredentials = function( event ) {
 		if ( wp.updates.updateDoneSuccessfully === false ) {
+			var $dialog = $( '#request-filesystem-credentials-dialog' );
+			// Get the clicked element
+			wp.updates.activeEl = $( event.target );
+
 			wp.updates.updateLock = true;
 			$( 'body' ).addClass( 'modal-open' );
-			$( '#request-filesystem-credentials-dialog' ).show();
+			$dialog.show();
+
+			// Set focus to the modal first input
+			$dialog.find( '#hostname' ).focus();
+			// Bind keydown event handler
+			$dialog.keydown( wp.updates.keydown );
 		}
 	};
 
+	/**
+	 * Close on Escape and constrain keyboard navigation inside the Credentials modal.
+	 *
+	 * @since 4.2.0
+	 */
+	wp.updates.keydown = function( event ) {
+		var id,
+			key = event.keyCode || event.charCode;
+
+		if ( 27 === key ) {
+			wp.updates.dialogClose();
+		} else if ( 9 === key ) {
+			id = event.target.id;
+			// #upgrade button must always be the last focusable element in the dialog.
+			if ( id === 'upgrade' && ! event.shiftKey ) {
+				$( '#hostname' ).focus();
+				event.preventDefault();
+			} else if ( id === 'hostname' && event.shiftKey ) {
+				$( '#upgrade' ).focus();
+				event.preventDefault();
+			}
+		}
+	};
+
+	/**
+	 * Store the active element that was clicked before the Credentials modal opens.
+	 *
+	 * @since 4.2.0
+	 *
+	 * @var jQuery object
+	 */
+	wp.updates.activeEl = null;
+
+	/**
+	 * Store the active update row.
+	 *
+	 * @since 4.2.0
+	 *
+	 * @var jQuery object
+	 */
+	wp.updates.updateRow = null;
+
 	$( document ).ready( function() {
 		/*
 		 * Check whether a user needs to submit filesystem credentials based on whether
@@ -419,8 +470,7 @@
 			wp.updates.filesystemCredentials.ssh.publicKey = $('#public_key').val();
 			wp.updates.filesystemCredentials.ssh.privateKey = $('#private_key').val();
 
-			$( '#request-filesystem-credentials-dialog' ).hide();
-			$( 'body' ).removeClass( 'modal-open' );
+			wp.updates.dialogClose();
 
 			// Unlock and invoke the queue.
 			wp.updates.updateLock = false;
@@ -429,14 +479,33 @@
 			return false;
 		});
 
+		wp.updates.dialogClose = function() {
+			var slug;
+
+			$( '#request-filesystem-credentials-dialog' ).hide();
+			$( 'body' ).removeClass( 'modal-open' );
+			// Plugin updates: set focus back to the Select checkbox.
+			if ( wp.updates.updateRow ) {
+				slug = wp.updates.updateRow.data( 'slug' );
+				$( '#' + slug ).find( '.check-column input' ).focus();
+			// Plugin install: set focus back to the Install button.
+			} else {
+				wp.updates.activeEl.focus();
+			}
+		};
+
+		$( '#request-filesystem-credentials-dialog [data-js-action="close"], #request-filesystem-credentials-dialog' ).on( 'click', function() {
+			wp.updates.dialogClose();
+		});
+
 		// Click handler for plugin updates in List Table view.
 		$( '.plugin-update-tr .update-link' ).on( 'click', function( e ) {
 			e.preventDefault();
 			if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.updateLock ) {
-				wp.updates.requestFilesystemCredentials();
+				wp.updates.requestFilesystemCredentials( e );
 			}
-			var $row = $( e.target ).parents( '.plugin-update-tr' );
-			wp.updates.updatePlugin( $row.data( 'plugin' ), $row.data( 'slug' ) );
+			wp.updates.updateRow = $( e.target ).parents( '.plugin-update-tr' );
+			wp.updates.updatePlugin( wp.updates.updateRow.data( 'plugin' ), wp.updates.updateRow.data( 'slug' ) );
 		} );
 
 		$( '#bulk-action-form' ).on( 'submit', function( e ) {
@@ -466,7 +535,7 @@
 		$( '.plugin-card .install-now' ).on( 'click', function( e ) {
 			e.preventDefault();
 			if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.updateLock ) {
-				wp.updates.requestFilesystemCredentials();
+				wp.updates.requestFilesystemCredentials( e );
 			}
 			var $button = $( e.target );
 			if ( $button.hasClass( 'button-disabled' ) ) {
