Themes: Fix accessibility issues with controls in themes screen.

Add accessible names to several theme controls so provide better context for screen reader users. Change theme details element into a button that can receive focus. Ensure focus is set back on existing theme when theme details modal is closed.

props alexstine, poena.
Fixes #52649.
Built from https://develop.svn.wordpress.org/trunk@51083


git-svn-id: http://core.svn.wordpress.org/trunk@50692 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
joedolson 2021-06-07 23:10:57 +00:00
parent 47fb9c7f3d
commit 637282bb0f
8 changed files with 75 additions and 43 deletions

View File

@ -67,7 +67,7 @@ body.js .theme-browser.search-loading {
} }
.theme-browser .theme:hover, .theme-browser .theme:hover,
.theme-browser .theme:focus { .theme-browser .theme.focus {
cursor: pointer; cursor: pointer;
} }
@ -96,8 +96,7 @@ body.js .theme-browser.search-loading {
} }
.theme-browser .theme:hover .theme-actions, .theme-browser .theme:hover .theme-actions,
.theme-browser .theme.focus .theme-actions, .theme-browser .theme.focus .theme-actions {
.theme-browser .theme:focus .theme-actions {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
opacity: 1; opacity: 1;
} }
@ -141,12 +140,12 @@ body.js .theme-browser.search-loading {
} }
.theme-browser .theme:hover .theme-screenshot, .theme-browser .theme:hover .theme-screenshot,
.theme-browser .theme:focus .theme-screenshot { .theme-browser .theme.focus .theme-screenshot {
background: #fff; background: #fff;
} }
.theme-browser.rendered .theme:hover .theme-screenshot img, .theme-browser.rendered .theme:hover .theme-screenshot img,
.theme-browser.rendered .theme:focus .theme-screenshot img { .theme-browser.rendered .theme.focus .theme-screenshot img {
opacity: 0.4; opacity: 0.4;
} }
@ -157,6 +156,7 @@ body.js .theme-browser.search-loading {
top: 35%; top: 35%;
left: 20%; left: 20%;
right: 20%; right: 20%;
width: 60%;
background: #1d2327; background: #1d2327;
background: rgba(0, 0, 0, 0.7); background: rgba(0, 0, 0, 0.7);
color: #fff; color: #fff;
@ -170,22 +170,26 @@ body.js .theme-browser.search-loading {
transition: opacity 0.1s ease-in-out; transition: opacity 0.1s ease-in-out;
} }
.theme-browser .theme:focus { .theme-browser .theme .more-details:focus {
box-shadow: 0 0 0 1px #fff, 0 0 0 3px #2271b1;
}
.theme-browser .theme.focus {
border-color: #4f94d4; border-color: #4f94d4;
box-shadow: 0 0 2px rgba(79, 148, 212, 0.8); box-shadow: 0 0 2px rgba(79, 148, 212, 0.8);
} }
.theme-browser .theme:focus .more-details { .theme-browser .theme.focus .more-details {
opacity: 1; opacity: 1;
} }
/* Current theme needs to have its action always on view */ /* Current theme needs to have its action always on view */
.theme-browser .theme.active:focus .theme-actions { .theme-browser .theme.active.focus .theme-actions {
display: block; display: block;
} }
.theme-browser.rendered .theme:hover .more-details, .theme-browser.rendered .theme:hover .more-details,
.theme-browser.rendered .theme:focus .more-details { .theme-browser.rendered .theme.focus .more-details {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
opacity: 1; opacity: 1;
} }
@ -878,12 +882,12 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
.theme:not(.active):hover .theme-actions, .theme:not(.active):hover .theme-actions,
.theme:not(.active):focus .theme-actions, .theme:not(.active):focus .theme-actions,
.theme:hover .more-details, .theme:hover .more-details,
.theme:focus .more-details { .theme.focus .more-details {
display: none; display: none;
} }
.theme-browser.rendered .theme:hover .theme-screenshot img, .theme-browser.rendered .theme:hover .theme-screenshot img,
.theme-browser.rendered .theme:focus .theme-screenshot img { .theme-browser.rendered .theme.focus .theme-screenshot img {
opacity: 1.0; opacity: 1.0;
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -66,7 +66,7 @@ body.js .theme-browser.search-loading {
} }
.theme-browser .theme:hover, .theme-browser .theme:hover,
.theme-browser .theme:focus { .theme-browser .theme.focus {
cursor: pointer; cursor: pointer;
} }
@ -95,8 +95,7 @@ body.js .theme-browser.search-loading {
} }
.theme-browser .theme:hover .theme-actions, .theme-browser .theme:hover .theme-actions,
.theme-browser .theme.focus .theme-actions, .theme-browser .theme.focus .theme-actions {
.theme-browser .theme:focus .theme-actions {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
opacity: 1; opacity: 1;
} }
@ -140,12 +139,12 @@ body.js .theme-browser.search-loading {
} }
.theme-browser .theme:hover .theme-screenshot, .theme-browser .theme:hover .theme-screenshot,
.theme-browser .theme:focus .theme-screenshot { .theme-browser .theme.focus .theme-screenshot {
background: #fff; background: #fff;
} }
.theme-browser.rendered .theme:hover .theme-screenshot img, .theme-browser.rendered .theme:hover .theme-screenshot img,
.theme-browser.rendered .theme:focus .theme-screenshot img { .theme-browser.rendered .theme.focus .theme-screenshot img {
opacity: 0.4; opacity: 0.4;
} }
@ -156,6 +155,7 @@ body.js .theme-browser.search-loading {
top: 35%; top: 35%;
right: 20%; right: 20%;
left: 20%; left: 20%;
width: 60%;
background: #1d2327; background: #1d2327;
background: rgba(0, 0, 0, 0.7); background: rgba(0, 0, 0, 0.7);
color: #fff; color: #fff;
@ -169,22 +169,26 @@ body.js .theme-browser.search-loading {
transition: opacity 0.1s ease-in-out; transition: opacity 0.1s ease-in-out;
} }
.theme-browser .theme:focus { .theme-browser .theme .more-details:focus {
box-shadow: 0 0 0 1px #fff, 0 0 0 3px #2271b1;
}
.theme-browser .theme.focus {
border-color: #4f94d4; border-color: #4f94d4;
box-shadow: 0 0 2px rgba(79, 148, 212, 0.8); box-shadow: 0 0 2px rgba(79, 148, 212, 0.8);
} }
.theme-browser .theme:focus .more-details { .theme-browser .theme.focus .more-details {
opacity: 1; opacity: 1;
} }
/* Current theme needs to have its action always on view */ /* Current theme needs to have its action always on view */
.theme-browser .theme.active:focus .theme-actions { .theme-browser .theme.active.focus .theme-actions {
display: block; display: block;
} }
.theme-browser.rendered .theme:hover .more-details, .theme-browser.rendered .theme:hover .more-details,
.theme-browser.rendered .theme:focus .more-details { .theme-browser.rendered .theme.focus .more-details {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
opacity: 1; opacity: 1;
} }
@ -877,12 +881,12 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
.theme:not(.active):hover .theme-actions, .theme:not(.active):hover .theme-actions,
.theme:not(.active):focus .theme-actions, .theme:not(.active):focus .theme-actions,
.theme:hover .more-details, .theme:hover .more-details,
.theme:focus .more-details { .theme.focus .more-details {
display: none; display: none;
} }
.theme-browser.rendered .theme:hover .theme-screenshot img, .theme-browser.rendered .theme:hover .theme-screenshot img,
.theme-browser.rendered .theme:focus .theme-screenshot img { .theme-browser.rendered .theme.focus .theme-screenshot img {
opacity: 1.0; opacity: 1.0;
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -404,11 +404,7 @@ themes.view.Theme = wp.Backbone.View.extend({
var data = this.model.toJSON(); var data = this.model.toJSON();
// Render themes using the html template. // Render themes using the html template.
this.$el.html( this.html( data ) ).attr({ this.$el.html( this.html( data ) ).attr( 'data-slug', data.id );
tabindex: 0,
'aria-describedby' : data.id + '-action ' + data.id + '-name',
'data-slug': data.id
});
// Renders active theme styles. // Renders active theme styles.
this.activeTheme(); this.activeTheme();
@ -764,7 +760,7 @@ themes.view.Details = wp.Backbone.View.extend({
// Return focus to the theme div. // Return focus to the theme div.
if ( themes.focusedTheme ) { if ( themes.focusedTheme ) {
themes.focusedTheme.trigger( 'focus' ); themes.focusedTheme.find('.more-details').trigger( 'focus' );
} }
}); });
} }
@ -952,7 +948,7 @@ themes.view.Preview = themes.view.Details.extend({
// Return focus to the theme div. // Return focus to the theme div.
if ( themes.focusedTheme ) { if ( themes.focusedTheme ) {
themes.focusedTheme.trigger( 'focus' ); themes.focusedTheme.find('.more-details').trigger( 'focus' );
} }
}).removeClass( 'iframe-ready' ); }).removeClass( 'iframe-ready' );

