Accessibility: Media: Use the ARIA tabs pattern for the media modal menus.
The ARIA tabs pattern improves interaction for keyboard and assistive technologies users. It gives the menu items proper roles, and `aria-selected` allows users of assistive technologies to know which tab is currently selected. Props audrasjb, afercia, joedolson, karmatosed, melchoyce. See #47149. Built from https://develop.svn.wordpress.org/trunk@46363 git-svn-id: http://core.svn.wordpress.org/trunk@46162 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
e534fdf5aa
commit
63e199abc7
|
@ -580,23 +580,29 @@
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.media-menu > a {
|
||||
.media-menu .media-menu-item {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 8px 20px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
line-height: 1.28571428;
|
||||
padding: 8px 20px;
|
||||
font-size: 14px;
|
||||
line-height: 1.28571428;
|
||||
background: transparent;
|
||||
color: #0073aa;
|
||||
text-align: right;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -606,6 +612,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;
|
||||
|
@ -621,42 +636,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: right;
|
||||
padding: 8px 10px 9px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 8px 10px 9px;
|
||||
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-left: 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;
|
||||
|
@ -752,15 +773,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.media-frame.hide-router .media-frame-title {
|
||||
border-bottom: 1px solid #ddd;
|
||||
box-shadow: 0 4px 4px -4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.media-frame-title .dashicons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-frame-title h1 {
|
||||
padding: 0 16px;
|
||||
font-size: 22px;
|
||||
|
@ -768,6 +780,10 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.wp-core-ui .button.media-frame-menu-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-frame-title .suggested-dimensions {
|
||||
font-size: 14px;
|
||||
float: left;
|
||||
|
@ -2251,27 +2267,60 @@
|
|||
* Responsive layout
|
||||
*/
|
||||
@media only screen and (max-width: 900px) {
|
||||
.media-modal .media-frame-title {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.media-modal .media-frame-title h1 {
|
||||
line-height: 2.22222222;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.media-modal-close {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
/* Drop-down menu */
|
||||
.media-frame:not(.hide-menu) .media-frame-title,
|
||||
.media-frame .media-frame-title {
|
||||
position: static;
|
||||
padding: 0 44px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-router,
|
||||
.media-frame:not(.hide-menu) .media-frame-content,
|
||||
.media-frame:not(.hide-menu) .media-frame-toolbar {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-router {
|
||||
/* 40 title + (40 - 6) menu toggle button + 6 spacing */
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-content {
|
||||
/* 80 + room for the tabs */
|
||||
top: 114px;
|
||||
}
|
||||
|
||||
.media-frame.hide-router .media-frame-content {
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-menu {
|
||||
position: static;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
display: none;
|
||||
width: auto;
|
||||
max-width: 80%;
|
||||
overflow: auto;
|
||||
z-index: 2000;
|
||||
top: 50px;
|
||||
right: -300px;
|
||||
top: 75px;
|
||||
right: 0;
|
||||
left: auto;
|
||||
bottom: auto;
|
||||
padding: 5px 0;
|
||||
|
@ -2279,7 +2328,7 @@
|
|||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu.visible {
|
||||
right: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu > a {
|
||||
|
@ -2287,29 +2336,32 @@
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu > a.active {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu .separator {
|
||||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title {
|
||||
right: 0;
|
||||
.wp-core-ui .media-frame:not(.hide-menu) .button.media-frame-menu-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: top;
|
||||
min-height: 40px;
|
||||
margin: -6px 6px 0;
|
||||
padding: 0 12px 0 2px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title .dashicons {
|
||||
display: inline-block;
|
||||
line-height: 2.5;
|
||||
.wp-core-ui .button.media-frame-menu-toggle:hover,
|
||||
.wp-core-ui .button.media-frame-menu-toggle:active {
|
||||
background: transparent;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title h1 {
|
||||
color: #0073aa;
|
||||
line-height: 3;
|
||||
font-size: 18px;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
.wp-core-ui .button.media-frame-menu-toggle:focus {
|
||||
/* Only visible in Windows High Contrast mode */
|
||||
outline: 1px solid transparent;
|
||||
}
|
||||
/* End drop-down menu */
|
||||
|
||||
|
@ -2561,31 +2613,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* Landscape specific header override */
|
||||
@media screen and (max-height: 400px) {
|
||||
.media-menu,
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
top: 44px;
|
||||
}
|
||||
|
||||
.media-frame-router {
|
||||
top: 44px;
|
||||
}
|
||||
|
||||
.media-frame-content {
|
||||
top: 78px;
|
||||
}
|
||||
|
||||
.attachments-browser .attachments {
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
/* Prevent unnecessary scrolling on title input */
|
||||
.embed-link-settings {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 901px) and (max-height: 400px) {
|
||||
.media-menu,
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
|
@ -2595,38 +2622,10 @@
|
|||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.media-modal-close {
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
.media-modal .media-frame-title {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.wp-core-ui.wp-customizer .media-button {
|
||||
margin-top: 13px;
|
||||
}
|
||||
|
||||
.media-modal .media-frame-title h1,
|
||||
.media-frame:not(.hide-menu) .media-frame-title h1 {
|
||||
font-size: 18px;
|
||||
line-height: 2.22222222;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title .dashicons {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.media-frame-router,
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
top: 40px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.media-frame-content {
|
||||
top: 74px;
|
||||
}
|
||||
|
||||
.media-frame.hide-router .media-frame-content {
|
||||
top: 40px;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -580,23 +580,29 @@
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.media-menu > a {
|
||||
.media-menu .media-menu-item {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 8px 20px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
line-height: 1.28571428;
|
||||
padding: 8px 20px;
|
||||
font-size: 14px;
|
||||
line-height: 1.28571428;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -606,6 +612,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;
|
||||
|
@ -621,42 +636,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;
|
||||
padding: 8px 10px 9px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 8px 10px 9px;
|
||||
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;
|
||||
|
@ -752,15 +773,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.media-frame.hide-router .media-frame-title {
|
||||
border-bottom: 1px solid #ddd;
|
||||
box-shadow: 0 4px 4px -4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.media-frame-title .dashicons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-frame-title h1 {
|
||||
padding: 0 16px;
|
||||
font-size: 22px;
|
||||
|
@ -768,6 +780,10 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.wp-core-ui .button.media-frame-menu-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-frame-title .suggested-dimensions {
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
|
@ -2251,27 +2267,60 @@
|
|||
* Responsive layout
|
||||
*/
|
||||
@media only screen and (max-width: 900px) {
|
||||
.media-modal .media-frame-title {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.media-modal .media-frame-title h1 {
|
||||
line-height: 2.22222222;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.media-modal-close {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
/* Drop-down menu */
|
||||
.media-frame:not(.hide-menu) .media-frame-title,
|
||||
.media-frame .media-frame-title {
|
||||
position: static;
|
||||
padding: 0 44px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-router,
|
||||
.media-frame:not(.hide-menu) .media-frame-content,
|
||||
.media-frame:not(.hide-menu) .media-frame-toolbar {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-router {
|
||||
/* 40 title + (40 - 6) menu toggle button + 6 spacing */
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-content {
|
||||
/* 80 + room for the tabs */
|
||||
top: 114px;
|
||||
}
|
||||
|
||||
.media-frame.hide-router .media-frame-content {
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-menu {
|
||||
position: static;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
display: none;
|
||||
width: auto;
|
||||
max-width: 80%;
|
||||
overflow: auto;
|
||||
z-index: 2000;
|
||||
top: 50px;
|
||||
left: -300px;
|
||||
top: 75px;
|
||||
left: 0;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
padding: 5px 0;
|
||||
|
@ -2279,7 +2328,7 @@
|
|||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu.visible {
|
||||
left: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu > a {
|
||||
|
@ -2287,29 +2336,32 @@
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu > a.active {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-menu .separator {
|
||||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title {
|
||||
left: 0;
|
||||
.wp-core-ui .media-frame:not(.hide-menu) .button.media-frame-menu-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: top;
|
||||
min-height: 40px;
|
||||
margin: -6px 6px 0;
|
||||
padding: 0 2px 0 12px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title .dashicons {
|
||||
display: inline-block;
|
||||
line-height: 2.5;
|
||||
.wp-core-ui .button.media-frame-menu-toggle:hover,
|
||||
.wp-core-ui .button.media-frame-menu-toggle:active {
|
||||
background: transparent;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title h1 {
|
||||
color: #0073aa;
|
||||
line-height: 3;
|
||||
font-size: 18px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
.wp-core-ui .button.media-frame-menu-toggle:focus {
|
||||
/* Only visible in Windows High Contrast mode */
|
||||
outline: 1px solid transparent;
|
||||
}
|
||||
/* End drop-down menu */
|
||||
|
||||
|
@ -2561,31 +2613,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* Landscape specific header override */
|
||||
@media screen and (max-height: 400px) {
|
||||
.media-menu,
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
top: 44px;
|
||||
}
|
||||
|
||||
.media-frame-router {
|
||||
top: 44px;
|
||||
}
|
||||
|
||||
.media-frame-content {
|
||||
top: 78px;
|
||||
}
|
||||
|
||||
.attachments-browser .attachments {
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
/* Prevent unnecessary scrolling on title input */
|
||||
.embed-link-settings {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 901px) and (max-height: 400px) {
|
||||
.media-menu,
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
|
@ -2595,38 +2622,10 @@
|
|||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.media-modal-close {
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
.media-modal .media-frame-title {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.wp-core-ui.wp-customizer .media-button {
|
||||
margin-top: 13px;
|
||||
}
|
||||
|
||||
.media-modal .media-frame-title h1,
|
||||
.media-frame:not(.hide-menu) .media-frame-title h1 {
|
||||
font-size: 18px;
|
||||
line-height: 2.22222222;
|
||||
}
|
||||
|
||||
.media-frame:not(.hide-menu) .media-frame-title .dashicons {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.media-frame-router,
|
||||
.media-frame:not(.hide-menu) .media-menu {
|
||||
top: 40px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.media-frame-content {
|
||||
top: 74px;
|
||||
}
|
||||
|
||||
.media-frame.hide-router .media-frame-content {
|
||||
top: 40px;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2924,7 +2924,7 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{
|
|||
regions: ['menu','title','content','toolbar','router'],
|
||||
|
||||
events: {
|
||||
'click div.media-frame-title h1': 'toggleMenu'
|
||||
'click .media-frame-menu-toggle': 'toggleMenu'
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2976,13 +2976,78 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{
|
|||
this.on( 'title:create:default', this.createTitle, this );
|
||||
this.title.mode('default');
|
||||
|
||||
this.on( 'title:render', function( view ) {
|
||||
view.$el.append( '<span class="dashicons dashicons-arrow-down"></span>' );
|
||||
});
|
||||
|
||||
// Bind default menu.
|
||||
this.on( 'menu:create:default', this.createMenu, this );
|
||||
|
||||
// Set the menu ARIA tab panel attributes when the modal opens.
|
||||
this.on( 'open', this.setMenuTabPanelAriaAttributes, this );
|
||||
// Set the router ARIA tab panel attributes when the modal opens.
|
||||
this.on( 'open', this.setRouterTabPanelAriaAttributes, this );
|
||||
|
||||
// Update the menu ARIA tab panel attributes when the content updates.
|
||||
this.on( 'content:render', this.setMenuTabPanelAriaAttributes, this );
|
||||
// Update the router ARIA tab panel attributes when the content updates.
|
||||
this.on( 'content:render', this.setRouterTabPanelAriaAttributes, this );
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the attributes to be used on the menu ARIA tab panel.
|
||||
*
|
||||
* @since 5.3.0
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
setMenuTabPanelAriaAttributes: function() {
|
||||
var stateId = this.state().get( 'id' ),
|
||||
tabPanelEl = this.$el.find( '.media-frame-tab-panel' ),
|
||||
ariaLabelledby;
|
||||
|
||||
tabPanelEl.removeAttr( 'role aria-labelledby tabindex' );
|
||||
|
||||
if ( this.menuView && this.menuView.isVisible ) {
|
||||
ariaLabelledby = 'menu-item-' + stateId;
|
||||
|
||||
// Set the tab panel attributes only if the tabs are visible.
|
||||
tabPanelEl
|
||||
.attr( {
|
||||
role: 'tabpanel',
|
||||
'aria-labelledby': ariaLabelledby,
|
||||
tabIndex: '0'
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the attributes to be used on the router ARIA tab panel.
|
||||
*
|
||||
* @since 5.3.0
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
setRouterTabPanelAriaAttributes: function() {
|
||||
var tabPanelEl = this.$el.find( '.media-frame-content' ),
|
||||
ariaLabelledby;
|
||||
|
||||
tabPanelEl.removeAttr( 'role aria-labelledby tabindex' );
|
||||
|
||||
// On the Embed view the router menu is hidden.
|
||||
if ( 'embed' === this.content._mode ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the tab panel attributes only if the tabs are visible.
|
||||
if ( this.routerView && this.routerView.isVisible && this.content._mode ) {
|
||||
ariaLabelledby = 'menu-item-' + this.content._mode;
|
||||
|
||||
tabPanelEl
|
||||
.attr( {
|
||||
role: 'tabpanel',
|
||||
'aria-labelledby': ariaLabelledby,
|
||||
tabIndex: '0'
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
|
||||
*/
|
||||
|
@ -3012,12 +3077,22 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{
|
|||
*/
|
||||
createMenu: function( menu ) {
|
||||
menu.view = new wp.media.view.Menu({
|
||||
controller: this
|
||||
controller: this,
|
||||
|
||||
attributes: {
|
||||
role: 'tablist',
|
||||
'aria-orientation': 'vertical'
|
||||
}
|
||||
});
|
||||
|
||||
this.menuView = menu.view;
|
||||
},
|
||||
|
||||
toggleMenu: function() {
|
||||
this.$el.find( '.media-menu' ).toggleClass( 'visible' );
|
||||
toggleMenu: function( event ) {
|
||||
var menu = this.$el.find( '.media-menu' );
|
||||
|
||||
menu.toggleClass( 'visible' );
|
||||
$( event.target ).attr( 'aria-expanded', menu.hasClass( 'visible' ) );
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -3035,8 +3110,15 @@ MediaFrame = Frame.extend(/** @lends wp.media.view.MediaFrame.prototype */{
|
|||
*/
|
||||
createRouter: function( router ) {
|
||||
router.view = new wp.media.view.Router({
|
||||
controller: this
|
||||
controller: this,
|
||||
|
||||
attributes: {
|
||||
role: 'tablist',
|
||||
'aria-orientation': 'horizontal'
|
||||
}
|
||||
});
|
||||
|
||||
this.routerView = router.view;
|
||||
},
|
||||
/**
|
||||
* @param {Object} options
|
||||
|
@ -3620,8 +3702,11 @@ Post = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{
|
|||
mainMenu: function( view ) {
|
||||
view.set({
|
||||
'library-separator': new wp.media.View({
|
||||
className: 'separator',
|
||||
priority: 100
|
||||
className: 'separator',
|
||||
priority: 100,
|
||||
attributes: {
|
||||
role: 'presentation'
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
@ -4520,6 +4605,8 @@ module.exports = Modal;
|
|||
/* 56 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var $ = jQuery;
|
||||
|
||||
/**
|
||||
* wp.media.view.FocusManager
|
||||
*
|
||||
|
@ -4533,7 +4620,40 @@ module.exports = Modal;
|
|||
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 );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -4589,8 +4709,10 @@ var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.pr
|
|||
},
|
||||
|
||||
/**
|
||||
* Hides from assistive technologies all the body children except the
|
||||
* provided element and other elements that should not be hidden.
|
||||
* Hides from assistive technologies all the body children.
|
||||
*
|
||||
* Sets an `aria-hidden="true"` attribute on all the body children except
|
||||
* the provided element and other elements that should not be hidden.
|
||||
*
|
||||
* The reason why we use `aria-hidden` is that `aria-modal="true"` is buggy
|
||||
* in Safari 11.1 and support is spotty in other browsers. Also, `aria-modal="true"`
|
||||
|
@ -4633,7 +4755,9 @@ var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.pr
|
|||
},
|
||||
|
||||
/**
|
||||
* Makes visible again to assistive technologies all body children
|
||||
* Unhides from assistive technologies all the body children.
|
||||
*
|
||||
* Makes visible again to assistive technologies all the body children
|
||||
* previously hidden and stored in this.ariaHiddenElements.
|
||||
*
|
||||
* @since 5.2.3
|
||||
|
@ -4687,7 +4811,158 @@ var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.pr
|
|||
*
|
||||
* @since 5.2.3
|
||||
*/
|
||||
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( $( 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;
|
||||
|
@ -5903,25 +6178,23 @@ var MenuItem;
|
|||
* @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
|
||||
*/
|
||||
_click: function( event ) {
|
||||
var clickOverride = this.options.click;
|
||||
|
||||
if ( event ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
/**
|
||||
* Allows to override the click event.
|
||||
*/
|
||||
_click: function() {
|
||||
var clickOverride = this.options.click;
|
||||
|
||||
if ( clickOverride ) {
|
||||
clickOverride.call( this );
|
||||
|
@ -5935,14 +6208,17 @@ MenuItem = wp.media.View.extend(/** @lends wp.media.view.MenuItem.prototype */{
|
|||
|
||||
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
|
||||
*/
|
||||
render: function() {
|
||||
var options = this.options;
|
||||
var options = this.options,
|
||||
menuProperty = options.state || options.contentMode;
|
||||
|
||||
if ( options.text ) {
|
||||
this.$el.text( options.text );
|
||||
|
@ -5950,6 +6226,9 @@ MenuItem = wp.media.View.extend(/** @lends wp.media.view.MenuItem.prototype */{
|
|||
this.$el.html( options.html );
|
||||
}
|
||||
|
||||
// Set the menu item ID based on the frame state associated to the menu item.
|
||||
this.$el.attr( 'id', 'menu-item-' + menuProperty );
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
@ -5983,15 +6262,30 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{
|
|||
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'
|
||||
} );
|
||||
|
||||
// The menu is always rendered and can be visible or hidden on some frames.
|
||||
this.isVisible = true;
|
||||
},
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
|
@ -6010,6 +6304,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{
|
|||
*/
|
||||
PriorityList.prototype.ready.apply( this, arguments );
|
||||
this.visibility();
|
||||
|
||||
// Set up aria tabs initial attributes.
|
||||
this.focusManager.setupAriaTabs();
|
||||
},
|
||||
|
||||
set: function() {
|
||||
|
@ -6035,6 +6332,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{
|
|||
hide = ! views || views.length < 2;
|
||||
|
||||
if ( this === view ) {
|
||||
// Flag this menu as hidden or visible.
|
||||
this.isVisible = ! hide;
|
||||
// Set or remove a CSS class to hide the menu.
|
||||
this.controller.$el.toggleClass( 'hide-' + region, hide );
|
||||
}
|
||||
},
|
||||
|
@ -6050,6 +6350,9 @@ Menu = PriorityList.extend(/** @lends wp.media.view.Menu.prototype */{
|
|||
|
||||
this.deselect();
|
||||
view.$el.addClass('active');
|
||||
|
||||
// Set up again the aria tabs initial attributes after the menu updates.
|
||||
this.focusManager.setupAriaTabs();
|
||||
},
|
||||
|
||||
deselect: function() {
|
||||
|
@ -6136,6 +6439,11 @@ Router = Menu.extend(/** @lends wp.media.view.Router.prototype */{
|
|||
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.
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -178,9 +178,15 @@ function wp_print_media_templates() {
|
|||
<?php // Template for the media frame: used both in the media grid and in the media modal. ?>
|
||||
<script type="text/html" id="tmpl-media-frame">
|
||||
<div class="media-frame-title" id="media-frame-title"></div>
|
||||
<button type="button" class="button button-link media-frame-menu-toggle" aria-expanded="false">
|
||||
<?php _e( 'Media Types' ); ?>
|
||||
<span class="dashicons dashicons-arrow-down" aria-hidden="true"></span>
|
||||
</button>
|
||||
<div class="media-frame-menu"></div>
|
||||
<div class="media-frame-router"></div>
|
||||
<div class="media-frame-content"></div>
|
||||
<div class="media-frame-tab-panel">
|
||||
<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>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '5.3-beta1-46362';
|
||||
$wp_version = '5.3-beta1-46363';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
Loading…
Reference in New Issue