Make WordPress Core

Ticket #47149: 47149.6.diff

File 47149.6.diff, 21.5 KB (added by afercia, 6 years ago)
  • src/js/media/views/focus-manager.js

     
     1var $ = jQuery;
     2
    13/**
    24 * wp.media.view.FocusManager
    35 *
     
    1113var FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.prototype */{
    1214
    1315        events: {
    14                 'keydown': 'constrainTabbing'
     16                'keydown': 'focusManagementMode'
    1517        },
    1618
    1719        /**
     20         * Initializes the Focus Manager.
     21         *
     22         * @param {object} options The Focus Manager options.
     23         *
     24         * @since 5.3.0
     25         *
     26         * @return {void}
     27         */
     28        initialize: function( options ) {
     29                this.mode                    = options.mode || 'constrainTabbing';
     30                this.tabsAutomaticActivation = options.tabsAutomaticActivation || false;
     31        },
     32
     33        /**
     34         * Determines which focus management mode to use.
     35         *
     36         * @since 5.3.0
     37         *
     38         * @param {object} event jQuery event object.
     39         *
     40         * @returns {void}
     41         */
     42        focusManagementMode: function( event ) {
     43                if ( this.mode === 'constrainTabbing' ) {
     44                        this.constrainTabbing( event );
     45                }
     46
     47                if ( this.mode === 'tabsNavigation' ) {
     48                        this.tabsNavigation( event );
     49                }
     50        },
     51
     52        /**
    1853         * Gets all the tabbable elements.
    1954         *
    2055         * @since 5.3.0
     
    67102        },
    68103
    69104        /**
    70          * Hides from assistive technologies all the body children except the
    71          * provided element and other elements that should not be hidden.
     105         * Hides from assistive technologies all the body children.
    72106         *
     107         * Sets an `aria-hidden="true"` attribute on all the body children except
     108         * the provided element and other elements that should not be hidden.
     109         *
    73110         * The reason why we use `aria-hidden` is that `aria-modal="true"` is buggy
    74111         * in Safari 11.1 and support is spotty in other browsers. Also, `aria-modal="true"`
    75112         * prevents the `wp.a11y.speak()` ARIA live regions to work as they're outside
     
    111148        },
    112149
    113150        /**
    114          * Makes visible again to assistive technologies all body children
     151         * Unhides from assistive technologies all the body children.
     152         *
     153         * Makes visible again to assistive technologies all the body children
    115154         * previously hidden and stored in this.ariaHiddenElements.
    116155         *
    117156         * @since 5.2.3
     
    165204         *
    166205         * @since 5.2.3
    167206         */
    168         ariaHiddenElements: []
     207        ariaHiddenElements: [],
     208
     209        /**
     210         * Holds the jQuery collection of ARIA tabs.
     211         *
     212         * @since 5.3.0
     213         */
     214        tabs: $(),
     215
     216        /**
     217         * Sets up tabs in an ARIA tabbed interface.
     218         *
     219         * @since 5.3.0
     220         *
     221         * @param {object} event jQuery event object.
     222         *
     223         * @returns {void}
     224         */
     225        setupAriaTabs: function() {
     226                this.tabs = this.$( '[role="tab"]' );
     227
     228                // Set up initial attributes.
     229                this.tabs.attr( {
     230                        'aria-selected': 'false',
     231                        tabIndex: '-1'
     232                } );
     233
     234                // Set up attributes on the initially active tab.
     235                this.tabs.filter( '.active' )
     236                        .removeAttr( 'tabindex' )
     237                        .attr( 'aria-selected', 'true' );
     238        },
     239
     240        /**
     241         * Enables arrows navigation within the ARIA tabbed interface.
     242         *
     243         * @since 5.3.0
     244         *
     245         * @param {object} event jQuery event object.
     246         *
     247         * @returns {void}
     248         */
     249        tabsNavigation: function( event ) {
     250                var orientation = 'horizontal',
     251                        keys = [ 32, 35, 36, 37, 38, 39, 40 ];
     252
     253                // Return if not Spacebar, End, Home, or Arrow keys.
     254                if ( keys.indexOf( event.which ) === -1 ) {
     255                        return;
     256                }
     257
     258                // Determine navigation direction.
     259                if ( this.$el.attr( 'aria-orientation' ) === 'vertical' ) {
     260                        orientation = 'vertical';
     261                }
     262
     263                // Make Up and Down arrow keys do nothing with horizontal tabs.
     264                if ( orientation === 'horizontal' && [ 38, 40 ].indexOf( event.which ) !== -1 ) {
     265                        return;
     266                }
     267
     268                // Make Left and Right arrow keys do nothing with vertical tabs.
     269                if ( orientation === 'vertical' && [ 37, 39 ].indexOf( event.which ) !== -1 ) {
     270                        return;
     271                }
     272
     273                this.switchTabs( event, this.tabs );
     274        },
     275
     276        /**
     277         * Switches tabs in the ARIA tabbed interface.
     278         *
     279         * @since 5.3.0
     280         *
     281         * @param {object} event jQuery event object.
     282         *
     283         * @returns {void}
     284         */
     285        switchTabs: function( event ) {
     286                var key   = event.which,
     287                        index = this.tabs.index( $( event.target ) ),
     288                        newIndex;
     289
     290                switch ( key ) {
     291                        // Space bar: Activate current targeted tab.
     292                        case 32: {
     293                                this.activateTab( this.tabs[ index ] );
     294                                break;
     295                        }
     296                        // End key: Activate last tab.
     297                        case 35: {
     298                                event.preventDefault();
     299                                this.activateTab( this.tabs[ this.tabs.length - 1 ] );
     300                                break;
     301                        }
     302                        // Home key: Activate first tab.
     303                        case 36: {
     304                                event.preventDefault();
     305                                this.activateTab( this.tabs[ 0 ] );
     306                                break;
     307                        }
     308                        // Left and up keys: Activate previous tab.
     309                        case 37:
     310                        case 38: {
     311                                event.preventDefault();
     312                                newIndex = ( index - 1 ) < 0 ? this.tabs.length - 1 : index - 1;
     313                                this.activateTab( this.tabs[ newIndex ] );
     314                                break;
     315                        }
     316                        // Right and down keys: Activate next tab.
     317                        case 39:
     318                        case 40: {
     319                                event.preventDefault();
     320                                newIndex = ( index + 1 ) === this.tabs.length ? 0 : index + 1;
     321                                this.activateTab( this.tabs[ newIndex ] );
     322                                break;
     323                        }
     324                }
     325        },
     326
     327        /**
     328         * Sets a single tab to be focusable and semantically selected.
     329         *
     330         * @since 5.3.0
     331         *
     332         * @param {object} tab The tab DOM element.
     333         *
     334         * @returns {void}
     335         */
     336        activateTab: function( tab ) {
     337                if ( ! tab ) {
     338                        return;
     339                }
     340
     341                // The tab is a DOM element: no need for jQuery methods.
     342                tab.focus();
     343
     344                // Handle automatic activation.
     345                if ( this.tabsAutomaticActivation ) {
     346                        tab.removeAttribute( 'tabindex' );
     347                        tab.setAttribute( 'aria-selected', 'true' );
     348                        tab.click();
     349
     350                        return;
     351                }
     352
     353                // Handle manual activation.
     354                $( tab ).on( 'click', function() {
     355                        tab.removeAttribute( 'tabindex' );
     356                        tab.setAttribute( 'aria-selected', 'true' );
     357                } );
     358        }
    169359});
    170360
    171361module.exports = FocusManager;
  • src/js/media/views/frame/post.js

     
    257257        mainMenu: function( view ) {
    258258                view.set({
    259259                        'library-separator': new wp.media.View({
    260                                 className: 'separator',
    261                                 priority: 100
     260                                className:  'separator',
     261                                priority:   100,
     262                                attributes: {
     263                                        role: 'presentation'
     264                                }
    262265                        })
    263266                });
    264267        },
  • src/js/media/views/media-frame.js

     
    2323        regions:   ['menu','title','content','toolbar','router'],
    2424
    2525        events: {
    26                 'click div.media-frame-title h1': 'toggleMenu'
     26                'click .media-frame-menu-toggle': 'toggleMenu'
    2727        },
    2828
    2929        /**
     
    7575                this.on( 'title:create:default', this.createTitle, this );
    7676                this.title.mode('default');
    7777
    78                 this.on( 'title:render', function( view ) {
    79                         view.$el.append( '<span class="dashicons dashicons-arrow-down"></span>' );
    80                 });
    81 
    8278                // Bind default menu.
    8379                this.on( 'menu:create:default', this.createMenu, this );
     80
     81                // Set the menu ARIA tab panel attributes when the modal opens.
     82                this.on( 'open', this.setMenuTabPanelAriaAttributes, this );
     83                // Set the router ARIA tab panel attributes when the modal opens.
     84                this.on( 'open', this.setRouterTabPanelAriaAttributes, this );
     85
     86                // Update the menu ARIA tab panel attributes when the content updates.
     87                this.on( 'content:render', this.setMenuTabPanelAriaAttributes, this );
     88                // Update the router ARIA tab panel attributes when the content updates.
     89                this.on( 'content:render', this.setRouterTabPanelAriaAttributes, this );
    8490        },
     91
    8592        /**
     93         * Sets the attributes to be used on the menu ARIA tab panel.
     94         *
     95         * @since 5.3.0
     96         *
     97         * @returns {void}
     98         */
     99        setMenuTabPanelAriaAttributes: function() {
     100                var stateId = this.state().get( 'id' ),
     101                        tabPanelEl = this.$el.find( '.media-frame-tab-panel' ),
     102                        ariaLabelledby;
     103
     104                tabPanelEl.removeAttr( 'role aria-labelledby tabindex' );
     105
     106                if ( this.menuView && this.menuView.isVisible ) {
     107                        ariaLabelledby = 'menu-item-' + stateId;
     108
     109                        // Set the tab panel attributes only if the tabs are visible.
     110                        tabPanelEl
     111                                .attr( {
     112                                        role: 'tabpanel',
     113                                        'aria-labelledby': ariaLabelledby,
     114                                        tabIndex: '0'
     115                                } );
     116                }
     117        },
     118
     119        /**
     120         * Sets the attributes to be used on the router ARIA tab panel.
     121         *
     122         * @since 5.3.0
     123         *
     124         * @returns {void}
     125         */
     126        setRouterTabPanelAriaAttributes: function() {
     127                var tabPanelEl = this.$el.find( '.media-frame-content' ),
     128                        ariaLabelledby;
     129
     130                tabPanelEl.removeAttr( 'role aria-labelledby tabindex' );
     131
     132                // On the Embed view the router menu is hidden.
     133                if ( 'embed' === this.content._mode ) {
     134                        return;
     135                }
     136
     137                // Set the tab panel attributes only if the tabs are visible.
     138                if ( this.routerView && this.routerView.isVisible && this.content._mode ) {
     139                        ariaLabelledby = 'menu-item-' + this.content._mode;
     140
     141                        tabPanelEl
     142                                .attr( {
     143                                        role: 'tabpanel',
     144                                        'aria-labelledby': ariaLabelledby,
     145                                        tabIndex: '0'
     146                                } );
     147                }
     148        },
     149
     150        /**
    86151         * @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
    87152         */
    88153        render: function() {
     
    111176         */
    112177        createMenu: function( menu ) {
    113178                menu.view = new wp.media.view.Menu({
    114                         controller: this
     179                        controller: this,
     180
     181                        attributes: {
     182                                role:               'tablist',
     183                                'aria-orientation': 'vertical'
     184                        }
    115185                });
     186
     187                this.menuView = menu.view;
    116188        },
    117189
    118         toggleMenu: function() {
    119                 this.$el.find( '.media-menu' ).toggleClass( 'visible' );
     190        toggleMenu: function( event ) {
     191                var menu = this.$el.find( '.media-menu' );
     192
     193                menu.toggleClass( 'visible' );
     194                $( event.target ).attr( 'aria-expanded', menu.hasClass( 'visible' ) );
    120195        },
    121196
    122197        /**
     
    134209         */
    135210        createRouter: function( router ) {
    136211                router.view = new wp.media.view.Router({
    137                         controller: this
     212                        controller: this,
     213
     214                        attributes: {
     215                                role:               'tablist',
     216                                'aria-orientation': 'horizontal'
     217                        }
    138218                });
     219
     220                this.routerView = router.view;
    139221        },
    140222        /**
    141223         * @param {Object} options
  • src/js/media/views/menu-item.js

     
    1111 * @augments Backbone.View
    1212 */
    1313MenuItem = wp.media.View.extend(/** @lends wp.media.view.MenuItem.prototype */{
    14         tagName:   'a',
     14        tagName:   'button',
    1515        className: 'media-menu-item',
    1616
    1717        attributes: {
    18                 href: '#'
     18                type: 'button',
     19                role: 'tab'
    1920        },
    2021
    2122        events: {
    2223                'click': '_click'
    2324        },
     25
    2426        /**
    25          * @param {Object} event
     27         * Allows to override the click event.
    2628         */
    27         _click: function( event ) {
     29        _click: function() {
    2830                var clickOverride = this.options.click;
    2931
    30                 if ( event ) {
    31                         event.preventDefault();
    32                 }
    33 
    3432                if ( clickOverride ) {
    3533                        clickOverride.call( this );
    3634                } else {
     
    4341
    4442                if ( state ) {
    4543                        this.controller.setState( state );
     44                        // Toggle the menu visibility in the responsive view.
    4645                        this.views.parent.$el.removeClass( 'visible' ); // TODO: or hide on any click, see below
    4746                }
    4847        },
     48
    4949        /**
    5050         * @returns {wp.media.view.MenuItem} returns itself to allow chaining
    5151         */
    5252        render: function() {
    53                 var options = this.options;
     53                var options = this.options,
     54                        menuProperty = options.state || options.contentMode;
    5455
    5556                if ( options.text ) {
    5657                        this.$el.text( options.text );
     
    5859                        this.$el.html( options.html );
    5960                }
    6061
     62                // Set the menu item ID based on the frame state associated to the menu item.
     63                this.$el.attr( 'id', 'menu-item-' + menuProperty );
     64
    6165                return this;
    6266        }
    6367});
  • src/js/media/views/menu.js

     
    2020        ItemView:  MenuItem,
    2121        region:    'menu',
    2222
    23         /* TODO: alternatively hide on any click anywhere
    24         events: {
    25                 'click': 'click'
     23        attributes: {
     24                role:               'tablist',
     25                'aria-orientation': 'horizontal'
    2626        },
    2727
    28         click: function() {
    29                 this.$el.removeClass( 'visible' );
     28        initialize: function() {
     29                this._views = {};
     30
     31                this.set( _.extend( {}, this._views, this.options.views ), { silent: true });
     32                delete this.options.views;
     33
     34                if ( ! this.options.silent ) {
     35                        this.render();
     36                }
     37
     38                // Initialize the Focus Manager.
     39                this.focusManager = new wp.media.view.FocusManager( {
     40                        el:   this.el,
     41                        mode: 'tabsNavigation'
     42                } );
     43
     44                // The menu is always rendered and can be visible or hidden on some frames.
     45                this.isVisible = true;
    3046        },
    31         */
    3247
    3348        /**
    3449         * @param {Object} options
     
    4762                 */
    4863                PriorityList.prototype.ready.apply( this, arguments );
    4964                this.visibility();
     65
     66                // Set up aria tabs initial attributes.
     67                this.focusManager.setupAriaTabs();
    5068        },
    5169
    5270        set: function() {
     
    7290                        hide = ! views || views.length < 2;
    7391
    7492                if ( this === view ) {
     93                        // Flag this menu as hidden or visible.
     94                        this.isVisible = ! hide;
     95                        // Set or remove a CSS class to hide the menu.
    7596                        this.controller.$el.toggleClass( 'hide-' + region, hide );
    7697                }
    7798        },
     
    87108
    88109                this.deselect();
    89110                view.$el.addClass('active');
     111
     112                // Set up again the aria tabs initial attributes after the menu updates.
     113                this.focusManager.setupAriaTabs();
    90114        },
    91115
    92116        deselect: function() {
  • src/js/media/views/router.js

     
    2020        ItemView:  wp.media.view.RouterItem,
    2121        region:    'router',
    2222
     23        attributes: {
     24                role:               'tablist',
     25                'aria-orientation': 'horizontal'
     26        },
     27
    2328        initialize: function() {
    2429                this.controller.on( 'content:render', this.update, this );
    2530                // Call 'initialize' directly on the parent class.
  • src/wp-includes/css/media-views.css

     
    580580        user-select: none;
    581581}
    582582
    583 .media-menu > a {
     583.media-menu .media-menu-item {
    584584        display: block;
     585        box-sizing: border-box;
     586        width: 100%;
    585587        position: relative;
     588        border: 0;
     589        margin: 0;
    586590        padding: 8px 20px;
    587         margin: 0;
     591        font-size: 14px;
    588592        line-height: 1.28571428;
    589         font-size: 14px;
     593        background: transparent;
    590594        color: #0073aa;
     595        text-align: left;
    591596        text-decoration: none;
     597        cursor: pointer;
    592598}
    593599
    594 .media-menu > a:hover {
    595         color: #0073aa;
     600.media-menu .media-menu-item:hover {
    596601        background: rgba(0, 0, 0, 0.04);
    597602}
    598603
    599 .media-menu > a:active {
     604.media-menu .media-menu-item:active {
     605        color: #0073aa;
    600606        outline: none;
    601607}
    602608
     
    606612        font-weight: 600;
    607613}
    608614
     615.media-menu .media-menu-item:focus {
     616        box-shadow:
     617                0 0 0 1px #5b9dd9,
     618                0 0 2px 1px rgba(30, 140, 190, 0.8);
     619        color: #124964;
     620        /* Only visible in Windows High Contrast mode */
     621        outline: 1px solid transparent;
     622}
     623
    609624.media-menu .separator {
    610625        height: 0;
    611626        margin: 12px 20px;
     
    621636        padding: 0 6px;
    622637        margin: 0;
    623638        clear: both;
    624         -webkit-user-select: none;
    625         -moz-user-select: none;
    626         -ms-user-select: none;
    627         user-select: none;
    628639}
    629640
    630 .media-router a {
    631         transition: none;
    632 }
    633 
    634 .media-router > a {
     641.media-router .media-menu-item {
    635642        position: relative;
    636643        float: left;
     644        border: 0;
     645        margin: 0;
    637646        padding: 8px 10px 9px;
    638         margin: 0;
    639647        height: 18px;
    640648        line-height: 1.28571428;
    641649        font-size: 14px;
    642650        text-decoration: none;
     651        background: transparent;
     652        cursor: pointer;
     653        transition: none;
    643654}
    644655
    645 .media-router > a:last-child {
     656.media-router .media-menu-item:last-child {
    646657        border-right: 0;
    647658}
    648659
    649 .media-router > a:active {
    650         outline: none;
     660.media-router .media-menu-item:hover,
     661.media-router .media-menu-item:active {
     662        color: #0073aa;
    651663}
    652664
    653665.media-router .active,
    654666.media-router .active:hover {
    655         color: #32373c;
     667        color: #23282d;
    656668}
    657669
     670.media-router .media-menu-item:focus {
     671        box-shadow:
     672                0 0 0 1px #5b9dd9,
     673                0 0 2px 1px rgba(30, 140, 190, 0.8);
     674        color: #124964;
     675        /* Only visible in Windows High Contrast mode */
     676        outline: 1px solid transparent;
     677}
     678
    658679.media-router .active,
    659 .media-router > a.active:last-child {
     680.media-router .media-menu-item.active:last-child {
    660681        margin: -1px -1px 0;
    661682        background: #fff;
    662683        border: 1px solid #ddd;
     
    752773        display: none;
    753774}
    754775
    755 .media-frame.hide-router .media-frame-title {
    756         border-bottom: 1px solid #ddd;
    757         box-shadow: 0 4px 4px -4px rgba(0, 0, 0, 0.1);
    758 }
    759 
    760 .media-frame-title .dashicons {
    761         display: none;
    762 }
    763 
    764776.media-frame-title h1 {
    765777        padding: 0 16px;
    766778        font-size: 22px;
     
    768780        margin: 0;
    769781}
    770782
     783.wp-core-ui .button.media-frame-menu-toggle {
     784        display: none;
     785}
     786
    771787.media-frame-title .suggested-dimensions {
    772788        font-size: 14px;
    773789        float: right;
     
    22512267 * Responsive layout
    22522268 */
    22532269@media only screen and (max-width: 900px) {
     2270        .media-modal .media-frame-title {
     2271                height: 40px;
     2272        }
    22542273
     2274        .media-modal .media-frame-title h1 {
     2275                line-height: 2.22222222;
     2276                font-size: 18px;
     2277        }
     2278
     2279        .media-modal-close {
     2280                width: 42px;
     2281                height: 42px;
     2282        }
     2283
    22552284        /* Drop-down menu */
    2256         .media-frame:not(.hide-menu) .media-frame-title,
     2285        .media-frame .media-frame-title {
     2286                position: static;
     2287                padding: 0 44px;
     2288                text-align: center;
     2289        }
     2290
    22572291        .media-frame:not(.hide-menu) .media-frame-router,
    22582292        .media-frame:not(.hide-menu) .media-frame-content,
    22592293        .media-frame:not(.hide-menu) .media-frame-toolbar {
     
    22602294                left: 0;
    22612295        }
    22622296
     2297        .media-frame:not(.hide-menu) .media-frame-router {
     2298                /* 40 title + (40 - 6) menu toggle button + 6 spacing */
     2299                top: 80px;
     2300        }
     2301
     2302        .media-frame:not(.hide-menu) .media-frame-content {
     2303                /* 80 + room for the tabs */
     2304                top: 114px;
     2305        }
     2306
     2307        .media-frame.hide-router .media-frame-content {
     2308                top: 80px;
     2309        }
     2310
    22632311        .media-frame:not(.hide-menu) .media-frame-menu {
    22642312                position: static;
    22652313                width: 0;
     
    22662314        }
    22672315
    22682316        .media-frame:not(.hide-menu) .media-menu {
     2317                display: none;
    22692318                width: auto;
    22702319                max-width: 80%;
    22712320                overflow: auto;
    22722321                z-index: 2000;
    2273                 top: 50px;
    2274                 left: -300px;
     2322                top: 75px;
     2323                left: 0;
    22752324                right: auto;
    22762325                bottom: auto;
    22772326                padding: 5px 0;
     
    22792328        }
    22802329
    22812330        .media-frame:not(.hide-menu) .media-menu.visible {
    2282                 left: 0;
     2331                display: block;
    22832332        }
    22842333
    22852334        .media-frame:not(.hide-menu) .media-menu > a {
     
    22872336                font-size: 16px;
    22882337        }
    22892338
    2290         .media-frame:not(.hide-menu) .media-menu > a.active {
    2291                 display: none;
    2292         }
    2293 
    22942339        .media-frame:not(.hide-menu) .media-menu .separator {
    22952340                margin: 5px 10px;
    22962341        }
    22972342
    2298         .media-frame:not(.hide-menu) .media-frame-title {
    2299                 left: 0;
     2343        .wp-core-ui .media-frame:not(.hide-menu) .button.media-frame-menu-toggle {
     2344                display: inline-flex;
     2345                align-items: center;
     2346                vertical-align: top;
     2347                min-height: 40px;
     2348                margin: -6px 6px 0;
     2349                padding: 0 2px 0 12px;
     2350                font-size: 0.875rem;
     2351                font-weight: 600;
     2352                text-decoration: none;
     2353                background: transparent;
    23002354        }
    23012355
    2302         .media-frame:not(.hide-menu) .media-frame-title .dashicons {
    2303                 display: inline-block;
    2304                 line-height: 2.5;
     2356        .wp-core-ui .button.media-frame-menu-toggle:hover,
     2357        .wp-core-ui .button.media-frame-menu-toggle:active {
     2358                background: transparent;
     2359                transform: none;
    23052360        }
    23062361
    2307         .media-frame:not(.hide-menu) .media-frame-title h1 {
    2308                 color: #0073aa;
    2309                 line-height: 3;
    2310                 font-size: 18px;
    2311                 float: left;
    2312                 cursor: pointer;
     2362        .wp-core-ui .button.media-frame-menu-toggle:focus {
     2363                /* Only visible in Windows High Contrast mode */
     2364                outline: 1px solid transparent;
    23132365        }
    23142366        /* End drop-down menu */
    23152367
     
    25612613        }
    25622614}
    25632615
    2564 /* Landscape specific header override */
    2565 @media screen and (max-height: 400px) {
    2566         .media-menu,
    2567         .media-frame:not(.hide-menu) .media-menu {
    2568                 top: 44px;
    2569         }
    2570 
    2571         .media-frame-router {
    2572                 top: 44px;
    2573         }
    2574 
    2575         .media-frame-content {
    2576                 top: 78px;
    2577         }
    2578 
    2579         .attachments-browser .attachments {
    2580                 top: 40px;
    2581         }
    2582 
    2583         /* Prevent unnecessary scrolling on title input */
    2584         .embed-link-settings {
    2585                 overflow: visible;
    2586         }
    2587 }
    2588 
    25892616@media only screen and (min-width: 901px) and (max-height: 400px) {
    25902617        .media-menu,
    25912618        .media-frame:not(.hide-menu) .media-menu {
     
    25952622}
    25962623
    25972624@media only screen and (max-width: 480px) {
    2598         .media-modal-close {
    2599                 top: -5px;
    2600         }
    2601 
    2602         .media-modal .media-frame-title {
    2603                 height: 40px;
    2604         }
    2605 
    26062625        .wp-core-ui.wp-customizer .media-button {
    26072626                margin-top: 13px;
    26082627        }
    26092628
    2610         .media-modal .media-frame-title h1,
    2611         .media-frame:not(.hide-menu) .media-frame-title h1 {
    2612                 font-size: 18px;
    2613                 line-height: 2.22222222;
    2614         }
    2615 
    2616         .media-frame:not(.hide-menu) .media-frame-title .dashicons {
    2617                 line-height: 2;
    2618         }
    2619 
    2620         .media-frame-router,
    2621         .media-frame:not(.hide-menu) .media-menu {
    2622                 top: 40px;
    2623                 padding-top: 0;
    2624         }
    2625 
    2626         .media-frame-content {
    2627                 top: 74px;
    2628         }
    2629 
    26302629        .media-frame.hide-router .media-frame-content {
    26312630                top: 40px;
    26322631        }
  • src/wp-includes/media-template.php

     
    178178        <?php // Template for the media frame: used both in the media grid and in the media modal. ?>
    179179        <script type="text/html" id="tmpl-media-frame">
    180180                <div class="media-frame-title" id="media-frame-title"></div>
     181                <button type="button" class="button button-link media-frame-menu-toggle" aria-expanded="false">
     182                        <?php _e( 'Media Types' ); ?>
     183                        <span class="dashicons dashicons-arrow-down" aria-hidden="true"></span>
     184                </button>
    181185                <div class="media-frame-menu"></div>
    182                 <div class="media-frame-router"></div>
    183                 <div class="media-frame-content"></div>
     186                <div class="media-frame-tab-panel">
     187                        <div class="media-frame-router"></div>
     188                        <div class="media-frame-content"></div>
     189                </div>
    184190                <div class="media-frame-toolbar"></div>
    185191                <div class="media-frame-uploader"></div>
    186192        </script>