File diff suppressed because one or more lines are too long

View File

@ -370,7 +370,7 @@ foreach ( $themes as $theme ) :
$active_class = ' active'; $active_class = ' active';
} }
?> ?>
<div class="theme<?php echo $active_class; ?>" tabindex="0" aria-describedby="<?php echo $aria_action . ' ' . $aria_name; ?>"> <div class="theme<?php echo $active_class; ?>">
<?php if ( ! empty( $theme['screenshot'][0] ) ) { ?> <?php if ( ! empty( $theme['screenshot'][0] ) ) { ?>
<div class="theme-screenshot"> <div class="theme-screenshot">
<img src="<?php echo $theme['screenshot'][0]; ?>" alt="" /> <img src="<?php echo $theme['screenshot'][0]; ?>" alt="" />
@ -503,7 +503,11 @@ foreach ( $themes as $theme ) :
} }
?> ?>
<span class="more-details" id="<?php echo $aria_action; ?>"><?php _e( 'Theme Details' ); ?></span> <?php
/* translators: %s: Theme name. */
$details_aria_label = sprintf( _x( 'View Theme Details for %s', 'theme' ), $theme['name'] );
?>
<button type="button" aria-label="<?php echo esc_attr( $details_aria_label ); ?>" class="more-details" id="<?php echo $aria_action; ?>"><?php _e( 'Theme Details' ); ?></button>
<div class="theme-author"> <div class="theme-author">
<?php <?php
/* translators: %s: Theme author name. */ /* translators: %s: Theme author name. */
@ -522,8 +526,12 @@ foreach ( $themes as $theme ) :
<div class="theme-actions"> <div class="theme-actions">
<?php if ( $theme['active'] ) { ?> <?php if ( $theme['active'] ) { ?>
<?php if ( $theme['actions']['customize'] && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { ?> <?php
<a class="button button-primary customize load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Customize' ); ?></a> if ( $theme['actions']['customize'] && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
/* translators: %s: Theme name. */
$customize_aria_label = sprintf( _x( 'Customize %s', 'theme' ), $theme['name'] );
?>
<a aria-label="<?php echo esc_attr( $customize_aria_label ); ?>" class="button button-primary customize load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Customize' ); ?></a>
<?php } ?> <?php } ?>
<?php } elseif ( $theme['compatibleWP'] && $theme['compatiblePHP'] ) { ?> <?php } elseif ( $theme['compatibleWP'] && $theme['compatiblePHP'] ) { ?>
<?php <?php
@ -531,8 +539,12 @@ foreach ( $themes as $theme ) :
$aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' ); $aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' );
?> ?>
<a class="button activate" href="<?php echo $theme['actions']['activate']; ?>" aria-label="<?php echo esc_attr( $aria_label ); ?>"><?php _e( 'Activate' ); ?></a> <a class="button activate" href="<?php echo $theme['actions']['activate']; ?>" aria-label="<?php echo esc_attr( $aria_label ); ?>"><?php _e( 'Activate' ); ?></a>
<?php if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { ?> <?php
<a class="button button-primary load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Live Preview' ); ?></a> if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
/* translators: %s: Theme name. */
$live_preview_aria_label = sprintf( _x( 'Live Preview %s', 'theme' ), '{{ data.name }}' );
?>
<a aria-label="<?php echo esc_attr( $live_preview_aria_label ); ?>" class="button button-primary load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Live Preview' ); ?></a>
<?php } ?> <?php } ?>
<?php } else { ?> <?php } else { ?>
<?php <?php
@ -850,7 +862,11 @@ function wp_theme_auto_update_setting_template() {
</p></div> </p></div>
<# } #> <# } #>
<span class="more-details" id="{{ data.id }}-action"><?php _e( 'Theme Details' ); ?></span> <?php
/* translators: %s: Theme name. */
$details_aria_label = sprintf( _x( 'View Theme Details for %s', 'theme' ), '{{ data.name }}' );
?>
<button type="button" aria-label="<?php echo esc_attr( $details_aria_label ); ?>" class="more-details" id="{{ data.id }}-action"><?php _e( 'Theme Details' ); ?></button>
<div class="theme-author"> <div class="theme-author">
<?php <?php
/* translators: %s: Theme author name. */ /* translators: %s: Theme author name. */
@ -870,7 +886,11 @@ function wp_theme_auto_update_setting_template() {
<div class="theme-actions"> <div class="theme-actions">
<# if ( data.active ) { #> <# if ( data.active ) { #>
<# if ( data.actions.customize ) { #> <# if ( data.actions.customize ) { #>
<a class="button button-primary customize load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Customize' ); ?></a> <?php
/* translators: %s: Theme name. */
$customize_aria_label = sprintf( _x( 'Customize %s', 'theme' ), '{{ data.name }}' );
?>
<a aria-label="<?php echo esc_attr( $customize_aria_label ); ?>" class="button button-primary customize load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Customize' ); ?></a>
<# } #> <# } #>
<# } else { #> <# } else { #>
<# if ( data.compatibleWP && data.compatiblePHP ) { #> <# if ( data.compatibleWP && data.compatiblePHP ) { #>
@ -879,7 +899,11 @@ function wp_theme_auto_update_setting_template() {
$aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' ); $aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' );
?> ?>
<a class="button activate" href="{{{ data.actions.activate }}}" aria-label="<?php echo $aria_label; ?>"><?php _e( 'Activate' ); ?></a> <a class="button activate" href="{{{ data.actions.activate }}}" aria-label="<?php echo $aria_label; ?>"><?php _e( 'Activate' ); ?></a>
<a class="button button-primary load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a> <?php
/* translators: %s: Theme name. */
$live_preview_aria_label = sprintf( _x( 'Live Preview %s', 'theme' ), '{{ data.name }}' );
?>
<a aria-label="<?php echo esc_attr( $live_preview_aria_label ); ?>" class="button button-primary load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a>
<# } else { #> <# } else { #>
<?php <?php
/* translators: %s: Theme name. */ /* translators: %s: Theme name. */
@ -1108,7 +1132,11 @@ function wp_theme_auto_update_setting_template() {
</div> </div>
<# if ( ! data.active && data.actions['delete'] ) { #> <# if ( ! data.active && data.actions['delete'] ) { #>
<a href="{{{ data.actions['delete'] }}}" class="button delete-theme"><?php _e( 'Delete' ); ?></a> <?php
/* translators: %s: Theme name. */
$aria_label = sprintf( _x( 'Delete %s', 'theme' ), '{{ data.name }}' );
?>
<a href="{{{ data.actions['delete'] }}}" class="button delete-theme" aria-label="<?php echo $aria_label; ?>"><?php _e( 'Delete' ); ?></a>
<# } #> <# } #>
</div> </div>
</div> </div>

View File

@ -13,7 +13,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '5.8-alpha-51082'; $wp_version = '5.8-alpha-51083';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.