Customize: Improve accessibility of markup for base `WP_Customize_Control` and `WP_Customize_Nav_Menu_Control` with proper use of `label` elements and inclusion of `aria-describedby`.

See #33085.
Props valendesigns, afercia, westonruter.


git-svn-id: https://develop.svn.wordpress.org/trunk@41740 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
westonruter 2017-10-04 18:11:08 +00:00
parent a0a2a4a105
commit b1faca5ca8
3 changed files with 114 additions and 83 deletions

View File

@ -929,9 +929,7 @@ p.customize-section-description {
line-height: 28px; line-height: 28px;
} }
.customize-control-radio label, .customize-control .customize-inside-control-row {
.customize-control-checkbox label,
.customize-control-nav_menu_auto_add label {
line-height: 20px; line-height: 20px;
display: block; display: block;
margin-left: 24px; margin-left: 24px;
@ -2670,9 +2668,9 @@ body.adding-widget .add-new-widget:before,
display: inline; display: inline;
} }
.customize-control-radio label, .customize-control-radio .customize-inside-control-row,
.customize-control-checkbox label, .customize-control-checkbox .customize-inside-control-row,
.customize-control-nav_menu_auto_add label { .customize-control-nav_menu_auto_add .customize-inside-control-row {
margin-left: 32px; margin-left: 32px;
} }

View File

