diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 36dd6e78ed..acdeaf17fd 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -97,7 +97,7 @@ * to be more flexible / relative */ #body-user .app-files #controls { - left: 310px; /* main nav bar + sidebar */ + left: 230px; /* sidebar width */ position: fixed; padding-left: 0px; } diff --git a/core/css/header.css b/core/css/header.css new file mode 100644 index 0000000000..83612c6744 --- /dev/null +++ b/core/css/header.css @@ -0,0 +1,293 @@ +/* prevent ugly selection effect on accidental selection */ +#header, +#navigation, +#expanddiv { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} + + + +/* HEADERS ------------------------------------------------------------------ */ + +#body-user #header, +#body-settings #header, +#body-public #header { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 100; + height: 45px; + line-height: 2.5em; + background-color: #1d2d44; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + + + +/* LOGO and APP NAME -------------------------------------------------------- */ + +#owncloud { + position: absolute; + top: 0; + left: 0; + padding: 6px; + padding-bottom: 0; + height: 45px; /* header height */ + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +#header .logo { + background-image: url(../img/logo.svg); + background-repeat: no-repeat; + width: 250px; + height: 118px; + margin: 0 auto; +} + +#header .logo-wide { + background-image: url(../img/logo-wide.svg); + background-repeat: no-repeat; + width: 147px; + height: 32px; +} + +#header .logo-icon { + /* display logo so appname can be shown next to it */ + display: inline-block; + background-image: url(../img/logo-icon.svg); + background-repeat: no-repeat; + width: 60px; + height: 32px; +} + +#header .menutoggle { + display: inline-block; + position: absolute; + left: 70px; + height: 27px; + padding-top: 18px; + padding-right: 10px; +} + +/* hover effect for app switcher label */ +.menutoggle .header-appname, +.menutoggle .icon-caret { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=75)"; + filter: alpha(opacity=75); + opacity: .75; +} +.menutoggle:hover .header-appname, +.menutoggle:hover .icon-caret, +.menutoggle:focus .header-appname +.menutoggle:focus .icon-caret +.menutoggle.active .header-appname +.menutoggle.active .icon-caret { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); + opacity: 1; +} + +/* show appname next to logo */ +.header-appname { + display: inline-block; + position: relative; + color: #fff; + font-size: 16px; + margin: 0; + margin-top: -24px; + padding: 7px 0 7px 5px; + vertical-align: middle; +} +/* show caret indicator next to logo to make clear it is tappable */ +#header .icon-caret { + display: inline-block; + width: 12px; + height: 12px; + margin: 0; + margin-top: -21px; + padding: 0; + vertical-align: middle; +} +/* do not show menu toggle on public share links as there is no menu */ +#body-public #header .icon-caret { + display: none; +} + + + +/* NAVIGATION --------------------------------------------------------------- */ + +#content-wrapper { + padding-left: 0; +} + +#navigation { + position: fixed; + top: 45px; + width: 265px; + max-height: 85%; + margin-top: 0; + padding-bottom: 10px; + background-color: rgba(36, 40, 47, .97); + border-bottom-right-radius: 7px; + box-shadow: 0 0 7px rgba(29,45,68,.97); + display: none; + overflow-y: auto; + overflow-x: hidden; + z-index: 150; +} +#navigation, #navigation * { + -moz-box-sizing:border-box; + box-sizing:border-box; +} +#navigation li { + display: inline-block; +} +#navigation a { + position: relative; + width: 80px; + height: 80px; + display: inline-block; + text-align: center; + padding: 20px 0; +} +#navigation a span { + display: inline-block; + font-size: 13px; + padding-bottom: 0; + padding-left: 0; + width: 80px; + text-align: center; + color: #fff; + white-space:nowrap; + overflow:hidden; + text-overflow:ellipsis; +} + /* icon opacity and hover effect */ + #navigation a img, + #navigation a span { + /* 50% opacity when inactive */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; + filter: alpha(opacity=50); + opacity: .5; + } + #navigation a:hover img, #navigation a:focus img, + #navigation a:hover span, #navigation a:focus span { + /* 80% opacity when hovered or focused */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; + filter: alpha(opacity=80); + opacity: .8; + } + #navigation a.active img, + #navigation a.active span { + /* full opacity for the active app */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); + opacity: 1; + } + +#navigation .app-icon { + margin: 0 auto; + padding: 0; +} + +/* Apps management */ +#apps-management { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; + filter: alpha(opacity=60); + opacity: .6; + min-height: initial; + height: initial; + margin: 0; +} + + +/* loading feedback for apps */ +#navigation .app-loading .icon-loading-dark { + display: inline !important; + position: absolute; + top: 20px; + left: 24px; + width: 32px; + height: 32px; +} +#navigation .app-loading .app-icon { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; + filter: alpha(opacity=10); + opacity: .1; +} + + + + +/* USER MENU -----------------------------------------------------------------*/ + +/* info part on the right, used e.g. for info on who shared something */ +.header-right { + position: absolute; + right: 0; + padding: 7px 5px; + color: #fff; + height: 100%; + max-width: 40%; + white-space: nowrap; +} + +/* Profile picture in header */ +#header .avatardiv { + float: left; + display: inline-block; + margin-right: 5px; +} +#header .avatardiv img { + opacity: 1; +} + +#settings { + float: right; + color: #bbb; +} +#expand { + display: block; + padding: 7px 12px 6px 7px; + cursor: pointer; +} +#expand:hover, #expand:focus, #expand:active { color:#fff; } +#expand img { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; margin-bottom:-2px; } +#expand:hover img, #expand:focus img, #expand:active img { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; } +#expanddiv { + position: absolute; + right: 0; + top: 45px; + z-index: 150; + display: none; + background-color: #383c43; + border-bottom-left-radius:7px; border-bottom:1px #333 solid; border-left:1px #333 solid; + box-shadow:0 0 7px rgb(29,45,68); + -moz-box-sizing: border-box; box-sizing: border-box; +} + #expanddiv a { + display: block; + height: 40px; + color: #fff; + padding: 4px 12px 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; + filter: alpha(opacity=70); + opacity: .7; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + #expanddiv a img { + margin-bottom: -3px; + margin-right: 6px; + } + #expanddiv a:hover, #expanddiv a:focus, #expanddiv a:active { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); + opacity: 1; + } diff --git a/core/css/mobile.css b/core/css/mobile.css index 025bee6415..9cea0dddc8 100644 --- a/core/css/mobile.css +++ b/core/css/mobile.css @@ -21,19 +21,6 @@ box-align: center; } -/* show caret indicator next to logo to make clear it is tappable */ -#owncloud.menutoggle { - background-image: url('../img/actions/caret.svg'); - background-repeat: no-repeat; - background-position: right 26px; - padding-right: 16px !important; -} -/* do not show menu toggle on public share links as there is no menu */ -#body-public #owncloud.menutoggle { - background-image: none; - padding-right: 0 !important; -} - /* compress search box on mobile, expand when focused */ .searchbox input[type="search"] { width: 15%; @@ -53,73 +40,6 @@ display: none; } -/* toggle navigation */ -#content-wrapper { - padding-left: 0; -} - -#navigation { - top: 45px; - bottom: initial; - width: 255px; - max-height: 90%; - margin-top: 0; - top: 45px; - background-color: rgba(36, 40, 47, .97); - overflow-x: initial; - border-bottom-right-radius: 7px; - border-bottom: 1px #333 solid; - border-right: 1px #333 solid; - box-shadow: 0 0 7px rgba(29,45,68,.97); - display: none; -} -#navigation, #navigation * { - box-sizing:border-box; -moz-box-sizing:border-box; -} -#navigation li { - display: inline-block; -} -#navigation a { - width: 80px; - height: 80px; - display: inline-block; - text-align: center; - padding: 20px 0; -} -#navigation a span { - display: inline-block; - font-size: 13px; - padding-bottom: 0; - padding-left: 0; - width: 80px; -} -#navigation .icon { - margin: 0 auto; - padding: 0; -} -#navigation li:first-child .icon { - padding-top: 0; -} -/* Apps management as sticky footer */ -#navigation .wrapper { - min-height: initial; - margin: 0; -} -#apps-management, #navigation .push { - height: initial; -} - - - -/* shift to account for missing app list */ -#body-user #controls, -#body-settings #controls { - padding-left: 0; -} -#body-user .app-files #controls { - left: 230px !important; /* sidebar only */ -} - /* don’t require a minimum width for controls bar */ #controls { min-width: initial !important; diff --git a/core/css/styles.css b/core/css/styles.css index 595b553267..6eb09e6e94 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -24,23 +24,6 @@ body { height: auto; } - -/* HEADERS */ -#body-user #header, -#body-settings #header, -#body-public #header { - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 100; - height: 45px; - line-height: 2.5em; - background-color: #1d2d44; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - #body-login { text-align: center; background: #1d2d44; /* Old browsers */ @@ -53,34 +36,7 @@ body { filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#35537a', endColorstr='#1d2d44',GradientType=0 ); /* IE6-9 */ } -#owncloud { - position: absolute; - top: 0; - left: 0; - padding: 6px; - padding-bottom: 0; -} -/* info part on the right, used e.g. for info on who shared something */ -.header-right { - position: absolute; - right: 0; - padding: 7px 5px; - color: #fff; - height: 100%; - max-width: 40%; - white-space: nowrap; -} - -/* Profile picture in header */ -#header .avatardiv { - float: left; - display: inline-block; - margin-right: 5px; -} -#header .avatardiv img { - opacity: 1; -} #nojavascript { position: absolute; @@ -110,20 +66,6 @@ body { color: #aaa; } -#header .logo { - background-image: url(../img/logo.svg); - background-repeat: no-repeat; - width: 250px; - height: 118px; - margin: 0 auto; -} - -#header .logo-wide { - background-image: url(../img/logo-wide.svg); - background-repeat: no-repeat; - width: 147px; - height: 32px; -} /* INPUTS */ input[type="text"], @@ -207,16 +149,6 @@ input img, button img, .button img { } -/* prevent ugly selection effect on accidental selection */ -#header, -#navigation, -#expanddiv { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - - /* SCROLLING */ ::-webkit-scrollbar { width: 8px; @@ -234,6 +166,7 @@ input[type="submit"], input[type="button"], button, .button, #quota, select, .pager li a { width: auto; + min-width: 25px; padding: 5px; background-color: rgba(240,240,240,.9); font-weight: bold; @@ -321,11 +254,6 @@ input[type="submit"].enabled { border-bottom: 1px solid #e7e7e7; z-index: 50; } -/* account for shift of controls bar due to app navigation */ -#body-user #controls, -#body-settings #controls { - padding-left: 80px; -} #controls .button, #controls button, #controls input[type='submit'], @@ -713,131 +641,6 @@ label.infield { -/* NAVIGATION ------------------------------------------------------------- */ -#navigation { - position: fixed; - top: 0; - bottom: 0; - left: 0; - width: 80px; - margin-top:45px; - z-index: 75; - background-color: #383c43; - overflow-y: auto; - overflow-x: hidden; - -moz-box-sizing:border-box; box-sizing:border-box; -} -#apps { - height: 100%; -} -#navigation a span { - display: block; - text-decoration: none; - font-size: 11px; - text-align: center; - color: #fff; - white-space:nowrap; overflow:hidden; text-overflow:ellipsis; /* ellipsize long app names */ - padding-bottom: 10px; - /* prevent shift caused by scrollbar */ - padding-left: 8px; - width: 64px; -} - - /* icon opacity and hover effect */ - #navigation a img, - #navigation a span { - /* 50% opacity when inactive */ - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; - filter: alpha(opacity=50); - opacity: .5; - } - #navigation a:hover img, #navigation a:focus img, - #navigation a:hover span, #navigation a:focus span { - /* 80% opacity when hovered or focused */ - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; - filter: alpha(opacity=80); - opacity: .8; - } - #navigation a.active img, - #navigation a.active span { - /* full opacity for the active app */ - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter: alpha(opacity=100); - opacity: 1; - } - #navigation .icon { - display: block; - width: 32px; - height: 32px; - margin-left: 24px; - padding: 10px 0 4px; - } - #navigation li:first-child .icon { /* special rule for Files icon as it's first */ - padding-top: 20px; - } - -/* Apps management as sticky footer, less obtrusive in the list */ -#navigation .wrapper { - min-height: 100%; - margin: 0 auto -82px 0; -} -#apps-management, #navigation .push { - height: 72px; -} -#apps-management { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; - filter: alpha(opacity=60); - opacity: .6; -} -#apps-management .icon { - padding-bottom: 0; -} - - - - -/* USER MENU */ -#settings { - float: right; - color: #bbb; -} -#expand { - display: block; - padding: 7px 12px 6px 7px; - cursor: pointer; -} -#expand:hover, #expand:focus, #expand:active { color:#fff; } -#expand img { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; margin-bottom:-2px; } -#expand:hover img, #expand:focus img, #expand:active img { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; } -#expanddiv { - position:absolute; right:0; top:45px; z-index:76; display:none; - background-color: #383c43; - border-bottom-left-radius:7px; border-bottom:1px #333 solid; border-left:1px #333 solid; - box-shadow:0 0 7px rgb(29,45,68); - -moz-box-sizing: border-box; box-sizing: border-box; -} - #expanddiv a { - display: block; - height: 40px; - color: #fff; - padding: 4px 12px 0; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; - filter: alpha(opacity=70); - opacity: .7; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - #expanddiv a img { - margin-bottom: -3px; - margin-right: 6px; - } - #expanddiv a:hover, #expanddiv a:focus, #expanddiv a:active { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter: alpha(opacity=100); - opacity: 1; - } - - /* VARIOUS REUSABLE SELECTORS */ .hidden { display:none; } .bold { font-weight:bold; } diff --git a/core/img/logo-icon.png b/core/img/logo-icon.png new file mode 100644 index 0000000000..26ed8b4641 Binary files /dev/null and b/core/img/logo-icon.png differ diff --git a/core/img/logo-icon.svg b/core/img/logo-icon.svg new file mode 100644 index 0000000000..05b467e87a --- /dev/null +++ b/core/img/logo-icon.svg @@ -0,0 +1,51 @@ + +image/svg+xml \ No newline at end of file diff --git a/core/js/js.js b/core/js/js.js index 834916b2e3..b3cefa83be 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -533,7 +533,6 @@ var OC={ */ registerMenu: function($toggle, $menuEl) { $menuEl.addClass('menu'); - $toggle.addClass('menutoggle'); $toggle.on('click.menu', function(event) { if ($menuEl.is(OC._currentMenu)) { $menuEl.slideUp(OC.menuSpeed); @@ -1111,45 +1110,27 @@ function initCore() { * If the screen is bigger, the main menu is not a toggle any more. */ function setupMainMenu() { - // toggle the navigation on mobile - if (!OC._matchMedia) { - return; - } - var mq = OC._matchMedia('(max-width: 768px)'); - var lastMatch = mq.matches; - var $toggle = $('#header #owncloud'); + // toggle the navigation + var $toggle = $('#header .menutoggle'); var $navigation = $('#navigation'); - function updateMainMenu() { - // mobile mode ? - if (lastMatch && !$toggle.hasClass('menutoggle')) { - // init the menu - OC.registerMenu($toggle, $navigation); - $toggle.data('oldhref', $toggle.attr('href')); - $toggle.attr('href', '#'); - $navigation.hide(); - } - else { - OC.unregisterMenu($toggle, $navigation); - $toggle.attr('href', $toggle.data('oldhref')); - $navigation.show(); - } - } + // init the menu + OC.registerMenu($toggle, $navigation); + $toggle.data('oldhref', $toggle.attr('href')); + $toggle.attr('href', '#'); + $navigation.hide(); - updateMainMenu(); - - // TODO: debounce this - $(window).resize(function() { - if (lastMatch !== mq.matches) { - lastMatch = mq.matches; - updateMainMenu(); + // show loading feedback + $navigation.delegate('a', 'click', function(event) { + var $app = $(event.target); + if(!$app.is('a')) { + $app = $app.closest('a'); } + $app.addClass('app-loading'); }); } - if (window.matchMedia) { - setupMainMenu(); - } + setupMainMenu(); } $(document).ready(initCore); diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index 37b5ceeec9..3c62b97677 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -356,62 +356,28 @@ describe('Core base tests', function() { }); }); describe('Main menu mobile toggle', function() { - var oldMatchMedia; + var clock; var $toggle; var $navigation; var clock; beforeEach(function() { clock = sinon.useFakeTimers(); - oldMatchMedia = OC._matchMedia; - // a separate method was needed because window.matchMedia - // cannot be stubbed due to a bug in PhantomJS: - // https://github.com/ariya/phantomjs/issues/12069 - OC._matchMedia = sinon.stub(); $('#testArea').append('' + ''); - $toggle = $('#owncloud'); + $toggle = $('#header').find('.menutoggle'); $navigation = $('#navigation'); }); - afterEach(function() { - OC._matchMedia = oldMatchMedia; clock.restore(); }); - it('Sets up menu toggle in mobile mode', function() { - OC._matchMedia.returns({matches: true}); + it('Sets up menu toggle', function() { window.initCore(); - expect($toggle.hasClass('menutoggle')).toEqual(true); expect($navigation.hasClass('menu')).toEqual(true); }); - it('Does not set up menu toggle in desktop mode', function() { - OC._matchMedia.returns({matches: false}); - window.initCore(); - expect($toggle.hasClass('menutoggle')).toEqual(false); - expect($navigation.hasClass('menu')).toEqual(false); - }); - it('Switches on menu toggle when mobile mode changes', function() { - var mq = {matches: false}; - OC._matchMedia.returns(mq); - window.initCore(); - expect($toggle.hasClass('menutoggle')).toEqual(false); - mq.matches = true; - $(window).trigger('resize'); - expect($toggle.hasClass('menutoggle')).toEqual(true); - }); - it('Switches off menu toggle when mobile mode changes', function() { - var mq = {matches: true}; - OC._matchMedia.returns(mq); - window.initCore(); - expect($toggle.hasClass('menutoggle')).toEqual(true); - mq.matches = false; - $(window).trigger('resize'); - expect($toggle.hasClass('menutoggle')).toEqual(false); - }); - it('Clicking menu toggle toggles navigation in mobile mode', function() { - OC._matchMedia.returns({matches: true}); + it('Clicking menu toggle toggles navigation in', function() { window.initCore(); $navigation.hide(); // normally done through media query triggered CSS expect($navigation.is(':visible')).toEqual(false); @@ -422,49 +388,6 @@ describe('Core base tests', function() { clock.tick(1 * 1000); expect($navigation.is(':visible')).toEqual(false); }); - it('Clicking menu toggle does not toggle navigation in desktop mode', function() { - OC._matchMedia.returns({matches: false}); - window.initCore(); - expect($navigation.is(':visible')).toEqual(true); - $toggle.click(); - expect($navigation.is(':visible')).toEqual(true); - }); - it('Switching to mobile mode hides navigation', function() { - var mq = {matches: false}; - OC._matchMedia.returns(mq); - window.initCore(); - expect($navigation.is(':visible')).toEqual(true); - mq.matches = true; - $(window).trigger('resize'); - expect($navigation.is(':visible')).toEqual(false); - }); - it('Switching to desktop mode shows navigation', function() { - var mq = {matches: true}; - OC._matchMedia.returns(mq); - window.initCore(); - expect($navigation.is(':visible')).toEqual(false); - mq.matches = false; - $(window).trigger('resize'); - expect($navigation.is(':visible')).toEqual(true); - }); - it('Switch to desktop with opened menu then back to mobile resets toggle', function() { - var mq = {matches: true}; - OC._matchMedia.returns(mq); - window.initCore(); - expect($navigation.is(':visible')).toEqual(false); - $toggle.click(); - clock.tick(1 * 1000); - expect($navigation.is(':visible')).toEqual(true); - mq.matches = false; - $(window).trigger('resize'); - expect($navigation.is(':visible')).toEqual(true); - mq.matches = true; - $(window).trigger('resize'); - expect($navigation.is(':visible')).toEqual(false); - $toggle.click(); - clock.tick(1 * 1000); - expect($navigation.is(':visible')).toEqual(true); - }); }); describe('SVG extension replacement', function() { var svgSupportStub; diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index d551c53521..e39bb94ed9 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -46,7 +46,13 @@