Make WordPress Core

Changeset 61757


Ignore:
Timestamp:
02/27/2026 07:14:49 PM (8 months ago)
Author:
joedolson
Message:

Media: Make filters & image selection usable by voice control.

Add a visible label with the aria-label value for image selection to enable voice control users to select images. Add visible labels on filters to improve access to media filters.

Props grahamarmfield, tomauger, afercia, rianrietveld, antpb, audrasjb, SirLouen, ozgursar, poojapadamad, mukesh27, alh0319, joedolson.
Fixes #23562.

Location:
trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/media/views/attachments/browser.js

    r58146 r61757  
    194194                                text:       l10n.filterAttachments,
    195195                                level:      'h2',
    196                                 className:  'media-attachments-filter-heading'
     196                                className:  'media-attachments-filter-heading screen-reader-text'
    197197                        }).render() );
    198198                }
    … …  
    200200                if ( showFilterByType ) {
    201201                        // "Filters" is a <select>, a visually hidden label element needs to be rendered before.
    202                         this.toolbar.set( 'filtersLabel', new wp.media.view.Label({
     202                        var filtersLabel = new wp.media.view.Label({
    203203                                value: l10n.filterByType,
    204204                                attributes: {
    … …  
    206206                                },
    207207                                priority:   -80
    208                         }).render() );
     208                        });
    209209
    210210                        if ( 'uploaded' === this.options.filters ) {
    211                                 this.toolbar.set( 'filters', new wp.media.view.AttachmentFilters.Uploaded({
     211                                Filters = new wp.media.view.AttachmentFilters.Uploaded({
    212212                                        controller: this.controller,
    213213                                        model:      this.collection.props,
    214                                         priority:   -80
    215                                 }).render() );
     214                                });
    216215                        } else {
    217216                                Filters = new wp.media.view.AttachmentFilters.All({
    218217                                        controller: this.controller,
    219218                                        model:      this.collection.props,
    220                                         priority:   -80
    221219                                });
    222 
    223                                 this.toolbar.set( 'filters', Filters.render() );
    224220                        }
    225                 }
    226 
     221
     222                        var filterContainer = wp.media.View.extend({
     223                                tagname: 'div',
     224                                className: 'media-filter-container type-filter',
     225
     226                                initialize: function() {
     227                                        this.views.add( [ filtersLabel, Filters ] );
     228                                }
     229                        });
     230
     231                        this.toolbar.set( 'filters', new filterContainer({
     232                                controller: this.controller,
     233                                model:      this.controller.props,
     234                                priority:   -80
     235                        }).render() );
     236                }
     237               
     238                var dateFilter, dateFilterLabel, dateFilterContainer;
    227239                /*
    228240                 * Feels odd to bring the global media library switcher into the Attachment browser view.
    … …  
    242254
    243255                        // DateFilter is a <select>, a visually hidden label element needs to be rendered before.
    244                         this.toolbar.set( 'dateFilterLabel', new wp.media.view.Label({
     256                        dateFilterLabel = new wp.media.view.Label({
    245257                                value: l10n.filterByDate,
    246258                                attributes: {
    247259                                        'for': 'media-attachment-date-filters'
    248260                                },
    249                                 priority: -75
    250                         }).render() );
    251                         this.toolbar.set( 'dateFilter', new wp.media.view.DateFilter({
     261                        });
     262                        dateFilter = new wp.media.view.DateFilter({
    252263                                controller: this.controller,
    253264                                model:      this.collection.props,
    254                                 priority: -75
     265                        });
     266
     267                        dateFilterContainer = wp.media.View.extend({
     268                                tagname: 'div',
     269                                className: 'media-filter-container date-filter',
     270
     271                                initialize: function() {
     272                                        this.views.add( [ dateFilterLabel, dateFilter ] );
     273                                }
     274                        });
     275
     276                        this.toolbar.set( 'dateFilters', new dateFilterContainer({
     277                                controller: this.controller,
     278                                model:      this.collection.props,
     279                                priority:   -75
    255280                        }).render() );
    256281
    … …  
    364389                } else if ( this.options.date ) {
    365390                        // DateFilter is a <select>, a visually hidden label element needs to be rendered before.
    366                         this.toolbar.set( 'dateFilterLabel', new wp.media.view.Label({
     391                        dateFilterLabel = new wp.media.view.Label({
    367392                                value: l10n.filterByDate,
    368393                                attributes: {
    369394                                        'for': 'media-attachment-date-filters'
    370395                                },
    371                                 priority: -75
    372                         }).render() );
    373                         this.toolbar.set( 'dateFilter', new wp.media.view.DateFilter({
     396                        });
     397                        dateFilter = new wp.media.view.DateFilter({
    374398                                controller: this.controller,
    375399                                model:      this.collection.props,
    376                                 priority: -75
     400                        });
     401
     402                        dateFilterContainer = wp.media.View.extend({
     403                                tagname: 'div',
     404                                className: 'media-filter-container date-filter',
     405
     406                                initialize: function() {
     407                                        this.views.add( [ dateFilterLabel, dateFilter ] );
     408                                }
     409                        });
     410
     411                        this.toolbar.set( 'dateFilters', new dateFilterContainer({
     412                                controller: this.controller,
     413                                model:      this.collection.props,
     414                                priority:   -75
    377415                        }).render() );
    378416                }
  • trunk/src/js/media/views/label.js

    r43309 r61757  
    1111var Label = wp.media.View.extend(/** @lends wp.media.view.Label.prototype */{
    1212        tagName: 'label',
    13         className: 'screen-reader-text',
    1413
    1514        initialize: function() {
  • trunk/src/js/media/views/uploader/inline.js

    r52171 r61757  
    116116                        $browser.detach().text( $placeholder.text() );
    117117                        $browser[0].className = $placeholder[0].className;
    118                         $browser[0].setAttribute( 'aria-labelledby', $browser[0].id + ' ' + $placeholder[0].getAttribute('aria-labelledby') );
     118                        $browser[0].setAttribute( 'aria-describedby', $placeholder[0].getAttribute('aria-describedby') );
    119119                        $placeholder.replaceWith( $browser.show() );
    120120                }
  • trunk/src/wp-admin/css/media.css

    r61652 r61757  
    556556}
    557557
     558.media-frame.mode-grid .media-toolbar label {
     559        display: block;
     560}
     561
    558562.media-frame.mode-grid .media-toolbar select {
    559563        margin: 0 10px 0 0;
    … …  
    573577        line-height: 2.30769231; /* 30px for 32px height with 13px font */
    574578        padding: 0 12px;
     579        align-self: end;
    575580}
    576581
    577582.media-frame.mode-grid.mode-edit .media-toolbar-secondary > .select-mode-toggle-button {
    578583        margin: 0 8px 0 0;
    579         vertical-align: middle;
     584        height: 100%;
    580585}
    581586
  • trunk/src/wp-includes/css/media-views.css

    r61744 r61757  
    2626.media-modal label {
    2727        font-size: 13px;
     28}
     29
     30.media-modal .media-filter-container label {
     31        display: block;
     32}
     33
     34.media-modal .media-filter-container select,
     35.media-modal .search-form input {
     36        margin-top: 6px;
    2837}
    2938
    … …  
    296305}
    297306
    298 .media-modal-content .media-frame select.attachment-filters {
    299         margin-top: 32px;
    300         margin-right: 2%;
    301         width: 42%;
    302         width: calc(48% - 12px);
    303 }
    304 
    305307/* higher specificity */
    306308.wp-core-ui .media-modal-icon {
    … …  
    318320        right: 0;
    319321        z-index: 100;
    320         height: 60px;
     322        height: 48px;
    321323        padding: 0 16px;
    322324        border: 0 solid #dcdcde;
    323         overflow: hidden;
     325        overflow: auto;
    324326}
    325327
    … …  
    348350        float: left;
    349351        height: 100%;
     352        display: flex;
     353        flex-wrap: wrap;
     354        gap: 12px;
    350355}
    351356
    … …  
    936941        line-height: 2.14285714; /* 30px for 32px height with 14px font */
    937942        padding: 0 24px 0 8px;
    938         margin-top: 11px;
    939943        margin-right: 2%;
    940         max-width: 42%;
    941         max-width: calc(48% - 12px);
    942944}
    943945
    … …  
    950952 */
    951953.media-frame .search {
    952         margin: 32px 0 0;
     954        margin: 0;
    953955        padding: 4px;
    954956        font-size: 13px;
    … …  
    963965
    964966.media-modal .media-frame .media-search-input-label {
    965         position: absolute;
    966         left: 0;
    967         top: 10px;
    968         margin: 0;
    969         line-height: 1;
     967        display: block;
    970968}
    971969
    … …  
    996994}
    997995
     996.wp-core-ui .attachment:not(:has(.filename))::after {
     997        content: attr(aria-label);
     998        position: absolute;
     999        bottom: 8px;
     1000        width: calc( 100% - 16px );
     1001        left: 8px;
     1002        font-size: 12px;
     1003        background-color: rgba(255, 255, 255, 0.8);
     1004        color: #1d2327;
     1005        max-height: 3rem;
     1006        overflow: hidden;
     1007        text-align: start;
     1008        padding: 5px 10px;
     1009        word-wrap: break-word;
     1010        box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
     1011        box-sizing: border-box;
     1012        font-weight: 600;
     1013}
     1014
    9981015.wp-core-ui .attachment:focus,
    9991016.wp-core-ui .selected.attachment:focus,
    … …  
    12191236.attachments-browser .media-toolbar {
    12201237        right: 300px;
    1221         height: 72px;
    12221238        background: #fff;
     1239        padding: 12px 16px;
    12231240}
    12241241
    … …  
    26032620
    26042621        .attachments-browser .media-toolbar {
    2605                 height: 82px;
     2622                height: 74px;
    26062623        }
    26072624
    … …  
    26092626        .attachments-browser .uploader-inline,
    26102627        .media-frame-content .attachments-browser .attachments-wrapper {
    2611                 top: 82px;
     2628                top: 90px;
    26122629        }
    26132630
  • trunk/src/wp-includes/media-template.php

    r61703 r61757  
    270270                                <h2 class="upload-instructions drop-instructions"><?php _e( 'Drop files to upload' ); ?></h2>
    271271                                <p class="upload-instructions drop-instructions"><?php _ex( 'or', 'Uploader: Drop files here - or - Select Files' ); ?></p>
    272                                 <button type="button" class="browser button button-hero" aria-labelledby="post-upload-info"><?php _e( 'Select Files' ); ?></button>
     272                                <button type="button" class="browser button button-hero" aria-describedby="post-upload-info"><?php _e( 'Select Files' ); ?></button>
    273273                        </div>
    274274
Note: See TracChangeset for help on using the changeset viewer.