Index: src/js/media/views/focus-manager.js
===================================================================
--- src/js/media/views/focus-manager.js	(revision 45665)
+++ src/js/media/views/focus-manager.js	(working copy)
@@ -1,3 +1,5 @@
+var $ = jQuery;
+
 /**
  * wp.media.view.FocusManager
  *
@@ -11,10 +13,43 @@
 var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.prototype */{
 
 	events: {
-		'keydown': 'constrainTabbing'
+		'keydown': 'focusManagementMode'
 	},
 
 	/**
+	 * Initializes the Focus Manager.
+	 *
+	 * @param {object} options The Focus Manager options.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @return {void}
+	 */
+	initialize: function( options ) {
+		this.mode                    = options.mode || 'constrainTabbing';
+		this.tabsAutomaticActivation = options.tabsAutomaticActivation || false;
+	},
+
+ 	/**
+	 * Determines which focus management mode to use.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param {object} event jQuery event object.
+	 *
+	 * @returns {void}
+	 */
+	focusManagementMode: function( event ) {
+		if ( this.mode === 'constrainTabbing' ) {
+			this.constrainTabbing( event );
+		}
+
+		if ( this.mode === 'tabsNavigation' ) {
+			this.tabsNavigation( event );
+		}
+	},
+
+	/**
 	 * Gets all the tabbable elements.
 	 *
 	 * @since 5.3.0
@@ -164,7 +199,158 @@
 	 *
 	 * @since 5.3.0
 	 */
-	ariaHiddenElements: []
+	ariaHiddenElements: [],
+
+	/**
+	 * Holds the jQuery collection of ARIA tabs.
+	 *
+	 * @since 5.3.0
+	 */
+	tabs: $(),
+
+	/**
+	 * Sets up tabs in an ARIA tabbed interface.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param {object} event jQuery event object.
+	 *
+	 * @returns {void}
+	 */
+	setupAriaTabs: function() {
+		this.tabs = this.$( '[role="tab"]' );
+
+		// Set up initial attributes.
+		this.tabs.attr( {
+			'aria-selected': 'false',
+			tabIndex: '-1'
+		} );
+
+		// Set up attributes on the initially active tab.
+		this.tabs.filter( '.active' )
+			.removeAttr( 'tabindex' )
+			.attr( 'aria-selected', 'true' );
+	},
+
+	/**
+	 * Enables arrows navigation within the ARIA tabbed interface.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param {object} event jQuery event object.
+	 *
+	 * @returns {void}
+	 */
+	tabsNavigation: function( event ) {
+		var orientation = 'horizontal',
+			keys = [ 32, 35, 36, 37, 38, 39, 40 ];
+
+		// Return if not Spacebar, End, Home, or Arrow keys.
+		if ( keys.indexOf( event.which ) === -1 ) {
+			return;
+		}
+
+		// Determine navigation direction.
+		if ( this.$el.attr( 'aria-orientation' ) === 'vertical' ) {
+			orientation = 'vertical';
+		}
+
+		// Make Up and Down arrow keys do nothing with horizontal tabs.
+		if ( orientation === 'horizontal' && [ 38, 40 ].indexOf( event.which ) !== -1 ) {
+			return;
+		}
+
+		// Make Left and Right arrow keys do nothing with vertical tabs.
+		if ( orientation === 'vertical' && [ 37, 39 ].indexOf( event.which ) !== -1 ) {
+			return;
+		}
+
+		this.switchTabs( event, this.tabs );
+	},
+
+	/**
+	 * Switches tabs in the ARIA tabbed interface.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param {object} event jQuery event object.
+	 *
+	 * @returns {void}
+	 */
+	switchTabs: function( event ) {
+		var key   = event.which,
+			index = this.tabs.index( jQuery( event.target ) ),
+			newIndex;
+
+		switch ( key ) {
+			// Space bar: Activate current targeted tab.
+			case 32: {
+				this.activateTab( this.tabs[ index ] );
+				break;
+			}
+			// End key: Activate last tab.
+			case 35: {
+				event.preventDefault();
+				this.activateTab( this.tabs[ this.tabs.length - 1 ] );
+				break;
+			}
+			// Home key: Activate first tab.
+			case 36: {
+				event.preventDefault();
+				this.activateTab( this.tabs[ 0 ] );
+				break;
+			}
+			// Left and up keys: Activate previous tab.
+			case 37:
+			case 38: {
+				event.preventDefault();
+				newIndex = ( index - 1 ) < 0 ? this.tabs.length - 1 : index - 1;
+				this.activateTab( this.tabs[ newIndex ] );
+				break;
+			}
+			// Right and down keys: Activate next tab.
+			case 39:
+			case 40: {
+				event.preventDefault();
+				newIndex = ( index + 1 ) === this.tabs.length ? 0 : index + 1;
+				this.activateTab( this.tabs[ newIndex ] );
+				break;
+			}
+		}
+	},
+
+	/**
+	 * Sets a single tab to be focusable and semantically selected.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param {object} tab  The tab DOM element.
+	 *
+	 * @returns {void}
+	 */
+	activateTab: function( tab ) {
+		if ( ! tab ) {
+			return;
+		}
+
+		// The tab is a DOM element: no need for jQuery methods.
+		tab.focus();
+
+		// Handle automatic activation.
+		if ( this.tabsAutomaticActivation ) {
+			tab.removeAttribute( 'tabindex' );
+			tab.setAttribute( 'aria-selected', 'true' );
+			tab.click();
+
+			return;
+		}
+
+		// Handle manual activation.
+		$( tab ).on( 'click', function() {
+			tab.removeAttribute( 'tabindex' );
+			tab.setAttribute( 'aria-selected', 'true' );
+		} );
+ 	}
 });
 
 module.exports = FocusManager;
