Index: wp-includes/css/media-views.css
===================================================================
--- wp-includes/css/media-views.css	(revision 22918)
+++ wp-includes/css/media-views.css	(working copy)
@@ -372,26 +372,27 @@
 	user-select: none;
 }
 
-.media-menu li {
+.media-menu .media-menu-item {
+	display: block;
 	position: relative;
 	padding: 4px 20px;
 	margin: 0;
 	line-height: 18px;
 	font-size: 14px;
-	color: #21759B;
 	text-shadow: 0 1px 0 #fff;
+	text-decoration: none;
 }
 
-.media-menu-item {
-	cursor: pointer;
-}
-
-.media-menu li:hover {
+.media-menu .media-menu-item:hover,
+.media-menu .media-menu-item:focus {
+	color: #21759B;
+	background: #f1f1f1;
 	background: rgba( 0, 0, 0, 0.04 );
+	outline: none;
 }
 
-.media-menu .active,
-.media-menu .active:hover {
+.media-menu .media-menu-item.active,
+.media-menu .media-menu-item.active:hover {
 	color: #333;
 	font-weight: bold;
 }
@@ -523,6 +524,10 @@
 	cursor: pointer;
 }
 
+.attachment-preview:focus {
+	outline: thin dotted;
+}
+
 .attachment .icon {
 	margin: 0 auto;
 	overflow: hidden;
@@ -1354,7 +1359,7 @@
 		width: 119px;
 	}
 
-	.media-menu li {
+	.media-menu .media-menu-item {
 		padding: 4px 10px;
 	}
 
Index: wp-includes/js/media-editor.js
===================================================================
--- wp-includes/js/media-editor.js	(revision 22918)
+++ wp-includes/js/media-editor.js	(working copy)
@@ -535,7 +535,10 @@
 				workflow.open();
 			else
 				workflow = wp.media.editor.add( id );
-
+			
+			// Add focus to modal
+			$( '.media-menu .active' ).focus();
+			
 			return workflow;
 		}
 	};
Index: wp-includes/js/media-views.js
===================================================================
--- wp-includes/js/media-views.js	(revision 22918)
+++ wp-includes/js/media-views.js	(working copy)
@@ -1648,8 +1648,13 @@
 		tagName:  'div',
 		template: media.template('media-modal'),
 
+		attributes: {
+			tabindex: 0
+		},
+
 		events: {
-			'click .media-modal-backdrop, .media-modal-close' : 'closeHandler'
+			'click .media-modal-backdrop, .media-modal-close': 'closeHandler',
+			'keydown': 'keydown'
 		},
 
 		initialize: function() {
@@ -1659,6 +1664,8 @@
 				container: document.body,
 				title:     ''
 			});
+
+			_.bindAll( this, '_captureBodyKeydown' );
 		},
 
 		render: function() {
@@ -1691,12 +1698,14 @@
 		},
 
 		open: function() {
+			document.addEventListener( 'keydown', this._captureBodyKeydown, true );
 			this.$el.show();
 			this.trigger('open');
 			return this;
 		},
 
 		close: function() {
+			document.removeEventListener( 'keydown', this._captureBodyKeydown, true );
 			this.$el.hide();
 			this.trigger('close');
 			return this;
@@ -1715,6 +1724,52 @@
 			// Set and render the content.
 			this.options.$content = ( $content instanceof Backbone.View ) ? $content.$el : $content;
 			return this.render();
+		},
+
+
+		// Thanks to jQuery UI dialog, which also limits tabbing to a modal
+		// window. The `:tabbable` expression, `$.ui.keyCode` object, and
+		// the overloaded `$.fn.focus( delay )` signature are all from the
+		// jQuery UI core.
+		keydown: function( event ) {
+			var tabbables, first, last;
+
+			// Close the modal when escape is pressed.
+			if ( $.ui.keyCode.ESCAPE === event.which ) {
+				event.preventDefault();
+				this.close();
+				return;
+			}
+
+			// Prevent tabbing outside of the modal.
+			if ( event.keyCode !== $.ui.keyCode.TAB )
+				return;
+
+			tabbables = this.$(':tabbable');
+			first     = tabbables.filter(':first');
+			last      = tabbables.filter(':last');
+
+			// If we attempt to tab past the last tabbable element, skip
+			// straight to the first tabbable element (and vice versa).
+			if ( event.target === last[0] && ! event.shiftKey ) {
+				first.focus( 1 );
+				return false;
+			} else if ( event.target === first[0] && event.shiftKey ) {
+				last.focus( 1 );
+				return false;
+			}
+		},
+
+		// If the focus somehow escapes the modal, restores focus to the
+		// first focusable element inside the modal.
+		//
+		// Captures the document's keydown event when the modal is open.
+		_captureBodyKeydown: function() {
+			if ( event.keyCode !== $.ui.keyCode.TAB )
+				return;
+
+			if ( ! $.contains( this.el, document.activeElement ) )
+				this.$(':tabbable').first().focus( 1 );
 		}
 	});
 
@@ -2347,7 +2402,6 @@
 	 * wp.media.view.Menu
 	 */
 	media.view.Menu = media.view.PriorityList.extend({
-		tagName:   'ul',
 		className: 'media-menu',
 
 		toView: function( options, state ) {
@@ -2372,16 +2426,22 @@
 	});
 
 	media.view.MenuItem = media.View.extend({
-		tagName:   'li',
+		tagName:   'a',
 		className: 'media-menu-item',
 
+		attributes: {
+			href: '#'
+		},
+
 		events: {
 			'click': 'click'
 		},
 
-		click: function() {
+		click: function( event ) {
 			var options = this.options;
 
+			event.preventDefault();
+
 			if ( options.click )
 				options.click.call( this );
 			else if ( options.state )
@@ -2417,6 +2477,7 @@
 
 		events: {
 			'click .attachment-preview':      'toggleSelection',
+			'keydown .attachment-preview':    'keydown',
 			'change [data-setting]':          'updateSetting',
 			'change [data-setting] input':    'updateSetting',
 			'change [data-setting] select':   'updateSetting',
@@ -2493,7 +2554,12 @@
 				this.$bar.width( this.model.get('percent') + '%' );
 		},
 
-		toggleSelection: function( event ) {
+		keydown: function( event ) {
+			if ( $.ui.keyCode.ENTER === event.keyCode )
+				this.toggleSelection();
+		},
+
+		toggleSelection: function() {
 			var selection = this.options.selection,
 				model = this.model;
 
Index: wp-includes/media.php
===================================================================
--- wp-includes/media.php	(revision 22918)
+++ wp-includes/media.php	(working copy)
@@ -1603,7 +1603,7 @@
 	</script>
 
 	<script type="text/html" id="tmpl-attachment">
-		<div class="attachment-preview type-{{ data.type }} subtype-{{ data.subtype }} {{ data.orientation }}">
+		<div class="attachment-preview type-{{ data.type }} subtype-{{ data.subtype }} {{ data.orientation }}" tabindex="0">
 			<# if ( data.uploading ) { #>
 				<div class="media-progress-bar"><div></div></div>
 			<# } else if ( 'image' === data.type ) { #>
@@ -1624,7 +1624,7 @@
 			<# } #>
 
 			<# if ( data.buttons.check ) { #>
-				<a class="check" href="#"><span>&#10003;</span><span class="dash">&ndash;</span></a>
+				<a class="check" href="#" tabindex="-1"><span>&#10003;</span><span class="dash">&ndash;</span></a>
 			<# } #>
 		</div>
 		<# if ( data.describe ) { #>