@ -477,83 +477,104 @@ class WP_Customize_Control {
* @since 3.4.0 * @since 3.4.0
*/ */
protected function render_content() { protected function render_content() {
switch( $this->type ) { $input_id = '_customize-input-' . $this->id;
$description_id = '_customize-description-' . $this->id;
$describedby_attr = ( ! empty( $this->description ) ) ? 'aria-describedby="' . esc_attr( $description_id ) . '"' : '';
switch ( $this->type ) {
case 'checkbox': case 'checkbox':
?> ?>
<label> <span class="customize-inside-control-row">
<input type="checkbox" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); checked( $this->value() ); ?> /> <input
<?php echo esc_html( $this->label ); ?> id="<?php echo esc_attr( $input_id ); ?>"
<?php echo $describedby_attr; ?>
type="checkbox"
value="<?php echo esc_attr( $this->value() ); ?>"
<?php $this->link(); ?>
<?php checked( $this->value() ); ?>
/>
<label for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $this->label ); ?></label>
<?php if ( ! empty( $this->description ) ) : ?> <?php if ( ! empty( $this->description ) ) : ?>
<span class="description customize-control-description"><?php echo $this->description; ?></span> <span id="<?php echo esc_attr( $description_id ); ?>" class="description customize-control-description"><?php echo $this->description; ?></span>
<?php endif; ?> <?php endif; ?>
</label> </span>
<?php <?php
break; break;
case 'radio': case 'radio':
if ( empty( $this->choices ) ) if ( empty( $this->choices ) ) {
return; return;
}
$name = '_customize-radio-' . $this->id; $name = '_customize-radio-' . $this->id;
?>
if ( ! empty( $this->label ) ) : ?> <?php if ( ! empty( $this->label ) ) : ?>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
<?php endif; <?php endif; ?>
if ( ! empty( $this->description ) ) : ?> <?php if ( ! empty( $this->description ) ) : ?>
<span class="description customize-control-description"><?php echo $this->description ; ?></span> <span id="<?php echo esc_attr( $description_id ); ?>" class="description customize-control-description"><?php echo $this->description ; ?></span>
<?php endif; <?php endif; ?>
foreach ( $this->choices as $value => $label ) : <?php foreach ( $this->choices as $value => $label ) : ?>
?> <span class="customize-inside-control-row">
<label> <input
<input type="radio" value="<?php echo esc_attr( $value ); ?>" name="<?php echo esc_attr( $name ); ?>" <?php $this->link(); checked( $this->value(), $value ); ?> /> id="<?php echo esc_attr( $input_id . '-radio-' . $value ); ?>"
<?php echo esc_html( $label ); ?><br/> type="radio" <?php echo $describedby_attr; ?>
</label> value="<?php echo esc_attr( $value ); ?>"
<?php name="<?php echo esc_attr( $name ); ?>"
endforeach; <?php $this->link(); ?>
<?php checked( $this->value(), $value ); ?>
/>
<label for="<?php echo esc_attr( $input_id . '-radio-' . $value ); ?>"><?php echo esc_html( $label ); ?></label>
</span>
<?php endforeach; ?>
<?php
break; break;
case 'select': case 'select':
if ( empty( $this->choices ) ) if ( empty( $this->choices ) ) {
return; return;
}
?> ?>
<label> <?php if ( ! empty( $this->label ) ) : ?>
<?php if ( ! empty( $this->label ) ) : ?> <label for="<?php echo esc_attr( $input_id ); ?>" class="customize-control-title"><?php echo esc_html( $this->label ); ?></label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <?php endif; ?>
<?php endif; <?php if ( ! empty( $this->description ) ) : ?>
if ( ! empty( $this->description ) ) : ?> <span id="<?php echo esc_attr( $description_id ); ?>" class="description customize-control-description"><?php echo $this->description; ?></span>
<span class="description customize-control-description"><?php echo $this->description; ?></span> <?php endif; ?>
<?php endif; ?>
<select <?php $this->link(); ?>> <select id="<?php echo esc_attr( $input_id ); ?>" <?php echo $describedby_attr; ?> <?php $this->link(); ?>>
<?php <?php
foreach ( $this->choices as $value => $label ) foreach ( $this->choices as $value => $label ) {
echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . '>' . $label . '</option>'; echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . '>' . $label . '</option>';
?> }
</select> ?>
</label> </select>
<?php <?php
break; break;
case 'textarea': case 'textarea':
?> ?>
<label> <?php if ( ! empty( $this->label ) ) : ?>
<?php if ( ! empty( $this->label ) ) : ?> <label for="<?php echo esc_attr( $input_id ); ?>" class="customize-control-title"><?php echo esc_html( $this->label ); ?></label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <?php endif; ?>
<?php endif; <?php if ( ! empty( $this->description ) ) : ?>
if ( ! empty( $this->description ) ) : ?> <span id="<?php echo esc_attr( $description_id ); ?>" class="description customize-control-description"><?php echo $this->description; ?></span>
<span class="description customize-control-description"><?php echo $this->description; ?></span> <?php endif; ?>
<?php endif; ?> <textarea
<textarea rows="5" <?php $this->input_attrs(); ?> <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea> id="<?php echo esc_attr( $input_id ); ?>"
</label> rows="5"
<?php echo $describedby_attr; ?>
<?php $this->input_attrs(); ?>
<?php $this->link(); ?>>
<?php echo esc_textarea( $this->value() ); ?>
</textarea>
<?php <?php
break; break;
case 'dropdown-pages': case 'dropdown-pages':
?> ?>
<label>
<?php if ( ! empty( $this->label ) ) : ?> <?php if ( ! empty( $this->label ) ) : ?>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <label for="<?php echo esc_attr( $input_id ); ?>" class="customize-control-title"><?php echo esc_html( $this->label ); ?></label>
<?php endif; <?php endif; ?>
if ( ! empty( $this->description ) ) : ?> <?php if ( ! empty( $this->description ) ) : ?>
<span class="description customize-control-description"><?php echo $this->description; ?></span> <span id="<?php echo esc_attr( $description_id ); ?>" class="description customize-control-description"><?php echo $this->description; ?></span>
<?php endif; ?> <?php endif; ?>
<?php <?php
@ -576,7 +597,7 @@ class WP_Customize_Control {
} }
// Hackily add in the data link parameter. // Hackily add in the data link parameter.
$dropdown = str_replace( '<select', '<select ' . $this->get_link(), $dropdown ); $dropdown = str_replace( '<select', '<select ' . $this->get_link() . ' id="' . esc_attr( $input_id ) . '" ' . $describedby_attr, $dropdown );
// Even more hacikly add auto-draft page stubs. // Even more hacikly add auto-draft page stubs.
// @todo Eventually this should be removed in favor of the pages being injected into the underlying get_pages() call. See <https://github.com/xwp/wp-customize-posts/pull/250>. // @todo Eventually this should be removed in favor of the pages being injected into the underlying get_pages() call. See <https://github.com/xwp/wp-customize-posts/pull/250>.
@ -596,30 +617,37 @@ class WP_Customize_Control {
echo $dropdown; echo $dropdown;
?> ?>
</label>
<?php if ( $this->allow_addition && current_user_can( 'publish_pages' ) && current_user_can( 'edit_theme_options' ) ) : // Currently tied to menus functionality. ?> <?php if ( $this->allow_addition && current_user_can( 'publish_pages' ) && current_user_can( 'edit_theme_options' ) ) : // Currently tied to menus functionality. ?>
<button type="button" class="button-link add-new-toggle"><?php <button type="button" class="button-link add-new-toggle">
<?php
/* translators: %s: add new page label */ /* translators: %s: add new page label */
printf( __( '+ %s' ), get_post_type_object( 'page' )->labels->add_new_item ); printf( __( '+ %s' ), get_post_type_object( 'page' )->labels->add_new_item );
?></button> ?>
</button>
<div class="new-content-item"> <div class="new-content-item">
<label for="create-input-<?php echo $this->id; ?>"><span class="screen-reader-text"><?php _e( 'New page title' ); ?></span></label> <label for="create-input-<?php echo $this->id; ?>"><span class="screen-reader-text"><?php _e( 'New page title' ); ?></span></label>
<input type="text" id="create-input-<?php echo $this->id; ?>" class="create-item-input" placeholder="<?php esc_attr_e( 'New page title&hellip;' ); ?>"> <input type="text" id="create-input-<?php echo $this->id; ?>" class="create-item-input" placeholder="<?php esc_attr_e( 'New page title&hellip;' ); ?>">
<button type="button" class="button add-content"><?php _e( 'Add' ); ?></button> <button type="button" class="button add-content"><?php _e( 'Add' ); ?></button>
</div> </div>
<?php endif; <?php endif; ?>
<?php
break; break;
default: default:
?> ?>
<label> <?php if ( ! empty( $this->label ) ) : ?>
<?php if ( ! empty( $this->label ) ) : ?> <label for="<?php echo esc_attr( $input_id ); ?>" class="customize-control-title"><?php echo esc_html( $this->label ); ?></label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <?php endif; ?>
<?php endif; <?php if ( ! empty( $this->description ) ) : ?>
if ( ! empty( $this->description ) ) : ?> <span id="<?php echo esc_attr( $description_id ); ?>" class="description customize-control-description"><?php echo $this->description; ?></span>
<span class="description customize-control-description"><?php echo $this->description; ?></span> <?php endif; ?>
<?php endif; ?> <input
<input type="<?php echo esc_attr( $this->type ); ?>" <?php $this->input_attrs(); ?> value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); ?> /> id="<?php echo esc_attr( $input_id ); ?>"
</label> type="<?php echo esc_attr( $this->type ); ?>"
<?php echo $describedby_attr; ?>
<?php $this->input_attrs(); ?>
value="<?php echo esc_attr( $this->value() ); ?>"
<?php $this->link(); ?>
/>
<?php <?php
break; break;
} }

