WordPress.org

Make WordPress Core

Changeset 38853


Ignore:
Timestamp:
10/21/2016 06:36:57 AM (19 months ago)
Author:
westonruter
Message:

Customize: Add sticky headers for panels and sections.

Includes autoprefixing of CSS.

Props delawski, celloexpressions.
See #35186.
Fixes #34343.

Location:
trunk/src/wp-admin
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/customize-controls.css

    r38829 r38853  
    5656#customize-controls .customize-info.section-meta {
    5757    margin-bottom: 15px;
     58}
     59
     60#customize-controls .customize-info.is-in-view,
     61#customize-controls .customize-section-title.is-in-view {
     62    position: absolute;
     63    z-index: 9;
     64    width: 100%;
     65    -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
     66    box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
     67}
     68
     69#customize-controls .customize-section-title.is-in-view {
     70    margin-top: 0;
     71}
     72
     73#customize-controls .customize-info.is-in-view + .accordion-section {
     74    margin-top: 15px;
     75}
     76
     77#customize-controls .customize-info.is-sticky,
     78#customize-controls .customize-section-title.is-sticky {
     79    position: fixed;
     80    top: 46px;
    5881}
    5982
     
    324347#customize-theme-controls .customize-pane-child.accordion-section-content {
    325348    padding: 12px;
     349}
     350
     351#customize-theme-controls .customize-pane-child.menu li {
     352    position: static;
    326353}
    327354
     
    410437    float: left;
    411438    width: 48px;
    412     height: 70px;
     439    height: 71px;
    413440    padding: 0 24px 0 0;
    414441    margin: 0;
     
    424451
    425452.customize-section-back {
    426     height: 73px;
     453    height: 74px;
    427454}
    428455
     
    485512
    486513.wp-full-overlay-sidebar .wp-full-overlay-header {
     514    background-color: #eee;
    487515    -webkit-transition: padding ease-in-out .18s;
    488516    transition: padding ease-in-out .18s;
     
    10891117    top: 0;
    10901118    left: 0;
     1119    -webkit-transition: .18s left ease-in-out;
    10911120    transition: .18s left ease-in-out;
    10921121    margin: 0 0 0 300px;
    10931122    padding:25px;
    10941123    overflow-y: scroll;
     1124    width: -webkit-calc(100% - 350px);
    10951125    width: calc(100% - 350px);
     1126    height: -webkit-calc(100% - 50px);
    10961127    height: calc(100% - 50px);
    10971128    background: #eee;
     
    11051136    position: relative;
    11061137    top: 0;
     1138    -webkit-transition: .18s top ease-in-out;
    11071139    transition: .18s top ease-in-out;
    11081140}
     
    11111143#customize-footer-actions .collapse-sidebar {
    11121144    bottom: 0;
     1145    -webkit-transition: .18s bottom ease-in-out;
    11131146    transition: .18s bottom ease-in-out;
    11141147}
     
    11471180
    11481181/* Adds a delay before fading in to avoid it "jumping" */
     1182@-webkit-keyframes themes-fade-in {
     1183    0% {
     1184        opacity: 0;
     1185    }
     1186    50% {
     1187        opacity: 0;
     1188    }
     1189    100% {
     1190        opacity: 1;
     1191    }
     1192}
    11491193@keyframes themes-fade-in {
    11501194    0% {
     
    11601204
    11611205.control-panel-themes .customize-themes-full-container.animate {
     1206    -webkit-animation: .6s themes-fade-in 1;
    11621207    animation: .6s themes-fade-in 1;
    11631208}
    11641209
    11651210.in-themes-panel:not(.animating) .control-panel-themes .filter-themes-count {
     1211    -webkit-animation: .6s themes-fade-in 1;
    11661212    animation: .6s themes-fade-in 1;
    11671213}
     
    12061252
    12071253    .control-panel-themes .filter-themes-count {
     1254        width: -webkit-calc(100% - 93px);
    12081255        width: calc(100% - 93px);
    12091256    }
     
    12371284
    12381285    .control-panel-themes .customize-themes-full-container {
     1286        width: -webkit-calc(100% - 50px);
    12391287        width: calc(100% - 50px);
    12401288        margin: 0;
    12411289        top: 46px;
     1290        height: -webkit-calc(100% - 96px);
    12421291        height: calc(100% - 96px);
    12431292        z-index: 1;
     
    12741323    width: 100%;
    12751324    background: #fff;
     1325    -webkit-box-shadow: none;
    12761326    box-shadow: none;
    12771327    outline: none;
     
    13051355    content: "\f147";
    13061356    font: 16px/1 dashicons;
     1357    -webkit-box-sizing: border-box;
     1358    -moz-box-sizing: border-box;
    13071359    box-sizing: border-box;
    13081360    width: 20px;
    13091361    height: 20px;
    13101362    padding: 3px 3px 1px 1px; /* Re-align the icon to the smaller grid */
     1363    -webkit-border-radius: 100%;
    13111364    border-radius: 100%;
    13121365    position: absolute;
     
    13771430    border: none;
    13781431    padding: 0;
     1432    -webkit-box-shadow: none;
    13791433    box-shadow: none;
    13801434}
     
    14071461    border-bottom-color: #0073aa; /* Color change for focus style should be acceptable because border-bottom is barely visible previously. */
    14081462    outline: none;
     1463    -webkit-box-shadow: none;
    14091464    box-shadow: none;
    14101465}
     
    14261481    margin: 0;
    14271482    padding: 12px 10px 12px 34px;
     1483    width: -webkit-calc(100% - 46px);
    14281484    width: calc(100% - 46px);
    14291485    line-height: 16px;
     
    14541510    width: 20px;
    14551511    height: 20px;
     1512    left: -webkit-calc(50% - 10px);
    14561513    left: calc(50% - 10px);
    14571514    float: none;
     
    14891546
    14901547.customize-control.customize-control-theme { /* override most properties on .customize-control */
     1548    -webkit-box-sizing: border-box;
     1549    -moz-box-sizing: border-box;
    14911550    box-sizing: border-box;
    14921551    width: 18.4%;
  • trunk/src/wp-admin/css/customize-nav-menus.css

    r38709 r38853  
    6666}
    6767
     68.wp-customizer .menu-item-handle:hover {
     69    z-index: 8;
     70}
     71
    6872.customize-control-nav_menu_item.has-notifications .menu-item-handle {
    6973    border-left: 4px solid #00a0d2;
     
    7377    max-width: 100%;
    7478    overflow: hidden;
     79    z-index: 8;
    7580    padding: 10px;
    7681    background: #eee;
  • trunk/src/wp-admin/js/customize-controls.js

    r38829 r38853  
    10051005                        content.addClass( 'open' );
    10061006                        overlay.addClass( 'section-open' );
     1007                        api.state( 'expandedSection' ).set( section );
    10071008                    }, this );
    10081009                }
     
    10431044                content.removeClass( 'open' );
    10441045                overlay.removeClass( 'section-open' );
     1046                if ( section === api.state( 'expandedSection' ).get() ) {
     1047                    api.state( 'expandedSection' ).set( false );
     1048                }
    10451049
    10461050            } else {
     
    19962000                overlay.addClass( 'in-sub-panel' );
    19972001                accordionSection.addClass( 'current-panel' );
     2002                api.state( 'expandedPanel' ).set( panel );
    19982003
    19992004            } else if ( ! expanded && accordionSection.hasClass( 'current-panel' ) ) {
     
    20122017                overlay.removeClass( 'in-sub-panel' );
    20132018                accordionSection.removeClass( 'current-panel' );
     2019                if ( panel === api.state( 'expandedPanel' ).get() ) {
     2020                    api.state( 'expandedPanel' ).set( false );
     2021                }
    20142022            }
    20152023        },
     
    49694977                processing = state.create( 'processing' ),
    49704978                paneVisible = state.create( 'paneVisible' ),
     4979                expandedPanel = state.create( 'expandedPanel' ),
     4980                expandedSection = state.create( 'expandedSection' ),
    49714981                changesetStatus = state.create( 'changesetStatus' ),
    49724982                previewerAlive = state.create( 'previewerAlive' ),
     
    50045014            processing( 0 );
    50055015            paneVisible( true );
     5016            expandedPanel( false );
     5017            expandedSection( false );
    50065018            previewerAlive( true );
    50075019            changesetStatus( api.settings.changeset.status );
     
    51575169        });
    51585170
     5171        /*
     5172         * Sticky header feature.
     5173         */
     5174        (function initStickyHeaders() {
     5175            var parentContainer = $( '.wp-full-overlay-sidebar-content' ),
     5176                changeContainer, getHeaderHeight, releaseStickyHeader, resetStickyHeader, positionStickyHeader,
     5177                activeHeader, lastScrollTop;
     5178
     5179            // Determine which panel or section is currently expanded.
     5180            changeContainer = function( container ) {
     5181                var newInstance = container,
     5182                    expandedSection = api.state( 'expandedSection' ).get(),
     5183                    expandedPanel = api.state( 'expandedPanel' ).get(),
     5184                    headerElement;
     5185
     5186                // Release previously active header element.
     5187                if ( activeHeader && activeHeader.element ) {
     5188                    releaseStickyHeader( activeHeader.element );
     5189                }
     5190
     5191                if ( ! newInstance ) {
     5192                    if ( ! expandedSection && expandedPanel && expandedPanel.contentContainer ) {
     5193                        newInstance = expandedPanel;
     5194                    } else if ( ! expandedPanel && expandedSection && expandedSection.contentContainer ) {
     5195                        newInstance = expandedSection;
     5196                    } else {
     5197                        activeHeader = false;
     5198                        return;
     5199                    }
     5200                }
     5201
     5202                headerElement = newInstance.contentContainer.find( '.customize-section-title, .panel-meta' ).first();
     5203                if ( headerElement.length ) {
     5204                    activeHeader = {
     5205                        instance: newInstance,
     5206                        element:  headerElement,
     5207                        parent:   headerElement.closest( '.customize-pane-child' ),
     5208                        height:   getHeaderHeight( headerElement )
     5209                    };
     5210                    if ( expandedSection ) {
     5211                        resetStickyHeader( activeHeader.element, activeHeader.parent );
     5212                    }
     5213                } else {
     5214                    activeHeader = false;
     5215                }
     5216            };
     5217            api.state( 'expandedSection' ).bind( changeContainer );
     5218            api.state( 'expandedPanel' ).bind( changeContainer );
     5219
     5220            // Throttled scroll event handler.
     5221            parentContainer.on( 'scroll', _.throttle( function() {
     5222                if ( ! activeHeader ) {
     5223                    return;
     5224                }
     5225
     5226                var scrollTop = parentContainer.scrollTop(),
     5227                    isScrollingUp = ( lastScrollTop ) ? scrollTop <= lastScrollTop : true;
     5228
     5229                lastScrollTop = scrollTop;
     5230                positionStickyHeader( activeHeader, scrollTop, isScrollingUp );
     5231            }, 8 ) );
     5232
     5233            // Release header element if it is sticky.
     5234            releaseStickyHeader = function( headerElement ) {
     5235                if ( ! headerElement.hasClass( 'is-sticky' ) ) {
     5236                    return;
     5237                }
     5238                headerElement
     5239                    .removeClass( 'is-sticky' )
     5240                    .addClass( 'maybe-sticky is-in-view' )
     5241                    .css( 'top', parentContainer.scrollTop() + 'px' );
     5242            };
     5243
     5244            // Reset position of the sticky header.
     5245            resetStickyHeader = function( headerElement, headerParent ) {
     5246                headerElement
     5247                    .removeClass( 'maybe-sticky is-in-view' )
     5248                    .css( {
     5249                        width: '',
     5250                        top: ''
     5251                    } );
     5252                headerParent.css( 'padding-top', '' );
     5253            };
     5254
     5255            // Get header height.
     5256            getHeaderHeight = function( headerElement ) {
     5257                var height = headerElement.data( 'height' );
     5258                if ( ! height ) {
     5259                    height = headerElement.outerHeight();
     5260                    headerElement.data( 'height', height );
     5261                }
     5262                return height;
     5263            };
     5264
     5265            // Reposition header on throttled `scroll` event.
     5266            positionStickyHeader = function( header, scrollTop, isScrollingUp ) {
     5267                var headerElement = header.element,
     5268                    headerParent = header.parent,
     5269                    headerHeight = header.height,
     5270                    headerTop = parseInt( headerElement.css( 'top' ), 10 ),
     5271                    maybeSticky = headerElement.hasClass( 'maybe-sticky' ),
     5272                    isSticky = headerElement.hasClass( 'is-sticky' ),
     5273                    isInView = headerElement.hasClass( 'is-in-view' );
     5274
     5275                // When scrolling down, gradually hide sticky header.
     5276                if ( ! isScrollingUp ) {
     5277                    if ( isSticky ) {
     5278                        headerTop = scrollTop;
     5279                        headerElement
     5280                            .removeClass( 'is-sticky' )
     5281                            .css( {
     5282                                top:   headerTop + 'px',
     5283                                width: ''
     5284                            } );
     5285                    }
     5286                    if ( isInView && scrollTop > headerTop + headerHeight ) {
     5287                        headerElement.removeClass( 'is-in-view' );
     5288                        headerParent.css( 'padding-top', '' );
     5289                    }
     5290                    return;
     5291                }
     5292
     5293                // Scrolling up.
     5294                if ( ! maybeSticky && scrollTop >= headerHeight ) {
     5295                    maybeSticky = true;
     5296                    headerElement.addClass( 'maybe-sticky' );
     5297                } else if ( 0 === scrollTop ) {
     5298                    // Reset header in base position.
     5299                    headerElement
     5300                        .removeClass( 'maybe-sticky is-in-view is-sticky' )
     5301                        .css( {
     5302                            top:   '',
     5303                            width: ''
     5304                        } );
     5305                    headerParent.css( 'padding-top', '' );
     5306                    return;
     5307                }
     5308
     5309                if ( isInView && ! isSticky ) {
     5310                    // Header is in the view but is not yet sticky.
     5311                    if ( headerTop >= scrollTop ) {
     5312                        // Header is fully visible.
     5313                        headerElement
     5314                            .addClass( 'is-sticky' )
     5315                            .css( {
     5316                                top:   '',
     5317                                width: headerParent.outerWidth() + 'px'
     5318                            } );
     5319                    }
     5320                } else if ( maybeSticky && ! isInView ) {
     5321                    // Header is out of the view.
     5322                    headerElement
     5323                        .addClass( 'is-in-view' )
     5324                        .css( 'top', ( scrollTop - headerHeight ) + 'px' );
     5325                    headerParent.css( 'padding-top', headerHeight + 'px' );
     5326                }
     5327            };
     5328        }());
     5329
    51595330        // Previewed device bindings.
    51605331        api.previewedDevice = new api.Value();
Note: See TracChangeset for help on using the changeset viewer.