Overhauled main menu
authorAlexander Ebert <ebert@woltlab.com>
Tue, 29 Mar 2016 12:17:08 +0000 (14:17 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 29 Mar 2016 12:17:19 +0000 (14:17 +0200)
com.woltlab.wcf/templates/pageHeader.tpl
wcfsetup/install/files/js/WCF.js
wcfsetup/install/files/js/WoltLab/WCF/Ui/Page/Header/Fixed.js
wcfsetup/install/files/style/bootstrap/mixin/box.scss
wcfsetup/install/files/style/layout/pageHeader.scss
wcfsetup/install/files/style/layout/pageHeaderSticky.scss
wcfsetup/install/files/style/ui/dropdownInteractive.scss

index 961efe10313c14827c67ea53d37c4b2e43b67fa8..9dd0c625264b1f77525bb3ad507802b3f3a8d867 100644 (file)
@@ -2,16 +2,13 @@
        <header id="pageHeader" class="pageHeader">
                <div>
                        <div class="layoutBoundary">
-                               <div class="pageHeaderContainerLeft">
-                                       {include file='pageHeaderLogo'}
-                                       
-                                       {include file='pageHeaderMenu'}
-                               </div>
-                               <div class="pageHeaderContainerRight">
-                                       {include file='pageHeaderSearch'}
-                                       
-                                       {include file='pageHeaderUser'}
-                               </div>
+                               {include file='pageHeaderLogo'}
+                               
+                               {include file='pageHeaderSearch'}
+                               
+                               {include file='pageHeaderMenu'}
+                               
+                               {include file='pageHeaderUser'}
                        </div>
                </div>
                
index fca070a86da87f6764849bb734d00f454564aac8..aa58bf8c1e9b0ae9cf61d7ad968cb9fb17101399 100755 (executable)
@@ -1180,6 +1180,7 @@ WCF.Dropdown.Interactive.Instance = Class.extend({
        open: function() {
                WCF.Dropdown._closeAll();
                
+               this._triggerElement.addClass('open');
                this._container.addClass('open');
                
                this.render();
@@ -1189,6 +1190,7 @@ WCF.Dropdown.Interactive.Instance = Class.extend({
         * Closes the dropdown
         */
        close: function() {
+               this._triggerElement.removeClass('open');
                this._container.removeClass('open');
        },
        
@@ -1236,6 +1238,7 @@ WCF.Dropdown.Interactive.Instance = Class.extend({
                else {
                        require(['Ui/Alignment'], (function(UiAlignment) {
                                UiAlignment.set(this._container[0], this._triggerElement[0], {
+                                       horizontal: 'right',
                                        pointer: true
                                });
                        }).bind(this));
index a0c8a437ef2e55dd888b1b87e1f6c40093a7eac1..779f1da7e0796c5bfb2fdfbd18f23472e1b7661b 100644 (file)
@@ -9,7 +9,7 @@
 define(['Core', 'EventHandler', 'Ui/CloseOverlay', 'Ui/Screen', 'Ui/SimpleDropdown'], function(Core, EventHandler, UiCloseOverlay, UiScreen, UiSimpleDropdown) {
        "use strict";
        
-       var _pageHeader, _pageHeaderContainer, _isFixed = false, _isMobile = false;
+       var _pageHeader, _pageHeaderContainer, _triggerHeight, _isFixed = false, _isMobile = false;
        
        /**
         * @exports     WoltLab/WCF/Ui/Page/Header/Fixed
@@ -41,6 +41,8 @@ define(['Core', 'EventHandler', 'Ui/CloseOverlay', 'Ui/Screen', 'Ui/SimpleDropdo
                _initStickyPageHeader: function() {
                        _pageHeader.style.setProperty('min-height', _pageHeader.clientHeight + 'px');
                        
+                       _triggerHeight = _pageHeader.clientHeight - elBySel('.mainMenu', _pageHeader).clientHeight;
+                       
                        this._scroll();
                        window.addEventListener('scroll', this._scroll.bind(this));
                },
@@ -79,7 +81,7 @@ define(['Core', 'EventHandler', 'Ui/CloseOverlay', 'Ui/Screen', 'Ui/SimpleDropdo
                 * @protected
                 */
                _scroll: function() {
-                       _isFixed = (window.scrollY > 50);
+                       _isFixed = (window.scrollY > _triggerHeight);
                        
                        _pageHeader.classList[_isFixed ? 'add' : 'remove']('sticky');
                        _pageHeaderContainer.classList[_isFixed ? 'add' : 'remove']('stickyPageHeader');
index 6f00c429803976c81208c8e8f89df3fc60f28e32..11c29f89c08f6cbfdc5d09abd218bbf1b658a467 100644 (file)
@@ -7,7 +7,7 @@
        }
        
        > :last-child {
-               flex: 1;
+               flex: 1 1 auto;
                overflow: hidden;
        }
 }
index 0ef065c4f55bae664f3ef5aa220b62d3360d4bbf..f85239a66839ad2940e69446499b2fd8f802acbf 100644 (file)
 .pageHeader .layoutBoundary {
        display: flex;
        
-       .pageHeaderContainerLeft,
-       .pageHeaderContainerRight {
-               display: flex;
-       }
-       
-       .pageHeaderContainerLeft {
-               flex: 1 1 auto;
-       }
-       
-       .pageHeaderContainerRight {
-               flex: 0 0 auto;
-       }
-       
        @include large-screen-only {
-               padding-top: 20px;
-               padding-bottom: 20px;
-               
-               .pageHeaderContainerLeft,
-               .pageHeaderContainerRight {
-                       flex-direction: column;
-                       justify-content: space-between;
-               }
+               align-items: center;
+               flex-wrap: wrap;
+               padding-top: 30px;
+               padding-bottom: 0;
        }
        
        @include small-screen-only {
        }
        
        @include large-screen-only {
-               margin-bottom: 15px;
+               flex: 0 0 50%;
+               margin-bottom: 30px;
        }
 }
 
 /* MAIN MENU */
-.mainMenu .boxMenu {
-       display: flex;
-       flex-wrap: wrap;
+.mainMenu {
+       flex: 1 1 auto;
        
-       > li {
-               flex: 0 0 auto;
-               
-               @include wcfFontHeadline;
-               
-               &:not(:last-child) {
-                       margin-right: 15px;
-               }
+       .boxMenu {
+               display: flex;
+               flex-wrap: wrap;
                
-               > a {
-                       border-bottom: 3px solid $wcfHeaderMenuBackground;
-                       color: $wcfHeaderMenuLink;
-                       display: block;
-                       font-size: 16px;
-                       font-weight: 400;
-                       padding: 5px 0 2px;
+               > li {
+                       flex: 0 0 auto;
                        
-                       > .boxMenuLinkOutstandingItems {
-                               background-color: rgb(255, 255, 255);
-                               color: rgb(192, 57, 43);
+                       > a {
+                               align-items: center;
+                               color: $wcfHeaderMenuLink;
+                               display: flex;
+                               height: 50px;
+                               padding: 0 10px;
+                               
+                               > span {
+                                       flex: 0 0 auto;
+                               }
+                               
+                               > .boxMenuLinkOutstandingItems {
+                                       background-color: rgb(255, 255, 255);
+                                       color: rgb(192, 57, 43);
+                               }
+                       }
+                       
+                       > span {
+                               cursor: default;
+                       }
+                       
+                       &.active > a {
+                               background: linear-gradient(to top, $wcfHeaderMenuBackground 0%, $wcfHeaderMenuBackgroundActive 50%);
+                               color: $wcfHeaderMenuLinkActive;
+                       }
+                       
+                       &:hover > a {
+                               background: $wcfHeaderMenuBackgroundActive;
+                               color: $wcfHeaderMenuLinkActive;
                        }
                }
                
-               > span {
-                       cursor: default;
-               }
-               
-               &.active > a,
-               &:hover > a {
-                       border-color: $wcfHeaderMenuBackgroundActive;
-                       color: $wcfHeaderMenuLinkActive;
-               }
-       }
-       
-       > .boxMenuHasChildren {
-               position: relative;
-               
-               &:hover .boxMenuDepth1 {
-                       visibility: visible;
-               }
-       }
-       
-       .boxMenuDepth1 {
-               background-color: $wcfHeaderMenuDropdownBackground;
-               position: absolute;
-               visibility: hidden;
-               
-               // align menu to the center of the menu item
-               left: 50%;
-               transform: translateX(-50%);
-               
-               // offset the menu to prevent the staircase effect when two elements with dark and light
-               // colors are right below each other; uses a transparent border rather than a margin to
-               // prevent losing the hover on the <li> causing the menu to collapse when the cursor is
-               // right between the menu item and the menu itself
-               background-clip: padding-box;
-               border-top: 15px solid transparent;
-               
-               @include wcfFontDefault;
-               
-               &::before {
-                       content: "";
-                       border: 10px solid transparent;
-                       border-bottom-color: $wcfHeaderMenuDropdownBorder;
-                       border-top-width: 0;
-                       left: calc(50% - 10px);
-                       position: absolute;
-                       top: -10px;
-               }
-               
-               &::after {
-                       content: "";
-                       border: 10px solid transparent;
-                       border-bottom-color: $wcfHeaderMenuDropdownBackground;
-                       border-top-width: 0;
-                       left: calc(50% - 10px);
-                       position: absolute;
-                       top: -9px;
+               > .boxMenuHasChildren {
+                       position: relative;
+                       
+                       &:hover .boxMenuDepth1 {
+                               visibility: visible;
+                       }
                }
                
-               > li {
-                       // the code below mimics the border surrounding the list element
-                       // as seen for similar elements such as dropdowns; we cannot use
-                       // the list border because the top border is abused to visually
-                       // push down the list w/o triggering a "hover-out" on the menu item
+               .boxMenuDepth1 {
                        background-color: $wcfHeaderMenuDropdownBackground;
-                       border: 1px solid $wcfHeaderMenuDropdownBorder;
-                       border-width: 0 1px;
+                       padding: 5px 0;
+                       position: absolute;
+                       visibility: hidden;
                        
-                       &:first-child {
-                               border-top-width: 1px;
-                               padding-top: 3px;
-                       }
+                       @include wcfFontDefault;
                        
-                       &:last-child {
-                               border-bottom-width: 1px;
-                               padding-bottom: 3px;
+                       > li {
+                               
+                               > a {
+                                       color: $wcfHeaderMenuDropdownLink;
+                               }
+                               
+                               > a,
+                               > span {
+                                       display: block;
+                                       padding: 7px 20px;
+                                       white-space: nowrap;
+                               }
+                               
+                               &.active > a,
+                               > a:hover {
+                                       background-color: $wcfHeaderMenuDropdownBackgroundActive;
+                                       color: $wcfHeaderMenuDropdownLinkActive;
+                                       text-decoration: none;
+                               }
                        }
-                       
+               }
+               
+               .boxMenuDepth2 > li {
                        > a {
                                color: $wcfHeaderMenuDropdownLink;
-                       }
-                       
-                       > a,
-                       > span {
                                display: block;
-                               padding: 7px 20px;
+                               padding: 5px 20px 5px 40px;
                                white-space: nowrap;
                        }
                        
                        }
                }
        }
-       
-       .boxMenuDepth2 > li {
-               > a {
-                       color: $wcfHeaderMenuDropdownLink;
-                       display: block;
-                       padding: 5px 20px 5px 40px;
-                       white-space: nowrap;
-               }
+}
+
+@include large-screen-only {
+       .pageHeader:not(.sticky) .mainMenu {
+               background-color: $wcfHeaderMenuBackground;
+               position: relative;
                
-               &.active > a,
-               > a:hover {
-                       background-color: $wcfHeaderMenuDropdownBackgroundActive;
-                       color: $wcfHeaderMenuDropdownLinkActive;
-                       text-decoration: none;
+               /* The `box-shadow` and the `::before` are used to create a full-width
+                  color stripe that matches the height of the main menu. This trick is
+                  used to allows us to have all elements in the header share a common
+                  ancestor in order to easily move elements with flexbox' `order` property.
+                  
+                  The `box-shadow` is a neat hack because an `::after` element would
+                  increase the page width unless we set `overflow: hidden` to the entire
+                  page header which is bad for multiple reasons. */
+               box-shadow: 900px 0 0 0 $wcfHeaderMenuBackground;
+               
+               &::before {
+                       background-color: $wcfHeaderMenuBackground;
+                       bottom: 0;
+                       content: "";
+                       left: -100%;
+                       position: absolute;
+                       top: 0;
+                       width: 100%;
                }
        }
 }
 
 /* user panel */
-.userPanel  > ul {
-       display: flex;
-       justify-content: flex-end;
+.userPanel {
+       flex: 0 0 auto;
        
-       > li {
-               align-items: center;
+       > ul {
                display: flex;
-               flex: 0 auto;
-               
-               /* margin between items, do not use the inner elements (such as a contained <a>) for
-                  this as it causes the last item to be of uneven size compared to all other items */
-               margin-left: 10px;
-               
-               &:not(:last-child) {
-                       margin-right: 10px;
-               }
+               justify-content: flex-end;
                
-               > a {
+               > li {
+                       align-items: center;
+                       display: flex;
                        flex: 0 auto;
-                       position: relative;
                        
-                       /* set icon color */
-                       > .icon {
-                               color: $wcfHeaderLink;
-                       }
-                       &:hover {
+                       > a {
+                               align-items: center;
+                               color: $wcfHeaderMenuLink;
+                               display: flex;
+                               flex: 0 0 auto;
+                               height: 50px;
+                               padding: 0 10px;
+                               position: relative;
+                               
+                               /* set icon color */
                                > .icon {
-                                       color: $wcfHeaderLinkActive;
+                                       color: inherit;
+                               }
+                               
+                               /* hide icon label */
+                               > span:not(.icon):not(.badge) {
+                                       display: none;
+                               }
+                               
+                               /* special styling for update badge */
+                               > span.badgeUpdate {
+                                       box-shadow: -1px 2px 3px rgba(0, 0, 0, .3), inset 0 2px 5px rgba(225, 225, 225, .3);
+                                       left: 16px;
+                                       position: absolute;
+                                       top: -5px;
                                }
                        }
                        
-                       /* hide icon label */
-                       > span:not(.icon):not(.badge) {
-                               display: none;
+                       &.open > a {
+                               background: linear-gradient(to top, $wcfHeaderMenuBackground 0%, $wcfHeaderMenuBackgroundActive 50%);
+                               color: $wcfHeaderMenuLinkActive;
                        }
                        
-                       /* special styling for update badge */
-                       > span.badgeUpdate {
-                               box-shadow: -1px 2px 3px rgba(0, 0, 0, .3), inset 0 2px 5px rgba(225, 225, 225, .3);
-                               left: 16px;
-                               position: absolute;
-                               top: -5px;
+                       &:hover > a {
+                               background: $wcfHeaderMenuBackgroundActive;
+                               color: $wcfHeaderMenuLinkActive;
                        }
-               }
-               
-               /* ringing animation for notification icon */
-               &#userNotifications:not([data-count="0"]) { 
-                       > a > .icon {
-                               animation: fa-bell-ring 5s ease 10s 6;
-                               transform-origin: 50% 0;
-                       }
-               }
-               
-               /* hover effect for user menu button */
-               &#userMenu {
-                       > a {
-                               &:hover {
-                                       > img {
-                                               box-shadow: 0 0 0 2px $wcfHeaderLink;
-                                       }
+                       
+                       /* ringing animation for notification icon */
+                       &#userNotifications:not([data-count="0"]) {
+                               > a > .icon {
+                                       animation: fa-bell-ring 5s ease 10s 6;
+                                       transform-origin: 50% 0;
                                }
                        }
                }
 /* SEARCH AREA */
 .pageHeaderSearch {
        @include large-screen-only {
-               margin-bottom: 15px;
+               align-self: flex-start;
+               flex: 0 0 50%;
+               margin-bottom: 30px;
                text-align: right;
                
                .pageHeaderSearchLabel {
index 64e5b427f10d5e1d47b6e74435496c8cdd655e2e..b0ec7b72132511882a1d4c8c2d01ec74edad10ce 100644 (file)
@@ -9,10 +9,8 @@
        }
        
        .pageHeader.sticky {
-               flex-wrap: nowrap;
-               
                > div {
-                       background-color: $wcfHeaderBackground;
+                       background-color: $wcfHeaderMenuBackground;
                        box-shadow: 0 0 10px rgba(0, 0, 0, .6);
                        left: 0;
                        position: fixed;
@@ -23,6 +21,7 @@
                
                
                .layoutBoundary {
+                       flex-wrap: nowrap;
                        min-height: 50px;
                        
                        // remove padding, the vertical alignment is done using `align-items`
@@ -43,6 +42,8 @@
                }
                
                .pageHeaderLogo {
+                       display: none;
+                       flex: 0 0 auto;
                        margin-bottom: 0;
                        order: 1;
                        
                }
                
                .mainMenu {
+                       flex: 1 1 auto;
+                       margin-right: 20px;
                        order: 2;
-                       margin: 0 20px;
                        
                        .boxMenu {
-                               background-color: $wcfHeaderBackground;
-                               padding-bottom: 5px;
-                               
                                > li > a {
                                        align-items: center;
                                        display: flex;
                }
                
                .userPanel {
+                       flex: 0 0 auto;
                        margin-left: 10px;
                        order: 4;
                }
                
                .pageHeaderSearch {
+                       flex: 0 0 auto;
                        margin-bottom: 0;
                        order: 3;
                        
index 97bdcf199f7b5203025d906bfd1503791d24832e..df2daf285e516a9c81d263ab6c10993720192877 100644 (file)
@@ -38,7 +38,7 @@
                }
                
                &.left {
-                       left: 5px;
+                       left: 15px;
                        
                        > span {
                                left: -10px;
@@ -46,7 +46,7 @@
                }
                
                &.right {
-                       right: 5px;
+                       right: 15px;
                        
                        > span {
                                right: -10px;