View File

@ -44,6 +44,7 @@ class WP_Customize_Nav_Menu_Control extends WP_Customize_Control {
*/ */
public function content_template() { public function content_template() {
?> ?>
<# var elementId; #>
<button type="button" class="button add-new-menu-item" aria-label="<?php esc_attr_e( 'Add or remove menu items' ); ?>" aria-expanded="false" aria-controls="available-menu-items"> <button type="button" class="button add-new-menu-item" aria-label="<?php esc_attr_e( 'Add or remove menu items' ); ?>" aria-expanded="false" aria-controls="available-menu-items">
<?php _e( 'Add Items' ); ?> <?php _e( 'Add Items' ); ?>
</button> </button>
@ -64,21 +65,25 @@ class WP_Customize_Nav_Menu_Control extends WP_Customize_Control {
</li> </li>
<?php foreach ( get_registered_nav_menus() as $location => $description ) : ?> <?php foreach ( get_registered_nav_menus() as $location => $description ) : ?>
<li class="customize-control customize-control-checkbox assigned-menu-location"> <# elementId = _.uniqueId( 'customize-nav-menu-control-location-' ); #>
<label> <li class="customize-control customize-control-checkbox assigned-menu-location customize-inside-control-row">
<input type="checkbox" data-menu-id="{{ data.menu_id }}" data-location-id="<?php echo esc_attr( $location ); ?>" class="menu-location" /> <?php echo $description; ?> <input id="{{ elementId }}" type="checkbox" data-menu-id="{{ data.menu_id }}" data-location-id="<?php echo esc_attr( $location ); ?>" class="menu-location" />
<span class="theme-location-set"><?php <label for="{{ elementId }}">
/* translators: %s: menu name */ <?php echo $description; ?>
printf( _x( '(Current: %s)', 'menu location' ), <span class="theme-location-set">
'<span class="current-menu-location-name-' . esc_attr( $location ) . '"></span>' <?php
); /* translators: %s: menu name */
?></span> printf( _x( '(Current: %s)', 'menu location' ),
</label> '<span class="current-menu-location-name-' . esc_attr( $location ) . '"></span>'
</li> );
?>
</span>
</label>
</li>
<?php endforeach; ?> <?php endforeach; ?>
</ul> </ul>
<?php endif; <?php endif; ?>
<?php
} }
/** /**