Index: src/js/media/views/frame/post.js
===================================================================
--- src/js/media/views/frame/post.js	(revision 45665)
+++ src/js/media/views/frame/post.js	(working copy)
@@ -257,8 +257,11 @@
 	mainMenu: function( view ) {
 		view.set({
 			'library-separator': new wp.media.View({
-				className: 'separator',
-				priority: 100
+				className:  'separator',
+				priority:   100,
+				attributes: {
+					role: 'presentation'
+				}
 			})
 		});
 	},
Index: src/js/media/views/media-frame.js
===================================================================
--- src/js/media/views/media-frame.js	(revision 45665)
+++ src/js/media/views/media-frame.js	(working copy)
@@ -80,8 +80,40 @@
 
 		// Bind default menu.
 		this.on( 'menu:create:default', this.createMenu, this );
+
+		this.on( 'content:render', this.updateContentTabPanelAriaLabelledBy, this );
 	},
+
 	/**
+	 * Updates the aria-labelledby to be used on an ARIA tab pabel.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @returns {string} The aria-labelledby value to use.
+	 */
+	updateContentTabPanelAriaLabelledBy: function() {
+		var stateId = this.state().get( 'id' ),
+			contentTabPanelAriaLabelledBy = 'menu-item-' + stateId;
+
+		this.$el.find( '.media-frame-tab-panel' ).attr( 'aria-labelledby', contentTabPanelAriaLabelledBy );
+
+		return contentTabPanelAriaLabelledBy;
+	},
+
+	/**
+	 * Prepares view for display.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @returns {void}
+	 */
+	prepare: function() {
+		return _.defaults({
+			tabPanelAriaLabelledBy: this.updateContentTabPanelAriaLabelledBy()
+		}, this.options );
+	},
+
+	/**
 	 * @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
 	 */
 	render: function() {
@@ -110,7 +142,12 @@
 	 */
 	createMenu: function( menu ) {
 		menu.view = new wp.media.view.Menu({
-			controller: this
+			controller: this,
+
+			attributes: {
+				role:               'tablist',
+				'aria-orientation': 'vertical'
+			}
 		});
 	},
 
Index: src/js/media/views/menu-item.js
===================================================================
--- src/js/media/views/menu-item.js	(revision 45665)
+++ src/js/media/views/menu-item.js	(working copy)
@@ -11,26 +11,24 @@
  * @augments Backbone.View
  */
 MenuItem = wp.media.View.extend(/** @lends wp.media.view.MenuItem.prototype */{
-	tagName:   'a',
+	tagName:   'button',
 	className: 'media-menu-item',
 
 	attributes: {
-		href: '#'
+		type: 'button',
+		role: 'tab'
 	},
 
 	events: {
 		'click': '_click'
 	},
+
 	/**
-	 * @param {Object} event
+	 * Allows to override the click event.
 	 */
-	_click: function( event ) {
+	_click: function() {
 		var clickOverride = this.options.click;
 
-		if ( event ) {
-			event.preventDefault();
-		}
-
 		if ( clickOverride ) {
 			clickOverride.call( this );
 		} else {
@@ -43,9 +41,11 @@
 
 		if ( state ) {
 			this.controller.setState( state );
+			// Toggle the menu visibility in the responsive view.
 			this.views.parent.$el.removeClass( 'visible' ); // TODO: or hide on any click, see below
 		}
 	},
+
 	/**
 	 * @returns {wp.media.view.MenuItem} returns itself to allow chaining
 	 */
@@ -58,6 +58,8 @@
 			this.$el.html( options.html );
 		}
 
+		this.$el.attr( 'id', 'menu-item-' + this.options.state );
+
 		return this;
 	}
 });
Index: src/js/media/views/menu.js
===================================================================
--- src/js/media/views/menu.js	(revision 45665)
+++ src/js/media/views/menu.js	(working copy)
@@ -20,15 +20,27 @@
 	ItemView:  MenuItem,
 	region:    'menu',
 
-	/* TODO: alternatively hide on any click anywhere
-	events: {
-		'click': 'click'
+	attributes: {
+		role:               'tablist',
+		'aria-orientation': 'horizontal'
 	},
 
-	click: function() {
-		this.$el.removeClass( 'visible' );
+	initialize: function() {
+		this._views = {};
+
+		this.set( _.extend( {}, this._views, this.options.views ), { silent: true });
+		delete this.options.views;
+
+		if ( ! this.options.silent ) {
+			this.render();
+		}
+
+		// Initialize the Focus Manager.
+		this.focusManager = new wp.media.view.FocusManager( {
+			el:   this.el,
+			mode: 'tabsNavigation'
+		} );
 	},
-	*/
 
 	/**
 	 * @param {Object} options
@@ -47,6 +59,9 @@
 		 */
 		PriorityList.prototype.ready.apply( this, arguments );
 		this.visibility();
+
+		// Set up aria tabs initial attributes.
+		this.focusManager.setupAriaTabs();
 	},
 
 	set: function() {
@@ -87,6 +102,9 @@
 
 		this.deselect();
 		view.$el.addClass('active');
+
+		// Set up again the aria tabs initial attributes after the menu updates.
+		this.focusManager.setupAriaTabs();
 	},
 
 	deselect: function() {
Index: src/js/media/views/router.js
===================================================================
--- src/js/media/views/router.js	(revision 45665)
+++ src/js/media/views/router.js	(working copy)
@@ -20,6 +20,11 @@
 	ItemView:  wp.media.view.RouterItem,
 	region:    'router',
 
+	attributes: {
+		role:               'tablist',
+		'aria-orientation': 'horizontal'
+	},
+
 	initialize: function() {
 		this.controller.on( 'content:render', this.update, this );
 		// Call 'initialize' directly on the parent class.
Index: src/wp-includes/css/media-views.css
===================================================================
--- src/wp-includes/css/media-views.css	(revision 45665)
+++ src/wp-includes/css/media-views.css	(working copy)
@@ -553,23 +553,29 @@
 	user-select: none;
 }
 
-.media-menu > a {
+.media-menu .media-menu-item {
 	display: block;
+	box-sizing: border-box;
+	width: 100%;
 	position: relative;
+	border: 0;
+	margin: 0;
 	padding: 8px 20px;
-	margin: 0;
+	font-size: 14px;
 	line-height: 1.28571428;
-	font-size: 14px;
+	background: transparent;
 	color: #0073aa;
+	text-align: left;
 	text-decoration: none;
+	cursor: pointer;
 }
 
-.media-menu > a:hover {
-	color: #0073aa;
+.media-menu .media-menu-item:hover {
 	background: rgba(0, 0, 0, 0.04);
 }
 
-.media-menu > a:active {
+.media-menu .media-menu-item:active {
+	color: #0073aa;
 	outline: none;
 }
 
@@ -579,6 +585,15 @@
 	font-weight: 600;
 }
 
+.media-menu .media-menu-item:focus {
+	box-shadow:
+		0 0 0 1px #5b9dd9,
+		0 0 2px 1px rgba(30, 140, 190, 0.8);
+	color: #124964;
+	/* Only visible in Windows High Contrast mode */
+	outline: 1px solid transparent;
+}
+
 .media-menu .separator {
 	height: 0;
 	margin: 12px 20px;
@@ -594,42 +609,48 @@
 	padding: 0 6px;
 	margin: 0;
 	clear: both;
-	-webkit-user-select: none;
-	-moz-user-select: none;
-	-ms-user-select: none;
-	user-select: none;
 }
 
-.media-router a {
-	transition: none;
-}
-
-.media-router > a {
+.media-router .media-menu-item {
 	position: relative;
 	float: left;
+	border: 0;
+	margin: 0;
 	padding: 8px 10px 9px;
-	margin: 0;
 	height: 18px;
 	line-height: 1.28571428;
 	font-size: 14px;
 	text-decoration: none;
+	background: transparent;
+	cursor: pointer;
+	transition: none;
 }
 
-.media-router > a:last-child {
+.media-router .media-menu-item:last-child {
 	border-right: 0;
 }
 
-.media-router > a:active {
-	outline: none;
+.media-router .media-menu-item:hover,
+.media-router .media-menu-item:active {
+	color: #0073aa;
 }
 
 .media-router .active,
 .media-router .active:hover {
-	color: #32373c;
+	color: #23282d;
 }
 
+.media-router .media-menu-item:focus {
+	box-shadow:
+		0 0 0 1px #5b9dd9,
+		0 0 2px 1px rgba(30, 140, 190, 0.8);
+	color: #124964;
+	/* Only visible in Windows High Contrast mode */
+	outline: 1px solid transparent;
+}
+
 .media-router .active,
-.media-router > a.active:last-child {
+.media-router .media-menu-item.active:last-child {
 	margin: -1px -1px 0;
 	background: #fff;
 	border: 1px solid #ddd;
Index: src/wp-includes/media-template.php
===================================================================
--- src/wp-includes/media-template.php	(revision 45665)
+++ src/wp-includes/media-template.php	(working copy)
@@ -179,8 +179,10 @@
 	<script type="text/html" id="tmpl-media-frame">
 		<div class="media-frame-title" id="media-frame-title"></div>
 		<div class="media-frame-menu"></div>
-		<div class="media-frame-router"></div>
-		<div class="media-frame-content"></div>
+		<div class="media-frame-tab-panel" role="tabpanel" aria-labelledby="{{ data.tabPanelAriaLabelledBy }}" tabindex="0">
+			<div class="media-frame-router"></div>
+			<div class="media-frame-content"></div>
+		</div>
 		<div class="media-frame-toolbar"></div>
 		<div class="media-frame-uploader"></div>
 	</script>
